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.

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

Następnie, najłatwiej jest załadować system operacyjny z karty SD: pobieramy z 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=noxferwsadzamy 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/mmcblk0boot0Producent R64 (Chiny) udostępnił ten plik binarny . 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ąż , 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 na BPI R64.
A właściwie tak: część userspace — Armbian, a jądro pochodzi z repozytorium -a. Najnowszy obraz można pobrać .
Cała aktywność związana z rozwojem oprogramowania R64 odbywa się na . 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: , , .
Rozwój takiego rozwiązania zrealizowałem za pomocą Ansible: .
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-1Następnie trzeba w podobny sposób wdrożyć na VPS nasz VPN:
ansible-playbook ./router.py -l current-vpnTutaj 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-1Ach tak, przed wszystkimi tymi operacjami należy wygenerować sekrety (w szczególności klucze Wireguard) do folderu ./secrets, katalog powinien wyglądać .
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: yesi 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 .
Ta funkcja nosi nazwę pybook zrealizowano . Dokumentacji do pybooka jeszcze nie ma, później naprawię ten błąd.
Co myślisz 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 : 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-preprodAuto 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
EOFTODO: 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 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 5Zatem, 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 .
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 .
Lepiej też od razu zamówić:
- + podać standard wtyczki EU lub US
- odprowadzanie ciepła: radiatory/wentylatory; ponieważ nagrzewa się zarówno CPU, jak i chipset switcha
- antena do wifi,
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
51700Wifi
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 .
Ethernet
Ethernet działa, ale po ~doby pakiety (DHCP) od R64 przestają przychodzić.
Restart interfejsu pomaga:
ifdown br0; sleep 30; ifup br0Sterownik nowy, jeszcze nie przyjęty do jądra, mam nadzieję, że Chińczyk Landen Chao .
Źródło: habr.com
