Router Banana Pi R64 — Debian, Wireguard, RKN

Banana Pi 64 to jednopłytowy komputer typu Raspberry Pi, ale z kilkoma portami Ethernet, co pozwala na zbudowanie z niego routera na bazie ogólnodostępnego systemu Linux.

Router Banana Pi R64 — Debian, Wireguard, RKN

Tak, istnieje już Openwrt, ale ma swoje trudności, własny GUI i CLI; jest Mikrotik, ale z kolei ma własny GUI/CLI, a Wireguard nie działa od razu… Chciałbym ogólnie router z elastycznymi ustawieniami, przy pozostaniu w ramach standardowego Linuksa, z którym pracuję na co dzień.

W artykule pod nazwami BPI, R64, jednopladnik będę odnosił się do tego samego — samego jednopłytowego Banana Pi R64.

Wybór obrazu. Ładowanie przez eMMC

Najważniejszą umiejętnością, którą trzeba zdobyć przy pracy z SBC ogólnie, oraz z R64 w szczególności, jest umiejętność załadowania systemu operacyjnego i możliwość interakcji z nim, gdyż R64 nie ma portu dla monitora (na przykład HDMI). Kiedy wszystko zawiedzie — przestaje działać Wifi, sieć Ethernet, Bluetooth, USB i inne, dostępne jest UART, przez które zawsze można sprawdzić, co poszło nie tak, a także uruchomić kilka poleceń z konsoli, w razie potrzeby.

Algorytm połączenia z R64 przez USB-UART:

  • biegniemy do sklepu z częściami elektronicznymi po kabel USB-UART (PL2303, Serial-to-USB)
  • podłączamy jeden koniec USB do komputera, a drugi, UART, do R64, trzema przewodami spośród czterech, jak na poniższym obrazku
  • w konsoli komputera uruchamiamy sudo minicom

Po tym w większości przypadków pojawi się konsola jednopłytowca = sukces.
Więcej informacji można znaleźć tutaj.

Router Banana Pi R64 — Debian, Wireguard, RKN

Następnie, najłatwiej jest załadować system operacyjny z karty SD: pobieramy z linkiem obraz i wrzucamy go:

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

wsadzamy kartę do slotu SD R64, włączamy, obserwując przez podłączoną konsolę ładowanie najpierw uboot, potem standardowe ładowanie Linuksa.

Alternatywną metodą ładowania jest wykorzystanie wbudowanej w R64 karty o pojemności 8Gb, nazywanej eMMC. Zgodnie z instrukcją w wiki przepisywany obraz na urządzenie
/dev/mmcblk0 в BPI, перегружаемся, вытаскиваем SD-карту, включаем BPI снова… и не работает. Как туда-сюда Boot select nie poruszaj.

Chodzi o to, że przynajmniej dla BPI konieczne jest ustawienie specjalnego flagu, aby móc ładować się z wewnętrznej pamięci flash:

root@bpi-r64:~# .\/mmc extcsd read \/dev\/mmcblk1 | grep 'PARTITION_CONFIG'\nBajty konfiguracji rozruchu [PARTITION_CONFIG: 0x00]\nroot@bpi-r64:~# .\/mmc bootpart enable 1 1 \/dev\/mmcblk1\nroot@bpi-r64:~# .\/mmc extcsd read \/dev\/mmcblk1 | grep 'PARTITION_CONFIG'\nBajty konfiguracji rozruchu [PARTITION_CONFIG: 0x48]

Następnie, w specjalnej sekcji rozruchowej trzeba zapisać preloader

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

Producent R64 (Chiny) udostępnił ten plik binarny tutaj. Co on robi, nie wiadomo (brak źródeł), ale bez niego również nie zadziała.

Ogólnie rzecz biorąc, po tym obrazki zaczynają się ładować z eMMC. Jeśli jednak chcesz się zapoznać i tworzyć obrazy od podstaw, to w obu przypadkach (SD/eMMC) trzeba nagrać jeszcze kilka plików (preloader dla karty SD, ATF, u-boot), tylko po to, żeby dojść do załadowania jądra. Temat ten jest wciąż rozwijana jest, ale dla nas najważniejsze, że działa i tyle.

Obecnie nie korzystam z ładowania po eMMC, szczerze mówiąc, karty SD wystarczają, ale poświęciłem sporo czasu, aby to działało, więc niech będzie w artykule.

Wybór systemu operacyjnego. Armbian

Pierwszym zadaniem aplikacyjnym jest uruchomienie VPN, oczywiście Wireguard. Od razu zauważyłem, że jądro nie jest skompilowane i brakuje nagłówków. Przebudowałem jądro i, z przyzwyczajenia z x86, skompilowałem moduł jądra za pomocą DKMS. Zaskoczyła mnie jednak prędkość kompilacji na arm64, nawet niewielkich narzędzi. A potem potrzebny był jeszcze jeden moduł jądra, itd. Ogólnie rzecz biorąc, wszystko związane z jądrem lepiej kompilować na ciepłym, lampowym laptopie x86, a następnie przenosić po prostu przez skopiowanie na R64, restartować i testować.

