OpenVPN est lent

Bonjour,

J’ai actuellement plusieurs liaisons OpenVPN actives entre mes machines. Mais, je me suis rendu compte d’un truc un peu gênant, bien qu’ayant des connexion assez rapide, la liaison par le VPN ne dépasse pas 30Mbps :

┌ (gilles@Stardust + 0) (26/07/20 - 11:55:25) (0.78 - 0%) (~)
└% iperf3 -c nut.almtesh.net
Connecting to host nut.almtesh.net, port 5201
[  5] local 2001:bc8:3335:1::2 port 51822 connected to 2001:bc8:3335:: port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  3.08 MBytes  25.9 Mbits/sec   24   86.0 KBytes       
[  5]   1.00-2.00   sec  2.99 MBytes  25.1 Mbits/sec    0    108 KBytes       
[  5]   2.00-3.00   sec  3.54 MBytes  29.7 Mbits/sec    0    129 KBytes       
[  5]   3.00-4.00   sec  4.03 MBytes  33.8 Mbits/sec    9    109 KBytes       
[  5]   4.00-5.00   sec  3.73 MBytes  31.2 Mbits/sec   14   93.8 KBytes       
[  5]   5.00-6.00   sec  3.97 MBytes  33.3 Mbits/sec    0    120 KBytes       
[  5]   6.00-7.00   sec  3.91 MBytes  32.8 Mbits/sec    2    102 KBytes       
[  5]   7.00-8.00   sec  3.24 MBytes  27.1 Mbits/sec    3   86.0 KBytes       
[  5]   8.00-9.00   sec  3.11 MBytes  26.1 Mbits/sec    3   79.5 KBytes       
[  5]   9.00-10.00  sec  3.30 MBytes  27.7 Mbits/sec    0    106 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  34.9 MBytes  29.3 Mbits/sec   55             sender
[  5]   0.00-10.03  sec  34.6 MBytes  29.0 Mbits/sec                  receiver

iperf Done.
gilles has logged on pts/2 from :0.                                                                                                                                                                                                                                                                                        
┌ (gilles@Stardust + 0) (26/07/20 - 12:30:15) (2.26 - 0%) (~)
└% iperf3 -c nut.almtesh.net -R
Connecting to host nut.almtesh.net, port 5201
Reverse mode, remote host nut.almtesh.net is sending
[  5] local 2001:bc8:3335:1::2 port 51826 connected to 2001:bc8:3335:: port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  2.14 MBytes  18.0 Mbits/sec                  
[  5]   1.00-2.00   sec  2.59 MBytes  21.8 Mbits/sec                  
[  5]   2.00-3.00   sec  2.81 MBytes  23.6 Mbits/sec                  
[  5]   3.00-4.00   sec  2.55 MBytes  21.4 Mbits/sec                  
[  5]   4.00-5.00   sec  2.92 MBytes  24.5 Mbits/sec                  
[  5]   5.00-6.00   sec  2.89 MBytes  24.3 Mbits/sec                  
[  5]   6.00-7.00   sec  2.73 MBytes  22.9 Mbits/sec                  
[  5]   7.00-8.00   sec  2.86 MBytes  24.0 Mbits/sec                  
[  5]   8.00-9.00   sec  2.54 MBytes  21.3 Mbits/sec                  
[  5]   9.00-10.00  sec  1.92 MBytes  16.1 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.03  sec  26.6 MBytes  22.3 Mbits/sec  157             sender
[  5]   0.00-10.00  sec  26.0 MBytes  21.8 Mbits/sec                  receiver

iperf Done.

Pour info, voici la vitesse en dehors du VPN :

