Как стать автором
Обновить

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

Время на прочтение 18 мин
Количество просмотров 13K

Так сложилось, что я по профессии администратор компьютерных систем и сетей (короче: сисадмин), и довелось поведать за немногим более чем 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 для оркестрации этих контейнеров, которым имя — клетки.


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


image


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


Насколько мне известно, 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.

Теги:
Хабы:
+4
Комментарии 17
Комментарии Комментарии 17

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн
PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн