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