┌ (gilles@Stardust + 0) (26/07/20 - 12:42:20) (2.07 - 0%) (~)
└% iperf3 -c 51.159.34.87      
Connecting to host 51.159.34.87, port 5201
[  5] local 10.255.1.10 port 53382 connected to 51.159.34.87 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  9.24 MBytes  77.5 Mbits/sec  137    219 KBytes       
[  5]   1.00-2.00   sec  6.90 MBytes  57.9 Mbits/sec    0    239 KBytes       
[  5]   2.00-3.00   sec  7.52 MBytes  63.1 Mbits/sec    0    260 KBytes       
[  5]   3.00-4.00   sec  6.77 MBytes  56.8 Mbits/sec    0    280 KBytes       
[  5]   4.00-5.00   sec  6.65 MBytes  55.8 Mbits/sec    0    300 KBytes       
[  5]   5.00-6.00   sec  6.77 MBytes  56.8 Mbits/sec    0    317 KBytes       
[  5]   6.00-7.00   sec  6.84 MBytes  57.3 Mbits/sec    0    332 KBytes       
[  5]   7.00-8.00   sec  6.90 MBytes  57.9 Mbits/sec    0    349 KBytes       
[  5]   8.00-9.00   sec  6.96 MBytes  58.4 Mbits/sec    0    363 KBytes       
[  5]   9.00-10.00  sec  7.64 MBytes  64.1 Mbits/sec    0    379 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  72.2 MBytes  60.6 Mbits/sec  137             sender
[  5]   0.00-10.07  sec  70.2 MBytes  58.5 Mbits/sec                  receiver

iperf Done.
┌ (gilles@Stardust + 0) (26/07/20 - 12:43:26) (0.82 - 0%) (~)
└% iperf3 -c 51.159.34.87 -R
Connecting to host 51.159.34.87, port 5201
Reverse mode, remote host 51.159.34.87 is sending
[  5] local 10.255.1.10 port 53390 connected to 51.159.34.87 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  33.7 MBytes   283 Mbits/sec                  
[  5]   1.00-2.00   sec  38.2 MBytes   320 Mbits/sec                  
[  5]   2.00-3.00   sec  40.0 MBytes   336 Mbits/sec                  
[  5]   3.00-4.00   sec  41.9 MBytes   351 Mbits/sec                  
[  5]   4.00-5.00   sec  42.0 MBytes   352 Mbits/sec                  
[  5]   5.00-6.00   sec  35.3 MBytes   296 Mbits/sec                  
[  5]   6.00-7.00   sec  36.2 MBytes   304 Mbits/sec                  
[  5]   7.00-8.00   sec  36.8 MBytes   308 Mbits/sec                  
[  5]   8.00-9.00   sec  37.6 MBytes   315 Mbits/sec                  
[  5]   9.00-10.00  sec  37.8 MBytes   317 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.04  sec   383 MBytes   320 Mbits/sec   70             sender
[  5]   0.00-10.00  sec   379 MBytes   318 Mbits/sec                  receiver

iperf Done.

Pour information, les deux nœuds du pont sont en Debian 10. Voici la configuration du serveur :

proto udp6
dev nut2lookout
dev-type tun
port 11000
ifconfig 10.255.255.1 10.255.255.2
route 10.255.1.0 255.255.255.0
route 10.255.2.0 255.255.255.0
route 192.168.100.0 255.255.255.252
tun-ipv6
ifconfig-ipv6 2001:bc8:3335:ff00:: 2001:bc8:3335:ff00::1
route-ipv6 2001:bc8:3335:1::/64 
route-ipv6 2001:bc8:3335:2::/64 
<secret>
secret partagé
</secret>

et celle du client :

remote 51.159.34.87
port 11000
keepalive 10 60
ping-timer-rem
persist-tun
persist-key
dev lookout2nut
dev-type tun
tun-ipv6

ifconfig 10.255.255.2 10.255.255.1
ifconfig-ipv6 2001:bc8:3335:ff00::1 2001:bc8:3335:ff00::

# almtesh.net
route 10.255.0.0 255.255.255.0
route 10.255.255.0 255.255.255.0
route-ipv6 2001:bc8:3335::/48

