Биткойн в клетке?

Так сложилось, что я по профессии администратор компьютерных систем и сетей (короче: сисадмин), и довелось поведать за немногим более чем 10 лет проф. дейтельности самых разных систем, включая тех, что требуют [по|за]вышенных мер безопасноти. А еще сложилось, что некоторое время назад я нашёл для себя интересным биткойн, и не просто им попользовался, но и запустил несколько микро-сервисов, для того что бы научиться самостоятельно работать с сетью биткойна (он же p2p как никак) с точки зрения разработчкика (я конечно такой себе dev, так, мимо проходил). Но я не про разработку, я про безопасное и эффективное окружение для приложений.

Финансовые технологии (fintech) идут рядом с информационной безопасностью (infosec) и первое без второго работать может, но недолго. Вот поэтому я хочу поделиться своим опытом и набором инструментов что я использую, который включает в себя как fintech, так и infosec, причем одновременно, а так же может быть использован и в более широком или совсем другом назначении. В этой статье расскажу не столько про биткойн, сколько про модель инфраструктуры для разработки и эксплуатации финансовых (и не только) сервисов — одним словом тех сервисов, где «Б» имеет значение. Применимо это как к биткойновой бирже, так и к самому типовому корпоративному зоопарку сервисов небольшой компании с биткойном никак не связанной.

Хочу отметить, что я сторонник приципов «keep it stupid simple» и «less is more», поэтому как статья, так и описанное в ней будет обладать свойствами о которых эти принципы.

Воображаемый сценарий: Давайте разберём всё на примере биткойнового обменника. Мы решили запустить обмен рублей, долларов, евро на биткойны и обратно, и у нас уже есть работающее решение, но для других цифровых денег вроде киви и webmoney, т.е. у нас закрыты все юридические вопросы, имеется готовое приложение которое выполняет роль платёжного шлюза для рублей, долларов и евро и других платежных систем. Завязано с нашими банковскими счетами и имеет некое API для наших конечных приложений. Так же у нас есть веб-приложение, выполняющее роль обменника для пользователей, ну вроде типичного киви или webmoney кабинета — заведите аккаунт, добавьте карту и так далее. Оно общается с нашим приложением-шлюзом, пусть по REST API в локалке. И вот мы решили подключить биткойны и заодно проапгрейдить инфраструктуру, т.к. изначально все было в спешке поднято на виртуалбоксах в офисе под столом… сайтом стали пользоваться, а мы стали переживать за аптайм и производительность.

Итак, начнём с основного — выбор сервера. Т.к. бизнес в нашем примере маленький и мы доверяем хостеру (OVH) мы выберем бюджетный вариант в котором нельзя установить систему из оригинального образа .iso, но не беда, отдел ИТ-безопасности обязательно проведёт анализ установленого образа. А когда вырастем, так вообще арендуем свой шкаф под замком и ограниченым физическим доступом, а может и свой ДЦ построим. В любом случае, стоит помнить, что при аренде железа и установке готовых образов есть шанс что у вас в системе будет висеть «троян от хостера», который в большинстве случаев предназначен не для слежки за вами а для того что бы предложить более удобные инструменты управления сервером.

Установка сервера

Здесь всё просто. Выбираем железо которое подходит нашим нуждам. Затем выбираем образ FreeBSD. Ну или подключаемся (в случае другого хостера и своего железа) по IPMI или с монитором и скармливаем в загрузку .iso FreeBSD образа. Для оркестральной установки я использую Ansible и mfsbsd. Единственное, в нашем случае с kimsufi, мы выбрали custom installation для того, что бы два диска в зеркале имели «открытые» только загрузочную и /home партиции, остальное пространство диска будет зашифровано, но об этом позже.

Установка системы происходит стандартным способом, я не буду на этом останавливаться, лишь отмечу, что перед началом эксплуатации стоит обратить внимание на hardening опции, что предлагает bsdinstaller в конце установки (если вы сами ставите систему):

Есть хороший материал по этой теме, вкратце я тут его повторю.

Включить вышупомянутые параметры возможно так же и на уже установленной системе. Для этого нужно отредактировать файл загрузчика и включить параметры ядра. *ee — это редактор такой в BSD

# ee /etc/rc.conf


#sec hard
clear_tmp_enable=»YES»
syslogd_flags=»-ss»
sendmail_enable=»NONE»

# ee /etc/sysctl.conf


#sec hard
security.bsd.see_other_uids=0
security.bsd.see_other_gids=0
security.bsd.unprivileged_read_msgbuf=0
security.bsd.unprivileged_proc_debug=0
kern.randompid=$(jot -r 1 9999)
security.bsd.stack_guard_page=1

Так же стоит убедится, что у вас установлена последняя версия системы, и выполнить все апдейты и апгрейды. В нашем случае, например, требуется апгрейд до последней версии, т.к. предустановочные образы отстают на полгода-год. Ну и там меняем SSH порт на отличный от по-молчанию, добавляем аутентификацию по ключам и отключаем по паролю.

Затем настраиваем aide, мониторинг состояния конфигурационных файлов системы. Более разжёвано можно почитать тут.

pkg install aide

и редактируем наш кронтаб

crontab -e

06 01 * * 0-6 /root/chkaide.sh

#! /bin/sh
#chkaide.sh
MYDATE=`date +%Y-%m-%d`
MYFILENAME=»Aide-«$MYDATE.txt
/bin/echo «Aide check !! `date`» > /tmp/$MYFILENAME
/usr/local/bin/aide —check > /tmp/myAide.txt
/bin/cat /tmp/myAide.txt|/usr/bin/grep -v failed >> /tmp/$MYFILENAME
/bin/echo «**************************************» >> /tmp/$MYFILENAME
/usr/bin/tail -20 /tmp/myAide.txt >> /tmp/$MYFILENAME
/bin/echo «****************DONE******************» >> /tmp/$MYFILENAME

Включаем системное аудитирование

sysrc auditd_enable=YES

# service auditd start

Как это дело администрировать отлично описано в руководстве.

Теперь перезагружаемся и приступаем к софту на сервере. Каждый сервер представляет из себя гипервизор для контейнеров или полных виртуальных машин. Поэтому важно, что бы процессор поддерживал VT-x и EPT если мы планируем использовать полную виртуализацию.

В качестве менеджмента контейнеров и виртуальных машин я использую cbsd от olevole, желаю побольше ему здоровья и благ за эту прекрасную утилиту!

Контейнеры? Опять docker что ли?

А вот и нет. FreeBSD Jails — это прекрасный инструмент для контейнерезации, ну а упомянутый cbsd для оркестрации этих контейнеров, которым имя — клетки.

Клетка это крайне эффективное решение для построения инфраструктуры для самых разных целей, где в итоге требуется полная изоляция отдельных сервисов или процессов. По сути это клон хост-системы, но ему не требуется полная виртуализация «железа». И ресурсы благодаря этому не тратятся на «гостевую ОС», а только на выполняемую работу. Когда клетки используются для внутренних нужд, это очень удобное решения для оптимального использования ресурса — куча клеток на одном железном сервере могут каждая по отдельности использовать весь ресурс сервера при необходимости. Учитывая что обычно разным подсервисам нужны доп. ресурсы в разное время, можно извлеч из одного сервера максимальную производительность, если правильно спланировать и расбалансировать клетки между серверами. В случае необходимости клеткам можно так же и выставлять ограничения по используемому ресурсу.

А что там с полной виртуализацией?

Насколько мне известно, cbsd поддерживает работу bhyve и XEN гипервизоры. Вторым я никогда не пользовался, а вот первый это относительно молодой гипервизор от FreeBSD. Мы рассмотрим пример использования bhyve в примере далее.

Установка и настройка окружения хоста

Мы используем ФС ZFS. Это крайне мощный инструмент для управления пространства на сервере. Благодаря ZFS можно напрямую из дисков строить массивы самых разных конфигураций, динамически «в горячую» расширять пространство, менять умершие диски, управлять снапшотами и многое, многое другое что можно описывать в целой серии статей. Вернёмся к нашему серверу и его дискам. В начале установки на дисках мы оставили свободное пространство для шифрованных разделов. Почему так? Это для того, что бы система поднималась автоматически и слушала по SSH.

gpart add -t freebsd-zfs /dev/ada0

/dev/ada0p4 added!

добавляем раздел диска на оставшееся место

geli init /dev/ada0p4

вбиваем наш пароль шифрования

geli attach /dev/ada0p4

опять вводим пароль и у нас появляется девайс /dev/ada0p4.eli — это и есть наше зашифрованное пространство. Затем повторяем тоже самое для /dev/ada1 и остальных дисков в массиве. И создаем новый ZFS pool.

zpool create vms mirror /dev/ada0p4.eli /dev/ada1p4.eli /dev/ada3p4.eli — ну вот, у нас минимальный боевой набор готов. Зеркальный массив дисков на случай выхода одного из трёх из строя.

Создаем датасет на новом «пуле»

zfs create vms/jails

pkg install cbsd — запустили команду, и устанавливаем менеджмент для наших клеток.

После того как cbsd установлен, его нужно инициализировать:

# env workdir=»/vms/jails» /usr/local/cbsd/sudoexec/initenv

ну и отвечаем на кучу вопросов, в основном ответами по-умолчанию.

*Если вы используете шифрование, важно что бы демон cbsdd не стартовал автоматически, пока вы не расшифруете диски вручную или автоматически (в нашем примере это делает zabbix)

**Так же я не использую NAT от cbsd, а настраиваю его сам в pf.

# sysrc pf_enable=YES

# ee /etc/pf.conf

IF_PUBLIC=»em0″
IP_PUBLIC=»1.23.34.56″
JAIL_IP_POOL=»192.168.0.0/24″

#WHITE_CL=»{ 127.0.0.1 }»

icmp_types=»echoreq»

set limit { states 20000, frags 20000, src-nodes 20000 }
set skip on lo0
scrub in all

#NAT for jails
nat pass on $IF_PUBLIC from $JAIL_IP_POOL to any -> $IP_PUBLIC

## Bitcoin network port forward
IP_JAIL=»192.168.0.1″
PORT_JAIL=»{8333}»
rdr pass on $IF_PUBLIC proto tcp from any to $IP_PUBLIC port $PORT_JAIL -> $IP_JAIL

# service pf start

# pfctl -f /etc/pf.conf

Настройка политик фаервола это тоже отдельная тема, поэтому я не буду углубляться в настройку политики BLOCK ALL и настройки белых списков, это можно сделать почитав официальную документацию или любую из огромного кол-ва статей доступных в гугле.

Ну что ж… у нас установлена cbsd, пора создать нашу первую рабочую лошадку — демон биткойна в клетке!

cbsd jconstruct-tui

Тут мы видим диалог создания клетки. После того как все значения выставили, создаем!

При создании первой клетки, следует выбрать что использовать в качестве основы для клеток. Я выбираю стрибутив с репозитория FreeBSD командой repo. Этот выбор производится только при создании первой клетки конкретной версии (хостить можно клетки любых версий, что старше версии хоста).

После того как все установлено — запускаем клетку!

# cbsd jstart bitcoind

Но нам нужно в клету установить софт.

# jls

JID IP Address Hostname Path
1 192.168.0.1 bitcoind.space.com /zroot/jails/jails/bitcoind

jexec bitcoind что бы попасть в консоль клетки

и уже внутри клетки устанавливаем софт с его зависимостями (наша хост-система остаеться чистой)

bitcoind:/@[15:25] # pkg install bitcoin-daemon bitcoin-utils

bitcoind:/@[15:30] # sysrc bitcoind_enable=YES

bitcoind:/@[15:30] # service bitcoind start

Биткойн в клетке есть, но нам нужна анонимность, потому как хотим подключатся к некоторым клеткам по сети ТОР. И вообще у нас в планах большинство клеток с подозрительным софтом крутить только через прокси. Благодаря pf можно отключить NAT определнному диапазону IP адресов в локальной сети, и разрешить NAT только для нашего TOR-узла. Таким образом даже если в клетку попадет зловред, он вероятнее всего не выйдет на связь с внешним миром, а если и выйдет, то не раскроет IP нашего сервера. поэтому мы создаем еще одну клетку, для «проброса» сервисов как «.onion»-сервис и как прокси для выхода в интернет отдельным клеткам.

# cbsd jsconstruct-tui

# cbsd jstart tor

# jexec tor

tor:/@[15:38] # pkg install tor

tor:/@[15:38] # sysrc tor_enable=YES

tor:/@[15:38] # ee /usr/local/etc/tor/torrc

Ставим слушать на локальом адресе (для всех клеток доступен)

SOCKSPort 192.168.0.2:9050

Чего же нам еще не хватает для полного счастья. Да, нам нужен сервис для нашего веба, может и не одного. Запустим nginx, который будет выполнять роль reverse-proxy и заботится о продлении Let’s Encrypt сертификатов

# cbsd jsconstruct-tui

# cbsd jstart nginx-rev

# jexec nginx-rev

nginx-rev:/@[15:47] # pkg install nginx py36-certbot

И вот 150 МБ зависимостей мы поместили в клетку. А хост по-прежнему чист.

вернемся к настройке nginx позже, нам нужно поднять еще две клетки для нашего платёжного шлюза на nodejs и rust и веб-апликацию, которая по каким-то причинам на апаче и пхп, а еще для последней нужна БД MySQL.

# cbsd jsconstruct-tui