Inna sprawa — część userspace. W moim przypadku wyboru Debiana, wszystko dla architektury arm64 jest już dostępne na packages.debian.org i nie trzeba niczego ponownie kompilować.

Aby nie tworzyć kolejnego roweru, ja przeniósł Armbian na BPI R64.
A właściwie tak: część userspace — Armbian, a jądro pochodzi z repozytorium Frank-a. Najnowszy obraz można pobrać tutaj.

Cała aktywność związana z rozwojem oprogramowania R64 odbywa się na forum. Mówiąc ogólnie, sam producent dąży do popularyzacji routera pod Openwrt, ale dzięki aktywności developera Franka z Niemiec, wszystkie funkcje szybko trafiają do jądra dla Debiana. To dziwne, ale Frank jest aktywny w każdej gałęzi forum.

Organizacja przestrzeni roboczej: kable

Osobno chciałbym opowiedzieć, jak podczas rozwoju/testowania umieścić SBC (nie tylko BPI) na biurku, aby nie prowadzić kabla Ethernet do niego od źródła internetu przez cały pokój/biuro. Chodzi o to, że z jednej strony trzeba zapewnić sprzętowi internet, a z drugiej strony w tym samym sprzęcie może wszystko się psuć, a w pierwszej kolejności Wifi.

Na początku postanowiłem kupić tani USB-Wifi "dongle", wpiąć go w jedyny port na BPI i zapomnieć o kablach. W tym celu zakupiłem niedrogi TP-LINK TL-WN725N USB 2.0, ale bardzo szybko okazało się, że to nie zadziała: do działania dongla potrzebny jest sterownik jądra, którego tam oczywiście nie było (później skompilowałem potrzebny sterownik RTL8XXXU, ale wciąż to było niepraktyczne). A kabel Ethernet psuł widok pokoju przez pewien czas.

W końcu udało mi się pozbyć kabla dzięki Tenda MW3 (system Wifi mesh): po prostu umieściłem jeden moduł pod biurkiem i podłączyłem BPI do portu LAN ostatniego za pomocą metrowego kabla Ethernet. Sukces.

Wireguard, RKN, Bird

Jedną z rzeczy, dla których używam Banana PI, jest posiadanie swobodnego dostępu do stron zablokowanych przez RKN, w szczególności, aby działał Telegram i połączenia w Slacku. Na ten temat już opublikowano artykuły na Habrze: raz, dwa, trzy.

Rozwój takiego rozwiązania zrealizowałem za pomocą Ansible: link.

Zakłada się, że VPS działa pod Ubuntu 18.04. Sprawdziłem jego działanie na dwóch hostach w Europie: Amazon i Digital Ocean.

Tak więc zainstalowaliśmy wspomniane Armbian na R64, jest dostępny przez ssh pod nazwą hm-bananapi-1 i ma dostęp do internetu. Kolejno wdrażamy ansible, skrypty automatyzacji i uruchamiamy instalację na 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

Następnie trzeba w podobny sposób wdrożyć na VPS nasz VPN:

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

