Banana Pi R64 роутер - Debian, Wireguard, RKN

Banana Pi 64 — это одноплатный компьютер по типу Raspberry Pi, но с несколькими портами Ethernet, что дает возможность сделать из него маршрутизатор на базе дистрибутива Linuх общего назначения.

Banana Pi R64 роутер - Debian, Wireguard, RKN

Да, уже есть Openwrt, но у него свои заморочки свой GUI и CLI; есть Mikrotik, но у него опять же свой GUI/CLI, да и Wireguard из коробки не работает… В общем хочется маршрутизатор с гибкими настройками, при этом оставшись в рамках стандартного линукса, с которым работаешь каждый день.

В статье под названиями BPI, R64, одноплатник я буду подразумевать одно и тоже — собственно сам одноплатник Banana Pi R64.

Выбор образа. Загрузка по eMMC

Самый первый навык, который нужно приобрести при работе с ПКС вообще, и с R64 в частности, это научиться грузить в него операционку и иметь возможность взаимодействовать с ним, ведь у R64 нет порта для монитора (HDMI, например). Когда все отвалилось — перестал работать Wifi, сеть Ethernet, Bluetooth, USB и прочее есть UART, через интерфейс которого всегда можно посмотреть, что пошло не так, а также запустить пару команд из консоли, по необходимости.

Алгоритм подключения к R64 по USB-UART:

  • бежим в магазин радиодеталей за кабелем USB-UART (PL2303, Serial-to-USB)
  • подключаем один USB-конец к компьютеру, а другой, UART,- к R64, тремя проводами из четырех, как на картинке ниже
  • в консоли компьютера запускаем sudo minicom

После этого в большинстве случаев появится консоль одноплатника = успех.
Подробнее можно посмотреть бул жерде.

Banana Pi R64 роутер - Debian, Wireguard, RKN

Далее, проще всего загрузить операционную систему с SD-карты: скачиваем по байланыш образ и заливаем его:

unzip -p 2019-08-23-ubuntu-16.04-lite-preview-bpi-r64-sd-emmc.img.zip | pv | sudo dd of=/dev/mmcblk0 bs=10M status=noxfer

вставляем карту в SD-слот R64, включаем, наблюдаем по подключенной консоли загрузку сначала uboot, затем стандартную загрузку линукса.

Альтернативный вариант загрузки — с помощью уже вшитой в R64 карты размером 8Gb, называемой eMMC. По инструкции в вики переписываем образ на устройство
/dev/mmcblk0 в BPI, перегружаемся, вытаскиваем SD-карту, включаем BPI снова… и не работает. Как туда-сюда Boot select ни дергай.

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

root@bpi-r64:~# ./mmc extcsd read /dev/mmcblk1 | grep 'PARTITION_CONFIG'
Boot configuration bytes [PARTITION_CONFIG: 0x00]
root@bpi-r64:~# ./mmc bootpart enable 1 1 /dev/mmcblk1
root@bpi-r64:~# ./mmc extcsd read /dev/mmcblk1 | grep 'PARTITION_CONFIG'
Boot configuration bytes [PARTITION_CONFIG: 0x48]

Далее, в специальный boot-вый раздел надо записать preloader

root@bpi-r64:~# echo 0 > /sys/block/mmcblk0boot0/force_ro 
root@bpi-r64:~# dd if=preloader_evb7622_64_foremmc.bin of=/dev/mmcblk0boot0

Производитель R64 (Китай) выложил этот бинарь бул жерде. Что он делает неизвестно (исходников нет), но без него тоже не заработает.

В общем-то после этого образы начинают грузиться и с eMMC. Если же захотеть разобраться и создавать образы с нуля, то для обоих случаев (SD/eMMC) нужно записывать еще несколько файлов (preloader для SD-карты, ATF, u-boot), только чтоб добраться до загрузки ядра. Тема эта до сих пор иштеп, но для нас главное, что работает и ладно.

Сейчас я загрузку по eMMC, честно говоря, не использую, SD карты достаточно, но я довольно много времени потратил на то, чтоб оно заработало, поэтому пусть будет в статье.

Выбор операционки. Armbian

Первая прикладная задача — запустить VPN, естественно Wireguard. Сразу же обнаружилось, что со стороны ядра он не собран, и заголовков нет. Пересобрал ядро и, по привычке с x86, собрал модуль ядра с помощью DKMS. Однако скорость сборки на arm64 даже небольших утилит меня неприятно удивила. А дальше еще один модуль ядра потребовался, и т.д. В общем, выходит, что все, связанное с ядром, лучше собирать на теплом-ламповом ноутбуке x86, затем простым копированием переносить на R64, перегружаться и тестить.

Другое дело — юзейспейсная часть. В моем случае выбора Debian, все для архитектуры arm64 уже есть на packages.debian.org и ничего пересобирать не приходится.

Чтобы не плодить очередной велосипед, я ташылган Армян на BPI R64.
Вернее так: userspace-ная часть — Armbian, а ядро берется из репозитория ачык-а. Самый свежий образ можно скачать бул жерде.

Вся активность по разработке софтовой части R64 ведется на Суперстан. Вообще говоря, сам производитель стремится популяризировать роутер под Openwrt, но благодаря активности разработчика Frank-а из Германии все фичи быстро оказываются в ядре для Debian-а. Удивительно, но Frank активен в каждой ветке форума.

Организация рабочего пространства: провода

Отдельно хочу рассказать, как во время разработки/тестирования разместить SBC (не только BPI) на столе так, чтоб не вести Ethernet-кабель к нему от источника интернета через всю комнату/офис. Дело в том, что с одной стороны нужно обеспечить железке интернет, а с другой стороны в этой самой железке может все ломаться, и в первую очередь Wifi.

Сначала я решил приобрести дешевый USB-Wifi "свисток", воткнуть его в единственный порт на BPI и забыть о проводах. Для этого приобрел недорогой TP-LINK TL-WN725N USB 2.0, но очень скоро стало понятно, что не взлетит: для работы свистка нужен драйвер ядра, которого там, естественно, не было (позже я собрал нужный драйвер RTL8XXXU, но все равно это непрактично). И Ethernet-кабель портил вид комнаты некоторое время.

В итоге от кабеля мне удалось избавиться с помощь Tenda MW3 (Wifi mesh-система): просто расположил один кубик под столом и метровым Ethernet-кабелем подключил BPI к LAN-порту последнего. Успех.

Wireguard, РКН, Bird

Одна из хотелок, для чего я использую Banana PI — иметь свободный доступ на сайты, заблокированные РКН, в частности, чтоб работал Telegram и звонки в Slack-е. На эту тему уже были предложены статьи на Хабре: убакыт, два, үч.

Развертывание именно такого решения я реализовал с помощью Ansible: байланыш.

Предполагается, что VPS работает под Ubuntu 18.04. Работоспособность проверил на двух хостерах в Европе: Amazon и Digital Ocean.

Итак, мы установили вышеуказанный Armbian на R64, он доступен по ssh под именем hm-bananapi-1 и имеет доступ в интернет. Развертываем последовательно ansible, скрипты автоматизации и запускаем установку собственно на R64:

# зависимости для Debian-based дистрибутивов
$ sudo apt install --no-install-recommends python3-pip python3-setuptools python3-wheel git
$ which pip3
/usr/bin/pip3

# ansible с pybook, скриптование на Python
$ pip3 install https://github.com/muravjov/ansible/archive/ansible-2.10.0.dev0-pybook2019.tar.gz

$ export PATH=~/.local/bin:$PATH
$ which ansible-playbook
/home/sa/.local/bin/ansible-playbook

$ git clone https://github.com/muravjov/ansible-bpi-r64.git
$ cd ansible-bpi-r64

$ git submodule update --init

# убеждаемся в доступности hm-bananapi-1
$ ssh hm-bananapi-1 which python3
/usr/bin/python3

# собственно установка
$ ansible-playbook ./router.py -l hm-bananapi-1

Далее нужно аналогичным образом задеплоить на VPS наш VPN:

ansible-playbook ./router.py -l current-vpn

Здесь аргумент всегда current-vpn, а собственно имя VPS настраивается в переменной (в данном случае это paris-vpn-aws-t2-micro-1):

$ grep current_vpn group_vars/all 
current_vpn: paris-vpn-aws-t2-micro-1
#current_vpn: frankfurt-vpn-d0-starter-1

Ах да, перед всеми этими операциями нужно сгенерировать секреты (в частности ключи Wireguard) в папку ./secrets, директория должна выглядеть ушундай.

Автоматизация Ansible на Python

Можно заметить, что вместо формата YAML команды Ansible закодированы в скриптах Python. Для сравнения, как обычным способом включить демон bird:

- name: start bird
  systemd:
    name: bird
    state: started
    enabled: yes

и как то же самое через Python:

with mapping:
    append("name", "start bird")
    with mapping("systemd"):
        append("name",  "bird")
        append("state", "started")
        append("enabled", "yes")

Запись команд Ansible кодом на Python позволяет повторно использовать код, да и вообще открыты все возможности языка общего назначения. Например, установка bird на R64 и VPS:

install_bird("router/bird.conf.j2")
install_bird("vpn/bird.conf.j2")

посмотреть код функции install_bird().

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

Что думает жогору ушул учурда.

Мониторинг. Prometheus

Итого: телеграмчик работает, linkedin и pornhub тоже, в общем user experience — ок. Но все может ломаться, и китайские железки тоже.

Обновления ядра тоже бывают интересными: например, я захотел обновить ядро 5.4 => 5.6, нуачо, там же Wireguard изкоробки, не надо патчить… Сказано-сделано: кропотливо переносил патчи с 5.4 на 5.6, ядро завелось, туннель до VPS пингуется, но bird не может соединиться с ошибкой "BGP Error"… "В ужасе откатился назад" (с) на 5.4; переезд на 5.6 отложил в TODO.

Поэтому в дополнение к инсталяции роутера и VPS добавил мониторинг (на x86 Ubuntu 18.04), который ставится на отдельный хост со следующими компонентами:

  • prometheus, alertmanager, blackbox_exporter — все в докере
  • алерты направляются в телеграм-канал с помощью бота metalmatze/alertmanager-bot — тоже в докере
  • tor для бота, чтобы бот мог алертить ситуации, когда интернет есть, но телеграм все равно не работает, и сам бот не может соединиться
  • колдонулат алерты: NodeVPNTroubles (нет ping-а до VPS), BirdVPNTroubles (нет сессии Bird), AntifilterDownloadTroubles (ошибка загрузки заблокированных IP-адресов), SiteTroubles (недоступен злополучный телеграм)
  • системные алерты, например, HostGrowingDiskReadLatency (дешевая SD-карта перестает читаться)

Пример установки мониторинга:

ansible-playbook ./monitoring.py -l monitoring-preprod

Auto Discovery для прометея настроено на папку /etc/prometheus/auto_http, пример добавления хоста в мониторинг (по умолчанию хосты не мониторятся):

bash << 'EOF'
HOSTNAME=hm-bananapi-1
IP_ADDRESS=`ssh -G $HOSTNAME | awk '/^hostname / { print $2 }'`

ssh monitoring-preprod sudo sponge /etc/prometheus/auto_http/$HOSTNAME.json << EOF2
[
  {
    "targets": ["$IP_ADDRESS:9100"],
    "labels": {
      "env": "prod",
      "hostname": "$HOSTNAME"
    }
  }
]
EOF2
EOF

TODO: 2 провайдера, 2 BPI, anycast failover

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