# cbsd jstart paygw

# jexec paygw

paygw:/@[15:55] # pkg install git node npm

paygw:/@[15:55] # curl —proto ‘=https’ —tlsv1.2 -sSf https://sh.rustup.rs | sh

… и еще 380 МБ пакетов изолировано

далее мы подкачиваем гитом наше приложение и запускаем.

# cbsd jsconstruct-tui

# cbsd jstart webapp

# jexec webapp

webapp:/@[16:02] # pkg install mariadb104-server apache24 php74 mod_php74 php74-pdo_mysql

450 МБ пакетов. в клетке.

тут даем доступ разработчика по SSH прям в клетку, они там сами всё сделают:

webapp:/@[16:02] # ee /etc/ssh/sshd_config

Port 2267 — меняем порт SSH клетки на любой произвольный

webapp:/@[16:02] # sysrc sshd_enable=YES

webapp:/@[16:02] # service sshd start

Ну вот, сервис запущен, осталось добавить правило в pf firewall

Посмотрим какие у нас ИП у клеток и как вообще выглядит наша «локалка»

# jls

JID IP Address Hostname Path
1 192.168.0.1 bitcoind.space.com /zroot/jails/jails/bitcoind
2 192.168.0.2 tor.space.com /zroot/jails/jails/tor
3 192.168.0.3 nginx-rev.space.com /zroot/jails/jails/nginx-rev
4 192.168.0.4 paygw.space.com /zroot/jails/jails/paygw
5 192.168.0.5 webapp.my.domain /zroot/jails/jails/webapp

и добавим правило

# ee /etc/pf.conf

## SSH for web-Devs
IP_JAIL=»192.168.0.5″
PORT_JAIL=»{ 2267 }»
rdr pass on $IF_PUBLIC proto tcp from any to $IP_PUBLIC port $PORT_JAIL -> $IP_JAIL

ну и раз уж мы тут, добавим так же правило на на reverse-proxy:

## web-ports for nginx-rev
IP_JAIL=»192.168.0.3″
PORT_JAIL=»{ 80, 443 }»
rdr pass on $IF_PUBLIC proto tcp from any to $IP_PUBLIC port $PORT_JAIL -> $IP_JAIL

# pfctl -f /etc/pf.conf

Ну а теперь немного о биткойнах

Что мы имеем — у нас есть веб-приложение, которое доступно снаружи, и оно локально общается с нашим платёжным шлюзом. Теперь нам нужно подготовить рабочее окружение для взаимодействия с самой сетью биткойна — нода bitcoind это всего лишь демон, который поддерживает локальную копию блокчейна акутальной. У этого демона есть RPC и функционал кошелька, однако для разработки приложений есть более удобные «обёртки». Для начала мы решили поставить electrum — это CLI кошелек. Этот кошелек у нас будет использоваться в качестве «холодного хранилища» для наших биткойнов — в общем те биткойны, которые нужно будет хранить «вне» системы доступной пользователям и вообще подальше от всех. У него так же есть GUI, поэтому такой же кошелек мы собираемся использовать у себя на
лаптопах. Пока будем електрум использовать с публичными серверами, а позже в еще одной клетке поднимем ElectrumX, что б совсем ни от кого не зависить.

# cbsd jsconstruct-tui

# cbsd jstart electrum

# jexec electrum

electrum:/@[8:45] # pkg install py36-electrum

еще 700 МБ софта у нас в клетке

electrum:/@[8:53] # adduser

Username: wallet
Full name:
Uid (Leave empty for default):
Login group [wallet]:
Login group is wallet. Invite wallet into other groups? []:
Login class [default]:
Shell (sh csh tcsh nologin) [sh]: tcsh
Home directory [/home/wallet]:
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]: no
Lock out the account after creation? [no]:
Username : wallet
Password : <disabled>
Full Name :
Uid : 1001
Class :
Groups : wallet
Home : /home/wallet
Home Mode :
Shell : /bin/tcsh
Locked : no
OK? (yes/no): yes
adduser: INFO: Successfully added (wallet) to the user database.
Add another user? (yes/no): no
Goodbye!
electrum:/@[8:53] # su wallet

electrum:/@[8:53] # su wallet

wallet@electrum:/ % electrum-3.6 create

{
«msg»: «Please keep your seed in a safe place; if you lose it, you will not be able to restore your wallet.»,
«path»: «/usr/home/wallet/.electrum/wallets/default_wallet»,
«seed»: «jealous win pig material ribbon young punch visual okay cactus random bird»
}

Вот у нас теперь создан кошелек.

