Amint említettem már, egy Raspberry Pi sok dologra alkalmas. A „vas” lehetőségei természetesen szerények, így hamar elérhetjük a rendelkezésre álló teljesítmény korlátait. Ebben a cikkben egy ilyen korlátról írnék, azaz milyen sávszélesség érhető el egy Raspberry Pi (RPi) alkalmazásával a titkosított OpenVPN hálózaton. Előre bocsátom, az alapértelmezett beállításokkal elérhető sávszélesség szánalmas, de kis finomhangolással megsokszorozható!
Miért OpenVPN?
Ha nem vagyunk befolyással a VPN szerver és a VPN kliens között valamennyi routerre, akkor könnyen hiábavaló szélmalomharcot kezdhetünk a hálózatok üzemeltetőivel. Kérhetjük ugyan, hogy engedjék át, NAT-olják a GRE, IPsec vagy egyéb protokollokat. Legtöbbször azonban csak a vállrándítós „nálunk minden rendben, oldjátok meg, ahogy akarjátok” lesz a jutalmunk, de ettől persze a VPN-ünk még nem kezd el működni. Küzdhetünk, de a legtöbbször nem érdemes. Az elmúlt 20 év tapasztalata alapján jelentem ki, hogy a fehér tollszín gyakoribb a hollóknál, mint a hozzáértés az informatikai szakembereknél. Vállalom a kövezést…
Az OpenVPN, szemben a PPTP és L2TP/IPsec megoldásokkal csupán egyetlen UDP vagy TCP portot igényel a működéséhez. Sokkal egyszerűbb dolgunk van ezzel a sok „koca-rendszergazda”, „hozzáértő szomszéd” és „informatika tanár” által üzemeltetett hálózaton. Ez is szempont, sőt, néha ez a leglényegesebb. Ilyen világban élünk.
OpenVPN beállítások
Az OpenVPN telepítéséről, kulcsok generálásáról vannak jól használható leírások (linkek a cikk végén), így erre most nem térek ki. Nézzük a konkrét konfigurációs állományokat.
OpenVPN szerver (Ubuntu) beállításai (/etc/openvpn/server.conf)
port 1194 dev tun proto udp persist-key persist-tun ca ca.crt cert ubuntu-server.crt key ubuntu-server.key dh dh1024.pem server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt keepalive 10 120 status openvpn-status.log verb 3
OpenVPN kliens (Raspbian) beállításai (/etc/openvpn/client.conf)
client dev tun proto udp remote ubuntu-server 1194 resolv-retry infinite nobind persist-key persist-tun ca ca.crt cert raspberry.crt key raspberry.key ns-cert-type server verb 3
A tömörítést első körben nem kapcsoltam be (comp-lzo), mert elsődlegesen a nyers átvitel érdekelt. A VPN kapcsolat felépítése után teszteltem az elérhető sebességet, egy iperf gyorsteszt első körben elegendő volt.
root@ubuntu-server:~# iperf -s
root@raspberrypi:~# iperf -c 10.8.0.1 -r
Az átvitel első látásra szánalmas, másodikra pedig már-már kétségbeejtő.
12 / 15 Mb/s
Tizenkettő megabit másodpercenként. Régen ez még lobogó haj érzésével lett volna egyenértékű, de azóta eltelt 10+ év.
Néhány teszt után egyértelművé vált, hogy a Raspberry Pi CPU teljesítménye limitálja leginkább a kapcsolat sebességét. Nosza, kikapcsoltam a titkosítást és a csomagok aláírását.
cipher none auth none
Újra teszteltem, remélve, hogy legalább a titkosítatlan kapcsolat rendben lesz.
22,5 / 27 Mb/s
Gyorsult a kapcsolat, de nem annyival, amennyivel kellene. Hová lett a két gép közötti 100 Mb/s körüli sávszélesség kb. 70%-a? Elővettem ismét a manuált, hátha. Az olvasás végére egy tippem volt:
fast-io
A konfigurációs állományokat bővítettem ezzel az opcióval, majd újraépítettem a VPN kapcsolatot. Az újabb teszt is lefutott.
23,9 / 30,6 Mb/s
Remek, mert gyorsult, de alig, titkosítás nélkül még a szánalmas szinten maradt.
Jöhetett az újabb kör, körülnéztem a fejlesztői listákon, felhasználói fórumokon. Mindig elfelejtem, hogy ezek csak arra jók, hogy elüssünk 1-2 órát, és végül meggyőződjünk róla, nem csak mi futottunk gondba. Jó, ha nem vagyunk egyedül a gondunkkal, de megoldást a legritkább esetben kapunk. Most sem volt ez másként. Leginkább azt olvashattam, hogy igen, gyenge hardveren bizony-bizony lassú a VPN. Lassú, de ennyire? Nem hittem el. Eltelt néhány óra a különféle trace-ek kimenetének bámulásával, mire körvonalazódott a helyzet.
Ez a kutyatetem több helyen van elásva
1. A Raspberry Pi ethernet interfésze nem a legjobb. Gyakorlatilag egy USB 2.0 buszra kötött, „gyengécske” smsc95xx. Nem sok terhet képes átvenni a CPU válláról, erről az alábbi parancs kimenete is árulkodik.
root@raspberrypi:~# ethtool -k eth0
Második probléma az RPi USB vezérlője. Az USB 2.0 elvileg 480 Mb/s átvitelre is képes, és ennek a felét valóban képes is elérni egy RPi, de ennek ára van. Az USB busz használata is jelentős mértékben terheli a CPU-t.
A fentiek már bőven elegendő indokkal szolgáltak arra, hogy a 100 Mb/s sebességet LAN-on, VPN és egyéb csalafintaságok nélkül, egy irányban sem képes elérni a Raspberry Pi.
Sokan kritizálják az RPi ezen részét (USB + ETH), de ők nem gondolnak bele, hogy egy jobb ethernet kártya ára bizony a Raspberry Pi teljes árának többszöröse.
2. A VPN kapcsolat egy virtuális hálózati interfészen keresztül bonyolódik, amelynél nyilván a CPU-t terheli valamennyi feladat. Az OpenVPN nem áll jól az optimális kódok tekintetében, ami csak tovább rontja a helyzetet.
A fenti okokra vezethető vissza az, hogy a VPN kapcsolaton elérhető sebesség a közelében sincs az elfogadható szintnek. A legkézenfekvőbb megoldást, a Raspberry Pi túlhajtását elvetettem, hiszen nem az a célom, hogy az eszköz idő előtt menjen a kukába.
Milyen lehetőségek maradtak?
A helyzet egyszerű, meg kell takarítani valahol egy kis erőforrást, hiszen minden megtakarítás növeli az elérhető sebességet. Fontos tudni, hogy az OpenVPN a titkosítást csomagonként végzi, és az OpenSSL algoritmusok erőforrásigénye függ a titkosítandó blokkok méretétől és számától is. Algoritmustól függő, de általában kevesebb erőforrást igényel 1db 16 kilobyteos blokk titkosítása, mint 16 db 1 kilobyteos blokké.
1. Valamivel takarékosabb titkosítási algoritmus
cipher AES-128-CBC auth MD4
Az AES-128-CBC cipher és az MD4 digest (auth) néhány teszt után került kiválasztásra. A teszteléshez az OpenSSL algoritmusok összehasonlító tesztjét használtam.
root@raspberrypi:~# openssl speed
2. Az MTU érték növelése a virtuális interfészeken
tun-mtu 9000 fragment 0 mssfix 0
A tunnel MTU értéke alapesetben a linken elérhető MTU értékéből származtatott, ami jelen esetben, az ethernet hálózaton szokásos 1500 byte-os érték lenne. A virtuális, tun interfészen a fizikai kapcsolattól függetlenül emelhető az MTU értéke, tehát a VPN szerver és kliens között ezzel nem lesz gond. A fragment és mssfix opciókkal az OpenVPN belső fragmentálását kapcsoltam ki. Magától értetődően a fenti beállítások szerver és kliens oldalon is szükségesek voltak.
A VPN újrakapcsolódás után teszt már szebb képet mutatott, az átviteli sebességek javultak.
34.2 / 36.6 Mb/s
Közel háromszor gyorsabb lett a VPN, mint az alapértelmezett beállításokkal. Elvégeztem magasabb tunnel MTU értékekkel is a tesztet. A tesztek eredményét az alábbi táblázatban összefoglaltam.
Ha a csomagoknak át kell menniük valahol egy a tun-mtu paraméterben megadottnál szűkebb interfészen, mondjuk a VPN szerver mögötti hálózaton lévő gépeket is el kell érni, akkor érkezni fog egy Fragmentation Needed ICMP üzenet. Persze ebben az esetben a megemelt MTU előnyeiből nem profitálunk. A 9000-es MTU még a legtöbb fizikai hálózaton is elérhető, de természetesen csak jumbo frameket támogató hálózati eszközökkel.
A végleges VPN kapcsolaton engedélyeztem a tömörítést, ehhez csak az alábbi sort kellett hozzáadni a kliens és szerver beállításaihoz.
comp-lzo
Ezt és a 60000-es tun-mtu értéket kombinálva már elég szép értékeket mutatott az iperf teszt.
160 / 217 Mb/s
Természetesen tudom, hogy ez nem teljesen valós érték, hiszen ritkán adódik annyira jól tömöríthető forgalom, mint a szintetikus, iperf teszt által generált. A fenti eredményen lehetne még kissé tuningolni, pl. a link és a tunnel MTU értékek egymáshoz hangolásával, hogy maximálisan kihasználjuk az 1500-as csomagokat. Ennek azonban a sok, eltérő kapcsolaton lévő végpont miatt nem láttam értelmét.
Legjobb megoldás természetesen egy tisztességes, megfelelően optimalizált VPN szerver/kliens szoftver használata volna. A jelenleg elérhető, opensource megoldások között ilyen sajnos nincs, legyen szó L2TP over IPsec, PPTP vagy egyéb protokollok implementációiról. Csak 1-2 kevésbé rossz van a nagyon rosszak között, nálam jelenleg az OpenVPN a befutó.
Hivatkozások:
http://openvpn.net/
https://wiki.debian.org/OpenVPN
https://help.ubuntu.com/13.10/serverguide/openvpn.html