Маршрутизатор Banana Pi R64 - Debian, Wireguard, РКН

Banana Pi 64 - це одноплатний комп'ютер на кшталт Raspberry Pi, але з кількома портами Ethernet, що дозволяє зробити з нього маршрутизатор на базі дистрибутива Linuх загального призначення.

Маршрутизатор Banana Pi R64 - Debian, Wireguard, РКН

Так, вже є Openwrt, але має свої проблеми свій GUI і CLI; є Mikrotik, але у нього знову ж таки свій GUI/CLI, та й Wireguard із коробки не працює… Загалом хочеться маршрутизатор із гнучкими налаштуваннями, при цьому залишившись у рамках стандартного лінуксу, з яким працюєш щодня.

У статті під назвами BPI, R64, одноплатник я маю на увазі одне і теж - власне сам одноплатник Banana Pi R64.

Вибір образу. Завантаження по eMMC

Найперша навичка, яку потрібно придбати при роботі з SBC взагалі, і з 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, РКН

Далі, найпростіше завантажити операційну систему з 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, ядро ​​завелося, тунель до тунель до тунель до не може з'єднатися з помилкою "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, кожен підключаємо до одного провайдера, з'єднуємо їх між собою та зв'язок один з одним зробимо динамічною маршрутизацією через bird/OSPF.

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

Цей функціонал поки не реалізував, підступний коронавірус і тут підгадав (не все приїхало з аліекспрес; ще один інтернет-магазин, 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

Wi-Fi

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 допилить.

Джерело: habr.com

Додати коментар або відгук