[Ninux-Calabria] OpenVPN su OpenWRT: howto, test, prestazioni, integrazione, etc.

Stefano De Carlo stefanauss a gmail.com
Dom 20 Lug 2014 18:55:44 UTC


TL; DR: OpenVPN non ce la fa a criptare tunnel && mantenere throughput
su questi routerini. Le ragioni di tutto questo non sono ovvie. Tuttavia
si conferma la migliore alternativa.

====

Ciao a tutti,

Dopo aver manovrato con GRE [1] e L2TP [2], mi sono dedicato un po' ad
una configurazione di tunneling in OpenWRT fatta con il molto più
popolare OpenVPN.

Ai nuovi arrivati in ML spiego brevemente la premessa: stiamo cercando
il miglior meccanismo di tunneling possibile tra una serie di
alternative, con l'obbiettivo di integrarlo e supportarlo nel firmware
Ninux cosentino/calabrese (NinucsWrt) [3]. Questo meccanismo consentirà
ai Ninuxers di "scegliersi" il proprio gateway tra i vari nodi della
rete, e la principale utilità pratica di questa cosa è che significa
poter condividere la propria connessione *ad Internet* solo con chi si
desidera, e per il resto essere connessi tutti-con-tutti dentro Ninux.
Non è semplice perché ci sono molte variabili da considerare: stabilità,
facilità di configurazione, manutenibilità, prestazioni, spazio
occupato, etc.

Non ho ancora un tutorial passo-passo client-server come per GRE e L2TP:
mi sono dedicato principalmente a prendere io stesso confidenza con
OpenVPN, ma soprattutto a rispondere all'elefante nella stanza: il più
grande vantaggio di OpenVPN sulle altre alternative è la sicurezza, ma
OpenVPN cryptato su questi router domestici ha abbastanza prestazioni
per gestire la condivisione della tipica banda ADSL?

Nei test che ho fatto la risposta è stata: quasi sicuramente no.

PeppeLinux si era portato avanti col lavoro nelle scorse settimane e
aveva riportato che in un caso operativo l'utilizzo di OpenVPN su una
connessione a 900 KB/s gli aveva consentito solo di sfruttarne 350 KB/s
quando usato in modalità cifrata (openvpn-openssl). Aveva dunque
ripiegato sulla versione in plain-text (openvpn-nossl) ed era tornato al
100% di banda.
A me è suonato strano e ho voluto fare dei test più approfonditi.

SERVER: TL-WR1043NDv1 @ Capizzanux, AA 12.09 stock + openvpn-openssl
CLIENT: TL-WR1043NDv1 @ HPCC, NinucsWrt AA 14.07 beta +
openvpn-{openssl,polarssl,nossl}.
LINK: NanoStation di test in HPCC, -79/-80, CCQ 98%, Airmax C/Q 35/17
SETTINGS OPENVPN: compressione attiva, protocollo TCP, device tun

Innanzitutto, c'era da stabilire la baseline delle prestazioni del
router. Per far questo c'è l'apposito benchmark incluso nel pacchetto
openssl-utils

# openssl speed