wallet@electrum:/ % electrum-3.6 listaddresses

[
«18WEhbjvMLGRMfwudzUrUd25U5C7uZYkzE»,
«14XHSejhxsZNDRtk4eFbqAX3L8rftzwQQU»,
«1KQXaN8RXiCN1ne9iYngUWAr6KJ6d4pPas»,

«1KeVcAwEYhk29qEyAfPwcBgF5mMMoy4qjw»,
«18VaUuSeBr6T2GwpSHYF3XyNgLyLCt1SWk»
]

wallet@electrum:/ % electrum-3.6 help

К нашему on-chain кошельку впредь сможет подключится только ограниченый круг лиц. Для того что бы не открывать доступ извне в эту клетку, подключения по SSH будут происходить через ТОР (такой децентрализованный вариант VPN). Запускаем в клетке SSH, но не трогаем наш pf.conf на хосте.

electrum:/@[9:00] # sysrc sshd_enable=YES

electrum:/@[9:00] # service sshd start

Теперь отключим клетке с кошельком выход в интернет. Поставим ей IP-адрес из другого пространства подсети, которое не NAT-ится. Сначала поменяем /etc/pf.conf на хосте

# ee /etc/pf.conf

JAIL_IP_POOL=»192.168.0.0/24″ сменим на JAIL_IP_POOL=»192.168.0.0/25″, таким образом все адреса 192.168.0.126-255 не будут иметь прямого доступа в интернет. Эдакий софтварный «air-gap» network. И NAT правило остаеться как было

nat pass on $IF_PUBLIC from $JAIL_IP_POOL to any -> $IP_PUBLIC

Перегружаем правила

# pfctl -f /etc/pf.conf

Теперь беремся за нашу клетку

# cbsd jconfig jname=electrum

jset mode=quiet jname=electrum ip4_addr=»192.168.0.200″
Remove old IP: /sbin/ifconfig em0 inet 192.168.0.6 -alias
Setup new IP: /sbin/ifconfig em0 inet 192.168.0.200 alias
ip4_addr: 192.168.0.200

Хм, но теперь у нас перестанет работать и сама система. Однако мы можем указать системный proxy. Но есть одно но, на TOR это SOCKS5 прокси, а для удобства нам бы еще HTTP прокси.

# cbsd jsconstruct-tui

# cbsd jstart polipo

# jexec polipo

polipo:/@[9:28] # pkg install polipo

polipo:/@[9:28] # ee /usr/local/etc/polipo/config

socksParentProxy = «192.168.0.2:9050»
socksProxyType = socks5

polipo:/@[9:42] # sysrc polipo_enable=YES

polipo:/@[9:43] # service polipo start

Ну вот, теперь в нашей системе есть два прокси-сервера, и оба выводят через TOR: socks5://192.168.0.2:9050 и http://192.168.0.6:8123

Теперь можно настроить окружение нашего кошелька

# jexec electrum

electrum:/@[9:45] # su wallet

wallet@electrum:/ % ee ~/.cshrc

#in the end of file proxy config
setenv http_proxy http://192.168.0.6:8123
setenv https_proxy http://192.168.0.6:8123

ну вот, теперь шелл будет работать из-под прокси. Если хотим устанавливать пакеты, то стоит добавить в /usr/local/etc/pkg.conf из под рута клетки

pkg_env: {
http_proxy: «http://my_proxy_ip:8123»,
}

Ну а теперь пришло время добавить TOR hidden service в качестве адреса нашего SSH сервиса в клетке кошелька.

# jexec tor

tor:/@[9:59] # ee /usr/local/etc/tor/torrc

HiddenServiceDir /var/db/tor/electrum/
HiddenServicePort 22 192.168.0.200:22

tor:/@[10:01] # mkdir /var/db/tor/electrum

tor:/@[10:01] # chown -R _tor:_tor /var/db/tor/electrum

tor:/@[10:01] # chmod 700 /var/db/tor/electrum

tor:/@[10:03] # service tor restart

tor:/@[10:04] # cat /var/db/tor/electrum/hostname

mdjus4gmduhofwcso57b3zl3ufoitguh2knitjco5cmgrokpreuxumad.onion

Вот он наш адрес для подключения. Давайте проверим c локальной машины. Но сначала надо добавить наш SSH-ключ:

wallet@electrum:/ % mkdir ~/.ssh

wallet@electrum:/ % ee ~/.ssh/authorized_keys

ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAG9Fk2Lqi4GQ8EXZrsH3EgSrVIQPQaAlS38MmJLBabihv9KHIDGXH7r018hxqLNNGbaJWO/wrWk7sG4T0yLHAbdQAFsMYof9kjoyuG56z0XZ8qaD/X/AjrhLMsIoBbUNj0AzxjKNlPJL4NbHsFwbmxGulKS0PdAD5oLcTQi/VnNdU7iFw== user@local

Ну и с клиентской линукс-машины

user@local ~$ nano ~/.ssh/config

#remote electrum wallet
Host remotebtc
User wallet
Port 22
Hostname mdjus4gmduhofwcso57b3zl3ufoitguh2knitjco5cmgrokpreuxumad.onion
ProxyCommand /bin/ncat —proxy localhost:9050 —proxy-type socks5 %h %p

Подключаемся (Для того что бы это работало нужен локальный демон TOR, который слушает на 9050)

user@local ~$ ssh remotebtc

The authenticity of host ‘mdjus4gmduhofwcso57b3zl3ufoitguh2knitjco5cmgrokpreuxumad.onion (<no hostip for proxy command>)’ can’t be established.
ECDSA key fingerprint is SHA256:iW8FKjhVF4yyOZB1z4sBkzyvCM+evQ9cCL/EuWm0Du4.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added ‘mdjus4gmduhofwcso57b3zl3ufoitguh2knitjco5cmgrokpreuxumad.onion’ (ECDSA) to the list of known hosts.
FreeBSD 12.1-RELEASE-p1 GENERIC
To save disk space in your home directory, compress files you rarely
use with «gzip filename».
— Dru <genesis@istar.ca>
wallet@electrum:~ % logout

Успех!

Для работы с мгновенными и микро-платежами нам так же необходима нода Lightning Network, собственно это будет наш основной рабочий инструмент с биткойном. У *c-lightning, который мы собираемся использовать в качестве демона, есть плагин Sparko, который является полноценным HTTP (REST) интерфейсом и позволяет работать как с off-chain транзакциями, так и с on-chain транзакциями. c-lightning для функционирования нужна bitcoind нода.

*есть разные реализация на разных ЯП протокола Lightning Network. Из тех что мы протестировали c-lightning (написан на С) показался найболее стабильным и ресурсо-эффективным

# cbsd jsconstruct-tui

# cbsd jstart cln

# jexec cln

lightning:/@[10:23] # adduser

Username: lightning

lightning:/@[10:24] # pkg install git

lightning:/@[10:23] # su lightning

cd ~ && git clone https://github.com/ElementsProject/lightning

lightning@lightning:~ % exit

lightning:/@[10:30] # cd /home/lightning/lightning/

lightning:/home/lightning/lightning@[10:31] # pkg install autoconf automake gettext git gmp gmake libtool python python3 sqlite3 libsodium py36-mako bash bitcoin-utils

lightning:/home/lightning/lightning@[10:34] # ./configure && gmake && gmake install

Пока компилируется и инсталируется все необходимое, создадим пользователя RPC для lightningd в bitcoind

# jexec bitcoind

bitcoind:/@[10:36] # ee /usr/local/etc/bitcoin.conf

rpcbind=192.168.0.1
rpcuser=test
rpcpassword=test
#allow only c-lightning
rpcallowip=192.168.0.7/32

bitcoind:/@[10:39] # service bitcoind restart

Моё хаотичное переключение между клетками оказывается не таким уж и хаотичным если отметить утилиту tmux, которая позволяет внутри одной сессии создавать множество под-сессий терминалов. Аналог: screen

Такс, мы не хотим светить реальный IP нашей ноды, и хотим вести все финансовые операции через ТОР. Поэтому на нужен еще один .onion.

# jexec tor

tor:/@[9:59] # ee /usr/local/etc/tor/torrc

HiddenServiceDir /var/db/tor/cln/
HiddenServicePort 9735 192.168.0.7:9735

tor:/@[10:01] # mkdir /var/db/tor/cln

tor:/@[10:01] # chown -R _tor:_tor /var/db/tor/cln

tor:/@[10:01] # chmod 700 /var/db/tor/cln

tor:/@[10:03] # service tor restart

tor:/@[10:04] # cat /var/db/tor/cln/hostname

en5wbkavnytti334jc5uzaudkansypfs6aguv6kech4hbzpcz2ove3yd.onion

теперь создадим конфиг для c-lightning

lightning:/home/lightning/lightning@[10:31] # su lightning

lightning@lightning:~ % mkdir .lightning

lightning@lightning:~ % ee .lightning/config

alias=My-LN-Node
bind-addr=192.168.0.7:9735
rgb=ff0000
announce-addr=en5wbkavnytti334jc5uzaudkansypfs6aguv6kech4hbzpcz2ove3yd.onion:9735
network=bitcoin
log-level=info
fee-base=0
fee-per-satoshi=1
proxy=192.168.0.2:9050
log-file=/home/lightning/.lightning/c-lightning.log
min-capacity-sat=200000

# sparko plugin
# https://github.com/fiatjaf/lightningd-gjson-rpc/tree/master/cmd/sparko

sparko-host=192.168.0.7
sparko-port=9737

sparko-tls-path=sparko-tls

#sparko-login=mywalletusername:mywalletpassword

#sparko-keys=masterkey;secretread:+listchannels,+listnodes;secretwrite:+invoice,+listinvoices,+delinvoice,+decodepay,+waitpay,+waitinvoice
sparko-keys=masterkey;secretread:+listchannels,+listnodes;ultrawrite:+invoice,+listinvoices,+delinvoice,+decodepay,+waitpay,+waitinvoice
# for the example above the initialization logs (mixed with lightningd logs) should print something like

lightning@lightning:~ % mkdir .lightning/plugins

lightning@lightning:~ % cd .lightning/plugins/

lightning@lightning:~/.lightning/plugins:% fetch https://github.com/fiatjaf/sparko/releases/download/v0.2.1/sparko_full_freebsd_amd64

lightning@lightning:~/.lightning/plugins % mkdir ~/.lightning/sparko-tls

lightning@lightning:~/.lightning/sparko-tls % cd ~/.lightning/sparko-tls

lightning@lightning:~/.lightning/sparko-tls % openssl genrsa -out key.pem 2048

lightning@lightning:~/.lightning/sparko-tls % openssl req -new -x509 -sha256 -key key.pem -out cert.pem -days 3650

lightning@lightning:~/.lightning/plugins % chmod +x sparko_full_freebsd_amd64

lightning@lightning:~/.lightning/plugins % mv sparko_full_freebsd_amd64 sparko

lightning@lightning:~/.lightning/plugins % cd ~

нужно так же создать конфигурационный файл для bitcoin-cli, утилиты, что общается с bitcoind

lightning@lightning:~ % mkdir .bitcoin

lightning@lightning:~ % ee .bitcoin/bitcoin.conf

rpcconnect=192.168.0.1
rpcuser=test
rpcpassword=test

проверяем

lightning@lightning:~ % bitcoin-cli echo «test»

[
«test»
]

запускаем lightningd

lightning@lightning:~ % lightningd —daemon

Сам lightningd можно управлять утилитой lightning-cli, например:

lightning-cli newaddr получить адрес для нового входящего платежа

{
«address»: «bc1q2n2ffq3lplhme8jufcxahfrnfhruwjgx3c78pv»,
«bech32»: «bc1q2n2ffq3lplhme8jufcxahfrnfhruwjgx3c78pv»
}

lightning-cli withdraw bc1jufcxahfrnfhruwjgx3cq2n2ffq3lplhme878pv all отправить на адрес все деньги кошелька (всех он-чейн адресов)

Так же команды для off-chain операций lightning-cli invoice, lightning-cli listinvoices, lightning-cli pay итд.

Ну а для коммуникации с приложение у нас есть REST Api

curl -k https://192.168.0.7:9737/rpc -d ‘{«method»: «pay», «params»: [«lnbc…»]}’ -H ‘X-Access masterkey’

Подведем итоги

# jls

JID IP Address Hostname Path
1 192.168.0.1 bitcoind.space.com /zroot/jails/jails/bitcoind
2 192.168.0.2 tor.space.com /zroot/jails/jails/tor
3 192.168.0.3 nginx-rev.space.com /zroot/jails/jails/nginx-rev
4 192.168.0.4 paygw.space.com /zroot/jails/jails/paygw
5 192.168.0.5 webapp.my.domain /zroot/jails/jails/webapp
7 192.168.0.200 electrum.space.com /zroot/jails/jails/electrum
8 192.168.0.6 polipo.space.com /zroot/jails/jails/polipo
9 192.168.0.7 lightning.space.com /zroot/jails/jails/cln

У нас имеется набор контейнеров, каждый со своим уровнем доступа как из так и в локальную сеть.

# zfs list