Наиболее продвинутый user experience на тему multi-wan описан бул жерде для системы Mwan3 под Openwrt. У данного решения богатый функционал, но настройка и эксплуатация вообще для multi-wan довольно хлопотна. Один только пример: если приходить на некоторые сайты сразу с двух IP-адресов, то им это может не понравится, они перестанут работать => "интернет не работает".

Учитывая данный опыт решил, что multihoming пока не в приоритете, только failover. Хотя, кажется, в последних версиях linux все должно работать одной командой вида:

ip route add default 
    nexthop via 192.168.1.1 weight 10 
    nexthop via 192.168.2.1 weight 5

Итак, чтобы не было единой точки отказа, берем 2 BPI, каждый подключаем к одному провайдеру, соединяем их между собой и связь друг c другом сделаем динамической маршрутизацией через bird/OSPF.

Далее, на каждом анонсируем одинаковый IP-адрес в случае, если сервис доступен (интернет, DNS). То есть проставлять маршрут по умолчанию будем не сами, а посредством bird. Решение подсмотрел бул жерде .

Данный функционал пока не реализовал, коварный коронавирус и тут подгадил (не все приехало c алиэкспресс; еще один интернет-магазин, Layta, обещал доставить за неделю, а уже больше месяца прошло; второй провайдер не успел кабель протянуть до карантина, успел только дырку в стене просверлить для кабеля).

Как заказать R64

Сама плата в официальном магазине SinoVoip.
Также лучше сразу заказать:

  • тамак-аш + сообщить стандарт штекера ЕС или США
  • теплоотвод: радиаторы/вентиляторы; потому что и CPU греется, и чип switch-а
  • антенну для wifi, Мисалы,

Есть нюанс — цена доставки с какого-то времени стала неадекватно высокой в официальном магазине. Менеджер Judy Huang убеждала меня, что ошибки нет, и можно выбрать ePacket за $5, но я видел, что для России есть только EMS за >33$. Неприятно, но не критично. Причем, если выбрать любую другую страну для доставки (перебрал все континенты), доставка будет за ~5$. Русофобы?.. Но потом я нашел, что для Франции цена доставки тоже ~30$, и успокоился.

В итоге Judy предложила сделать заказ, но не оплачивать (шек: положить на карту меньше, чтоб автоматом оплата не прошла); написать ей, и она снизит цену доставки до нормальной. Успех.

маселелер

Не все пока работает идеально.

кирешелүүлүк

Медленно выполняются команды Ansible=Python, даже холостые, по 20-30 секунд; на порядок дольше, чем на ноуте x86. Причем сначала выполняются достачно быстро, ~3 секунды, затем резко замедляются. Возможно это происходит из-за нагревающегося CPU (throttling). Код на Go тоже долго работает:

# запрос метрик для прометея из node_exporter на Go
$ time curl -s http://172.30.1.1:9100/metrics > /dev/null

real    0m6,118s
user    0m0,005s
sys     0m0,009s

# однако температура 51 градус, не так и много
sa@bananapir64:~$ cat /sys/devices/virtual/thermal/thermal_zone0/temp
51700

WiFi

Wifi работает, но на Armbian где-то через сутки перестает, пишет:

sa@bananapir64:~$ dmesg | grep -E 'mt7622_wmac.*timeout'
[470303.802539] mt7622_wmac 18000000.wmac: Message 38 (seq 3) timeout
[470314.042508] mt7622_wmac 18000000.wmac: Message 50 (seq 4) timeout
...

Помогает лишь рестарт. Надо дальше разбираться.

Ethernet

Ethernet работает, но через ~сутки пакеты (DHCP) от R64 перестают приходить.
Помогает рестарт интерфейса:

ifdown br0; sleep 30; ifup br0

Драйвер новый, в ядро еще не приняли, надеюсь китаец Landen Chao допилит.

Source: www.habr.com

Комментарий кошуу