OpenSSL 1.0.1g 7 Apr 2014
built on: Tue Apr  8 17:43:03 UTC 2014
options:bn(64,32) rc4(ptr,char) des(idx,cisc,2,long) aes(partial)
blowfish(ptr)
compiler: ccache_cc -fPIC -DOPENSSL_PIC -DZLIB_SHARED -DZLIB
-DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H
-I/build/ar71xx/generic/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/include
-I/build/ar71xx/generic/staging_dir/target-mips_r2_uClibc-0.9.33.2/include
-I/build/ar71xx/generic/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/usr/include
-I/build/ar71xx/generic/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/include
-DOPENSSL_SMALL_FOOTPRINT -DHAVE_CRYPTODEV -DOPENSSL_NO_ERR -DTERMIO -Os
-pipe -mips32r2 -mtune=mips32r2 -fno-caller-saves -fhonour-copts
-Wno-error=unused-but-set-variable -msoft-float -fpic
-fomit-frame-pointer -Wall -DSHA1_ASM -DSHA256_ASM -DAES_ASM
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192
bytes
md2                  0.00         0.00         0.00         0.00        
0.00
mdc2                 0.00         0.00         0.00         0.00        
0.00
md4               1337.23k     4809.70k    15041.46k    32107.76k   
46368.45k
md5               1064.83k     3757.20k    10761.25k    21661.97k   
29593.60k
hmac(md5)         1732.11k     5608.89k    14695.18k    24586.76k   
30465.91k
sha1              1055.08k     3430.31k     8514.10k    13732.27k   
17264.42k
rmd160               0.00         0.00         0.00         0.00        
0.00
rc4              18328.98k    19548.02k    20286.68k    20678.97k   
20756.95k
des cbc           2795.99k     2870.77k     2982.02k     2868.67k    
2924.46k
des ede3          1023.99k     1033.51k     1050.51k     1037.87k    
1051.16k
idea cbc             0.00         0.00         0.00         0.00        
0.00
seed cbc          3640.35k     3790.84k     3840.18k     3971.45k    
3870.01k
rc2 cbc           3358.52k     3558.51k     3491.34k     3468.89k    
3536.55k
rc5-32/12 cbc        0.00         0.00         0.00         0.00        
0.00
blowfish cbc      5773.93k     6349.70k     6478.39k     6630.76k    
6508.25k
cast cbc          5856.78k     6375.54k     6488.18k     6562.22k    
6550.73k
aes-128 cbc       4606.32k     5032.80k     5069.35k     5077.92k    
5134.22k
aes-192 cbc       4040.48k     4341.22k     4553.13k     4437.22k    
4526.08k
aes-256 cbc       3606.39k     3812.04k     3942.31k     3882.37k    
3932.72k
camellia-128 cbc        0.00         0.00         0.00        
0.00         0.00
camellia-192 cbc        0.00         0.00         0.00        
0.00         0.00
camellia-256 cbc        0.00         0.00         0.00        
0.00         0.00
sha256            1165.47k     2794.21k     5133.20k     6440.37k    
6968.77k
sha512             349.74k     1382.64k     2070.35k     2824.91k    
3245.29k
whirlpool          255.43k      501.51k      803.70k      939.13k    
1013.30k
aes-128 ige       4608.48k     5287.40k     5537.48k     5580.26k    
5542.97k
aes-192 ige       4018.42k     4547.74k     4701.36k     4762.67k    
4784.36k
aes-256 ige       3626.96k     3937.06k     4008.14k     4188.34k    
4173.88k
ghash             5440.17k     5565.77k     5676.30k     5745.31k    
5840.38k
                  sign    verify    sign/s verify/s
rsa  512 bits 0.006894s 0.000578s    145.1   1729.7
rsa 1024 bits 0.034429s 0.001729s     29.0    578.5
rsa 2048 bits 0.210870s 0.006085s      4.7    164.3
rsa 4096 bits 1.461429s 0.022796s      0.7     43.9
                  sign    verify    sign/s verify/s
dsa  512 bits 0.005801s 0.006825s    172.4    146.5
dsa 1024 bits 0.016839s 0.020652s     59.4     48.4
dsa 2048 bits 0.060375s 0.074000s     16.6     13.5

di particolare interesse per noi è la riga relativa a "blowfish cbc",
che è l'algo di criptazione di default di OpenVPN, nonché il più
performante del set supportato [4], che mostra come il router è capace
di criptare a ritmi di 6500 KB/s in un test puramente di CPU. Si tratta
di 50 Mbit/s, quindi come algoritmo grezzo ci siamo.

Passo successivo, stabilire il throughput nudo del link: ~14.5 Mbps

stefanauss a barney:~$ iperf -c 10.87.7.1 -i 5 -t 250
------------------------------------------------------------
Client connecting to 10.87.7.1, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[  3] local 10.87.80.127 port 50872 connected with 10.87.7.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 5.0 sec  8.62 MBytes  14.5 Mbits/sec
[  3]  5.0-10.0 sec  8.12 MBytes  13.6 Mbits/sec
[  3] 10.0-15.0 sec  8.50 MBytes  14.3 Mbits/sec
[  3] 15.0-20.0 sec  8.75 MBytes  14.7 Mbits/sec
[  3] 20.0-25.0 sec  8.50 MBytes  14.3 Mbits/sec
[  3] 25.0-30.0 sec  8.50 MBytes  14.3 Mbits/sec
[  3] 30.0-35.0 sec  8.50 MBytes  14.3 Mbits/sec
[  3] 35.0-40.0 sec  8.62 MBytes  14.5 Mbits/sec

Fatto questo, si passa a fare lo stesso percorso ma criptando il
traffico attraverso la VPN criptata+compressa: si nota che a causa del
link così-così l'effetto della compressione impiega un po' ad azionarsi
ma quando lo fa il buffering fa la differenza: ~22 Mbps!

stefanauss a barney:~$ iperf -c 100.67.0.1 -i 5 -t 250
------------------------------------------------------------
Client connecting to 100.67.0.1, TCP port 5001
TCP window size: 45.0 KByte (default)
------------------------------------------------------------
[  3] local 10.87.80.127 port 42508 connected with 100.67.0.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 5.0 sec  6.00 MBytes  10.1 Mbits/sec
[  3]  5.0-10.0 sec  6.50 MBytes  10.9 Mbits/sec
[  3] 10.0-15.0 sec  6.50 MBytes  10.9 Mbits/sec
[  3] 15.0-20.0 sec  6.50 MBytes  10.9 Mbits/sec
[  3] 20.0-25.0 sec  6.25 MBytes  10.5 Mbits/sec
[  3] 25.0-30.0 sec  6.50 MBytes  10.9 Mbits/sec
[  3] 30.0-35.0 sec  9.12 MBytes  15.3 Mbits/sec
[  3] 35.0-40.0 sec  13.0 MBytes  21.8 Mbits/sec
[  3] 40.0-45.0 sec  12.5 MBytes  21.0 Mbits/sec
[  3] 45.0-50.0 sec  12.9 MBytes  21.6 Mbits/sec
[  3] 50.0-55.0 sec  13.0 MBytes  21.8 Mbits/sec

In tutto questo "top" segnala CPU intorno al 50%. Tutto consistente col
benchmark iniziale! [5]
Il degrado comincia a sorgere proprio quando si passa ad utilizzare
l'endpoint VPN come default gateway.
Ecco uno speedtest direttamente da Capizzanux: ~1375 KB/s

root a CapizzanuxGRND:~# time wget --output-document=/dev/null
http://188.165.12.10
6/files/100Mio.dat
Connecting to 188.165.12.106 (188.165.12.106:80)
null                 100% |********************************|   100M 
0:00:00 ETA
real    1m 14.46s
user    0m 0.96s
sys    0m 3.03s

Ed ecco l'identico speedtest attraverso la VPN: 982 KB/s, ovvero il 72%
della capacità.

stefanauss a barney:~$ time wget --output-document=/dev/null
http://188.165.12.106/files/100Mio.dat
--2014-07-18 19:10:00--  http://188.165.12.106/files/100Mio.dat
Connessione a 188.165.12.106:80... connesso.
Richiesta HTTP inviata, in attesa di risposta... 200 OK
Lunghezza: 104857600 (100M) [application/octet-stream]
Salvataggio in: "/dev/null"

100%[=======================================>] 104.857.600 1,13MB/s   in
1m 44s

2014-07-18 19:11:44 (982 KB/s) - "/dev/null" salvato [104857600/104857600]


real    1m44.430s
user    0m1.236s
sys    0m3.395s

Non raccapricciante come il 39% stimato dal caso di Peppe, ma comunque
probabilmente un deal-breaker quando si tratta di condividere l'ADSL.
Come prevedibile, senza la criptazione le cose evolvono nella direzione
giusta. Ho testato sia con openvpn-nossl, sia semplicemente aggiungendo
l'opzione cipher none in /etc/config/openvpn.
Chiaramente le baseline da Capizzanux (Ninux & ADSL throughput)
rimangono quelle riportate sopra.
Ecco il test di throughput attraverso VPN non criptata stavolta: saliamo
a 28 Mbps!

stefanauss a barney:~$ iperf -c 100.67.0.1 -i 5 -t
250------------------------------------------------------------
Client connecting to 100.67.0.1, TCP port 5001
TCP window size: 45.0 KByte (default)
------------------------------------------------------------
[  3] local 10.87.80.127 port 42629 connected with 100.67.0.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 5.0 sec  7.62 MBytes  12.8 Mbits/sec
[  3]  5.0-10.0 sec  7.62 MBytes  12.8 Mbits/sec
[  3] 10.0-15.0 sec  7.38 MBytes  12.4 Mbits/sec
[  3] 15.0-20.0 sec  7.88 MBytes  13.2 Mbits/sec
[  3] 20.0-25.0 sec  7.75 MBytes  13.0 Mbits/sec
[  3] 25.0-30.0 sec  7.75 MBytes  13.0 Mbits/sec
[  3] 30.0-35.0 sec  7.62 MBytes  12.8 Mbits/sec
[  3] 35.0-40.0 sec  7.50 MBytes  12.6 Mbits/sec
[  3] 40.0-45.0 sec  10.4 MBytes  17.4 Mbits/sec
[  3] 45.0-50.0 sec  17.0 MBytes  28.5 Mbits/sec
[  3] 50.0-55.0 sec  16.6 MBytes  27.9 Mbits/sec
[  3] 55.0-60.0 sec  16.6 MBytes  27.9 Mbits/sec
[  3] 60.0-65.0 sec  16.9 MBytes  28.3 Mbits/sec
[  3] 65.0-70.0 sec  16.6 MBytes  27.9 Mbits/sec
[  3] 70.0-75.0 sec  16.8 MBytes  28.1 Mbits/sec
[  3] 75.0-80.0 sec  16.6 MBytes  27.9 Mbits/sec

E lo speedtest come default gateway stavolta svela risultati che vanno
precisati: si tratta di solo 100 KB/s in più, ma la cosa è da imputare
al jitter piuttosto alto del link wireless utilizzato (mi era
impossibile fare di meglio con le location a mia disposizione e senza
interrompere servizi): nei periodi "buoni" questo test ha segnato
velocità sostenute di 1.35 MB/s, quindi siamo al 99% di capacità! Coi
link in produzione queste sarebbero le nostre velocità standard.

stefanauss a barney:~$ time wget --output-document=/dev/null
http://188.165.12.106/files/100Mio.dat
--2014-07-18 19:15:30--  http://188.165.12.106/files/100Mio.dat
Connessione a 188.165.12.106:80... connesso.
Richiesta HTTP inviata, in attesa di risposta... 200 OK
Lunghezza: 104857600 (100M) [application/octet-stream]
Salvataggio in: "/dev/null"

100%[=======================================>] 104.857.600 1,20MB/s   in
92s   

2014-07-18 19:17:02 (1,08 MB/s) - "/dev/null" salvato [104857600/104857600]


real    1m32.608s
user    0m1.225s
sys    0m3.266s

A margine va detto che, quando client o server criptati erano serviti su
qualcosa di più carrozzato di OpenWrt, sono riuscito a sfruttare il 100%
della banda.

Server: 1043nd-Capizzanux / Client: rPi: 1.40 MB/s (100% della ADSL di
Peppe)
Server: PfSense-HPCC / Client: 1043nd-Stefanauss: 7.71 Mbps (100% della
ADSL di Stefanauss)

Premesso che: con un link wireless eccellente e un router più carrozzato
(1043v2/3600/4300) sarebbe probabilmente possibile ottenere qualcosa in
più del 72% di cui sopra anche con VPN criptata.
Non essendo, come detto sopra, la pura potenza di calcolo il problema,
le mie ipotesi più educate (amburgerismo @ Vin-San) sono:
- memory bandwidth infima del SoC: è durante il trasferimento da/alla
memoria del pacchetto criptato/decriptato/viceversa che la latenza
uccide il throughput
- qualche passaggio in userspace poco performante. I miei test si sono
svolti in AA, su BB non mi aspetterei niente di diverso ma se il
problema è qui potrebbero esserci delle sorprese.

È tutto. Manterrei questo thread per discutere delle problematiche di
integrazione e prestazionali di OpenVPN in OpenWRT; per il NinucsWrt
development ci sono gli altri thread.

Stefanauss.

[1] http://ml.ninux.org/pipermail/calabria/2014-June/003366.html
[2] http://ml.ninux.org/pipermail/calabria/2014-July/003455.html
[3] http://test.ninux.org/~stefanauss/NinucsWRT/
[4] Per sapere quali sono quelli supportati, lanciate openvpn con la
sola opzione --show-ciphers.
[5] Per riferimento, con un iperf da 10.87.1.0/24 (rete Ninux "fissa"
HPCC) a 10.87.7.1, Capizzanux, ottengo 21 Mbps di throughput puro Ninux,
durante il quale i router non vanno oltre il 6%-7% di CPU.

-------------- parte successiva --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://ml.ninux.org/pipermail/calabria/attachments/20140720/19a2406f/attachment.pgp>


Maggiori informazioni sulla lista Calabria