NAME USED AVAIL REFER MOUNTPOINT
zroot 279G 1.48T 88K /zroot
zroot/ROOT 1.89G 1.48T 88K none
zroot/ROOT/default 1.89G 17.6G 1.89G /
zroot/home 88K 1.48T 88K /home
zroot/jails 277G 1.48T 404M /zroot/jails
zroot/jails/bitcoind 190G 1.48T 190G /zroot/jails/jails-data/bitcoind-data
zroot/jails/cln 653M 1.48T 653M /zroot/jails/jails-data/cln-data
zroot/jails/electrum 703M 1.48T 703M /zroot/jails/jails-data/electrum-data
zroot/jails/nginx-rev 190M 1.48T 190M /zroot/jails/jails-data/nginx-rev-data
zroot/jails/paygw 82.4G 1.48T 82.4G /zroot/jails/jails-data/paygw-data
zroot/jails/polipo 57.6M 1.48T 57.6M /zroot/jails/jails-data/polipo-data
zroot/jails/tor 81.5M 1.48T 81.5M /zroot/jails/jails-data/tor-data
zroot/jails/webapp 360M 1.48T 360M /zroot/jails/jails-data/webapp-data

Как видно, bitcoind занимает все 190 ГБ пространства. А что если нам понадобиться еще одна нода для тестов? Тут ZFS как никак кстати. При помощи cbsd jclone old=bitcoind new=bitcoind-clone host_hostname=clonedbtc.space.com можно создать снапшот и подвязать новую клетку к этому снапшоту. У новой клетки будет полностью свое собственное пространство, но при этом учитываться в ФС будут только разница между текущим состоянием и оригиналом (сэкономим как минимум 190 ГБ)

Каждая клетка это свой отдельный датасет ZFS, и это крайне удобно. ZFS так же позволяет делать разные другие крутые штуки, вроде отправки снапшотов по SSH. Описывать это не будем, итак уже много.

Стоит так же отметить необходимость удаленного мониторинга хоста, у нас для этих целей Zabbix.

Б — безопасность

Что касается безопасности, давайте исходить из ключевых принципов в контексте инфраструктры:

Конфиденциальность — Стандартные инструменты UNIX-подобных систем обеспечивают выполнение этого принципа. Мы логически разделяем доступ к каждому логически отдельному элементу системы — клетке. Доступ осуществляется посредством стандартной пользовательской аутентификацией по личным ключам пользователей. Вся коммуникация между и до конечных клеток происходит в шифрованном виде. Благодаря шифрованию дисков мы можем не беспокоится и сохранности данных во время замены диска или миграции на другой сервер. Единственный критический доступ является доступ к хост-системе, так как такой доступ обеспечивает в общем случае доступ к данным внутри контейнеров.

Целостность — Выполнение этого принципа происходит на нескольких разных уровнях. Во-первых важно отметить что в случае серверного оборудования, ECC памяти, ZFS уже «из коробки» заботится о целостности данных на уровне битов информации. Мгновенные снапшоты позволяют делать резервное копирование в любой момент времени на лету. Удобные инструменты экспорта-импорта клеток делают простым реплицирование клеток.

Доступность — Тут уже опционально. Зависит от степени вашей известности и факта наличия у вас ненавистников. В нашем примере мы обеспечили доступность кошелька исключительно из ТОР сети. При необходимости можно на фаерволе заблокировать всё и разрешить доступ к серверу сключительно через тунели (ТОР или ВПН это другой вопрос). Таким образом сервер будет отрезан от внешнего мира насколько это возможно, и повлиять на его доступность сможем только мы сами.

Невозможность отказа — А это зависит от дальнейшей эксплуатации и соблюдения верных политик пользовательских прав, доступа итп. Но при правильном подходе у нас все действия пользователей аудитируются, а благодаря криптографическим решениям возможно однозначно идентифицировать кто и когда совершал те или иные действия.

Конечно описанная конфигурация не является абсолютным примером как оно должно быть всегда, это скорее один из примеров, как оно может быть, сохраняя за собой очень эластичные возможности масштабирования и кастомизации.

А как же полная виртуализация?

Про полную виртуализацию средствами cbsd можно прочитать тут. Я лишь добавлю, что для работ bhyve необходимо включить некоторые параметры ядра.

# cat /etc/rc.conf


kld_list=»vmm if_tap if_bridge nmdm»

# cat /boot/loader.conf


vmm_load=»YES»

Так что если вдруг есть необходимости завести докер, то поднимаем какйой-нибудь debian и вперёд!

Вот и всё

Пожалуй это всё чем я хотел поделиться. Если Вам понравилась статья то мне можно закинуть биткойнов — bc1qu7lhf45xw83ddll5mnzte6ahju8ktkeu6qhttc. Если хотите попробовать клетки в действии и есть немного биткойнов, то можно зайти на мой pet-project.

Оставить комментарий