<secret>
secret partagé
</secret>

Quelques pistes :

  • charge CPU pour le chiffrement/déchiffrement
  • surcharge protocolaire (overhead) de l’encapsulation
  • fragmentation des paquets encapsulants ou encapsulés

Ah, effectivement, la solution serait donc d’utiliser un chiffrement mois gourmand. Je ne sais pas si on peut faire ça et comment on peut le faire, d’autant qu’il me semble que j’utilise déjà le chiffrement le moins fort (avec une clef symétrique)

Je ne pense pas que le protocole OpenVPN soit si lourd que ça. Et puis, quand je fais mes tests de débit, je les fais avec des gros paquets, l’overhead devrait passer inaperçu.

Ça, par contre, je n’ai pas compris.

Avant d’envisager de changer de chiffrement, il faut déterminer si c’est bien le CPU qui limite d’un côté ou de l’autre du VPN. Pour cela il suffit d’observer la charge CPU des deux noeuds à débit max dans chaque sens pendant assez longtemps.

Quand on empile toutes les couches, ça commence à faire :
IPv4 = 20 octets
UDP = 8 octets
OpenVPN = ?
IPv6 = 40 octets
TCP = 20 octets

L’encapsulation peut augmenter la taille des paquets au-delà de la MTU du chemin du tunnel, ce qui peut provoquer de la fragmentation. Deux cas :

  • si la MTU du tunnel n’est pas diminuée en conséquence, le tunnel fragmente après l’encapsulation (le paquet encapsulé n’est pas fragmenté, donc le paquet encapsulant est trop gros et doit être fragmenté)

  • si la MTU du tunnel est diminuée en conséquence, le tunnel fragmente avant l’encapsulation (le paquet encapsulé est trop gros et doit être fragmenté, chaque fragment est transporté dans un paquet encapsulant non fragmenté) ; quand tout se passe bien, TCP devrait s’adapter et limiter la taille des paquets pour éviter la fragmentation.

Dans les deux cas, la fragmentation résulte en l’envoi d’un fragment de taille maximum et d’un fragment de petite taille pour transmettre un paquet complet, ce qui fait chuter le débit effectif sans parler de la charge CPU pour gérer la fragmentation et le réassemblage à l’arrivée.

Je pense que c’est ça, le processus openvpn prend 100 % du CPU sur Lookout (le client, un Raspberry Pi), c’est pour ça que je commence à penser que ça peut être ça.

Et tu ne comptes pas la couche liaison, mais bon, je ne sais pas s’il y en a une dans une interface en tun.

Ah, le MTU est très mal géré sur mon réseau, peut-être une petite optimisation à faire de ce côté. La connexion vers l’extérieur et la connexion VPN ont toutes les deux un MTU de 1500. Je m’amusais à gérer ça quand j’avais une connexion ADSL avec un MTU de 1492 et aucun VPN, mais là, je n’ai même pas réfléchi à la question.

Probablement. Le processeur du Raspberry Pi n’est pas prévu pour faire du chiffrement intensif.

Normalement non. En mode tap c’est 14 octets d’en-tête ethernet.

C’est le cas n° 1, et ce n’est pas idéal : si on envoie un paquet de 1500 octets sur l’interface tun, le paquet encapsulant résultant aura une taille de plus de 1500 octets et devra être fragmenté. Comme les paquets encapsulants et encapsulés sont indépendants du point de vue du noyau, la couche IP n’a aucun moyen de signaler cette fragmentation à l’émetteur du paquet original afin qu’il réduise la taille de ses paquets (contrairement au cas n° 2). Seul le démon openvpn pourrait faire suivre les informations de fragmentation de la couche IP de transport à la couche IP transportée mais ce n’est pas trivial, j’ignore s’il le fait.

Tu pourrais progressivement réduire la MTU sur les interfaces tun des deux côtés pour voir si tu peux gagner un peu de débit. Mais si c’est le CPU qui limite à cause du chiffrement, le gain risque d’être modeste.

une question bête quelle est la vitesse du port RJ du raspberry pi ?
il y a un autre probleme avec le rpi c’est que le bus est en usb 2

Je ne vois pas de raison pour que la limitation du port ou du bus affecte différemment les flux dans le VPN et en dehors du VPN.

Très bonne question, mais deux choses. D’abord, il s’agit du Raspberry Pi 4, ils sont passé à l’USB 3. Le port est donc en Gigabit. Ensuite :

Je peux sans doute utiliser un chiffrement moins gourmand. Ne pas pouvoir dépasser les 30 Mbps avec un processeur quadruple-cœur à 1,5 GHz, c’est un peu rude.

openvpn utilise à fond les 4 coeurs simultanément ?

Non, justement, top indique 100 %, c’est que d’un seul cœur. Mais si on multiplie vite-fait par trois et demi, ça fait à peu plus de 100 Mbps, c’est toujours mieux, mais je ne sais pas du tout comment on fait utiliser toutes les ressources à openvpn.

On ne peut pas. OpenVPN est connu pour ne fonctionner qu’en mono-processus.

A contrario, Wireguard utilise tous les threads d’une machine. Et le fait qu’il réside en grande partie dans le noyau permet de gagner encore plus en performances par rapport à OpenVPN.

Sur un appareil en x86 aux capacités limitées, je fais du gigabit symétrique avec Wireguard alors que je plafonnais à 300 Mbps avec OpenVPN.

Testé sur une Raspberry Pi 4 avec Ubuntu en 64 bits, là aussi Wireguard envoie du pâté !


AnonymousCoward

2 J'aime

Wireguard ? Inconnu au bataillon, que ce soit sur le client ou le serveur. Bizarre, le site nous dit qu’il est dans les dépôts.

Oui il est dans les backports de Buster ou dans les dépôts Bullseye et Sid, c’est plutôt récent.

https://wiki.debian.org/WireGuard

les packages dans buster-backports


AnonymousCoward

Heu, oui, ça résoult le problème pour le serveur, mais pas pour le client. Il n’y a pas de backports dans Raspbian.

Il doit être disponible dans la branche unstable pour le côté serveur :wink:
Sinon tu le compile à la main et tu propose le backport :sweat_smile:

Effectivement, il faut installer les paquets de Wireguard depuis les dépôts de Debian pour l’architecture armhf, si c’est pour Raspbian en 32 bits.

Il existe de nombreuses pages web décrivant l’installation de Wireguard sur Raspberry Pi.

Celle-ci me paraît bien : https://engineerworkshop.com/blog/how-to-set-up-wireguard-on-a-raspberry-pi/

Pour autant que je puisse le voir, la version de Wireguard est actuellement identique pour les suites unstable, testing et buster-backports : 1.0.20200513-1 .

D’après mon expérience pratique, utiliser une distribution en 64 bits pour la Raspberry Pi améliore pas mal les performances de la partie réseau en général.
Mais ce n’est normalement pas nécessaire, y compris sur un accès à Internet de type fibre optique pour un particulier.


AnonymousCoward

Salut,
comme indiqué plus haut OpenVPN ne fonctionne que en mode monothread donc peu importe qu’il y ait un grand nombre de cœur, seul la puissance d’un seul sera utilisé.
Il est également important de savoir que le CPU du raspberry ne prends pas en charge le chiffrement matériel (pas d’instruction aes) ce qui implique une perte colossale de performance.

La piste de la MTU est également à vérifier, de manière générale, sur mes serveurs openVPN qui sont sur le réseau publique, je met la mtu à 1460 d’office. Dans ton cas je te suggère avec la commande Ping de voir la mtu entre tes deux serveurs connectés sans le vpn et ensuite de retirer 40 sur le résultat que tu auras eu afin d’avoir la MTU pour openVPN.