Tutaj argument to zawsze current-vpn, a nazwa VPS jest konfigurowana w zmiennej (w tym przypadku jest to 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

Ach tak, przed wszystkimi tymi operacjami należy wygenerować sekrety (w szczególności klucze Wireguard) do folderu ./secrets, katalog powinien wyglądać tak.

Automatyzacja Ansible w Pythonie

Można zauważyć, że zamiast formatu YAML komendy Ansible są zakodowane w skryptach Python. Dla porównania, jak w zwykły sposób uruchomić demona bird:

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

i jak to samo przez Python:

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

Rejestrowanie komend Ansible w kodzie Pythona pozwala na ponowne wykorzystanie kodu, a w ogóle otwiera wszystkie możliwości języka ogólnego przeznaczenia. Na przykład instalacja bird na R64 i VPS:

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

zobacz kod funkcji install_bird().

Ta funkcja nosi nazwę pybook zrealizowano tutaj. Dokumentacji do pybooka jeszcze nie ma, później naprawię ten błąd.

Co myślisz upstream o tym?

Monitoring. Prometheus

Podsumowując: telegram działa, linkedin i pornhub również, ogólnie doświadczenie użytkownika — w porządku. Ale wszystko może się popsuć, a chińskie urządzenia również.

Aktualizacje jądra też bywają ciekawe: na przykład, postanowiłem zaktualizować jądro 5.4 => 5.6, no bo tam jest Wireguard z pudełka, nie trzeba patchować… Powiedziano-zrobione: skrupulatnie przenosiłem patche z 5.4 na 5.6, jądro się uruchomiło, tunel do VPS pingowany, ale bird nie może się połączyć z błędem "BGP Error"… "W przerażeniu wróciłem" (c) do 5.4; migrację na 5.6 odłożyłem na TODO.

Dlatego w дополнieniu do instalacji routera i VPS dodałem monitoring (na x86 Ubuntu 18.04), który jest uruchamiany na oddzielnym hoście z następującymi komponentami:

  • prometheus, alertmanager, blackbox_exporter — wszystko w dockerze
  • alerty kierowane do kanału telegramowego z pomocą bota metalmatze/alertmanager-bot — również w dockerze
  • tor dla bota, aby bot mógł informować o sytuacjach, kiedy internet działa, ale telegram nadal nie działa, a sam bot nie może się połączyć
  • aplikacyjne alerty: NodeVPNTroubles (brak ping do VPS), BirdVPNTroubles (brak sesji Bird), AntifilterDownloadTroubles (błąd pobierania zablokowanych adresów IP), SiteTroubles (niedostępny feralny telegram)
  • alerty systemowe, na przykład HostGrowingDiskReadLatency (tani karta SD przestaje działać)

Przykład instalacji monitoringu:

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

Auto Discovery dla prometheusa ustawione na folderze \/etc\/prometheus\/auto_http, przykład dodania hosta do monitoringu (domyślnie hosty nie są monitorowane):

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 dostawców, 2 BPI, anycast failover

W dodatku do wszystkiego zaplanowałem połączenie z dwoma dostawcami, aby internet działał dalej, nawet jeśli jeden z dostawców ma problemy z siecią, lub zapomnieli zapłacić za internet itp., oraz inny ludzki czynnik.

Najbardziej zaawansowane doświadczenie użytkownika na temat multi-wan opisano tutaj dla systemu Mwan3 pod Openwrt. To rozwiązanie ma bogatą funkcjonalność, ale konfiguracja i eksploatacja multi-wan jest dość uciążliwa. Tylko jeden przykład: jeśli odwiedzasz niektóre strony jednocześnie z dwóch adresów IP, to może im się to nie spodobać, przestaną działać => "internet nie działa".

Biorąc pod uwagę to doświadczenie, zdecydowałem, że multihoming na razie nie jest priorytetem, tylko failover. Chociaż wydaje się, że w ostatnich wersjach Linux wszystko powinno działać jedną komendą w stylu:

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

Zatem, aby uniknąć jednego punktu awarii, bierzemy 2 BPI, każdy podłączamy do jednego dostawcy, łączymy je między sobą i połączenie między nimi realizujemy dynamicznym routowaniem przez bird/OSPF.

Następnie na każdym ogłaszamy ten sam adres IP w przypadku, gdy usługa jest dostępna (internet, DNS). To znaczy, że trasę domyślną będziemy ustawiać nie sami, a za pomocą bird. Rozwiązanie podpatrzyłem tutaj .

Tej funkcjonalności na razie nie wdrożyłem, podstępny koronawirus znów się wtrącił (nie wszystko dotarło z Aliexpress; kolejny sklep internetowy, Layta, obiecał dostarczenie w ciągu tygodnia, a minął już ponad miesiąc; drugi dostawca nie zdążył poprowadzić kabla przed kwarantanną, udało mu się tylko wywiercić dziurę w ścianie na kabel).

Jak zamówić R64

Sama płyta w oficjalnym sklepie SinoVoip.
Lepiej też od razu zamówić:

  • zasilacz + podać standard wtyczki EU lub US
  • odprowadzanie ciepła: radiatory/wentylatory; ponieważ nagrzewa się zarówno CPU, jak i chipset switcha
  • antena do wifi, na przykład

Jest jeden problem - cena dostawy od jakiegoś czasu stała się nieadekwatnie wysoka w oficjalnym sklepie. Menedżerka Judy Huang przekonywała mnie, że nie ma błędu i można wybrać ePacket za 5 USD, ale widziałem, że dla Rosji dostępna jest tylko EMS za >33 USD. Niezbyt przyjemne, ale nie krytyczne. Zresztą, jeśli wybiorę jakikolwiek inny kraj do dostawy (przepatrzyłem wszystkie kontynenty), dostawa wyniesie ~5 USD. Rusofobia?.. Ale potem odkryłem, że dla Francji cena dostawy również wynosi ~30 USD i uspokoiłem się.

Ostatecznie Judy zaproponowała, żeby złożyć zamówienie, ale nie płacić (hint: wpłacić na kartę mniej, aby płatność nie przeszła automatycznie); napisać do niej, a ona obniży cenę dostawy do normalnej. Sukces.

Problemy

Nie wszystko działa jeszcze idealnie.

Wydajność

Polecenia Ansible=Python wykonują się powoli, nawet puste, przez 20-30 sekund; o rząd wielkości dłużej niż na laptopie x86. Z początku wykonują się wystarczająco szybko, ~3 sekundy, potem nagle zwalniają. Może to wynika z przegrzewającego się CPU (throttling). Kod w Go też działa długo:

# запрос метрик для прометея из 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 działa, ale na Armbianie gdzieś po jednej dobie przestaje, wyświetla:

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
...

Tylko restart pomaga. Trzeba dalej się z tym zająć.

Ethernet

Ethernet działa, ale po ~doby pakiety (DHCP) od R64 przestają przychodzić.
Restart interfejsu pomaga:

ifdown br0; sleep 30; ifup br0

Sterownik nowy, jeszcze nie przyjęty do jądra, mam nadzieję, że Chińczyk Landen Chao doprowadzi do końca.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster