Muy bajo rendimiento de TCP OpenVPN (puerto de 100Mbit, baja utilización de CPU)

27

Estoy experimentando tasas de transferencia de OpenVPN extremadamente lentas entre dos servidores. Para esta pregunta, llamaré a los servidores Servidor A y Servidor B.

Tanto el servidor A como el servidor B ejecutan CentOS 6.6. Ambos se encuentran en centros de datos con una línea de 100Mbit y las transferencias de datos entre los dos servidores fuera de OpenVPN se ejecutan cerca de ~ 88Mbps.

Sin embargo, cuando intento transferir cualquier archivo a través de la conexión OpenVPN que he establecido entre el Servidor A y el Servidor B, obtengo un rendimiento de alrededor de 6.5Mbps.

Resultados de la prueba de iperf:

[  4] local 10.0.0.1 port 5001 connected with 10.0.0.2 port 49184
[  4]  0.0-10.0 sec  7.38 MBytes  6.19 Mbits/sec
[  4]  0.0-10.5 sec  7.75 MBytes  6.21 Mbits/sec
[  5] local 10.0.0.1 port 5001 connected with 10.0.0.2 port 49185
[  5]  0.0-10.0 sec  7.40 MBytes  6.21 Mbits/sec
[  5]  0.0-10.4 sec  7.75 MBytes  6.26 Mbits/sec

Además de estas pruebas iperf de OpenVPN, ambos servidores están prácticamente completamente inactivos con carga cero.

El servidor A tiene asignada la IP 10.0.0.1 y es el servidor OpenVPN. El servidor B tiene asignada la IP 10.0.0.2 y es el cliente OpenVPN.

La configuración de OpenVPN para el Servidor A es la siguiente:

port 1194
proto tcp-server
dev tun0
ifconfig 10.0.0.1 10.0.0.2
secret static.key
comp-lzo
verb 3

La configuración de OpenVPN para el Servidor B es la siguiente:

port 1194
proto tcp-client
dev tun0
remote 204.11.60.69
ifconfig 10.0.0.2 10.0.0.1
secret static.key
comp-lzo
verb 3

Lo que he notado:

1. Mi primer pensamiento fue que estaba bloqueando la CPU en el servidor. OpenVPN es de un solo subproceso y ambos servidores ejecutan procesadores Intel Xeon L5520 que no son los más rápidos. Sin embargo, ejecuté un topcomando durante una de las pruebas de iperf y presioné 1para ver la utilización de la CPU por núcleo y descubrí que la carga de la CPU era muy baja en cada núcleo:

top - 14:32:51 up 13:56,  2 users,  load average: 0.22, 0.08, 0.06
Tasks: 257 total,   1 running, 256 sleeping,   0 stopped,   0 zombie
Cpu0  :  2.4%us,  1.4%sy,  0.0%ni, 94.8%id,  0.3%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu1  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu2  :  0.0%us,  0.0%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.3%st
Cpu3  :  0.3%us,  0.0%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu4  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu5  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu6  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu7  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu8  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu9  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu10 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu11 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu12 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu13 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu14 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu15 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    946768k total,   633640k used,   313128k free,    68168k buffers
Swap:  4192188k total,        0k used,  4192188k free,   361572k cached

2. Los tiempos de ping aumentan considerablemente sobre el túnel OpenVPN mientras se ejecuta iperf. Cuando iperf no se está ejecutando, los tiempos de ping sobre el túnel son consistentemente de 60 ms (normal). Pero cuando iperf se está ejecutando y empujando mucho tráfico, los tiempos de ping se vuelven erráticos. Puede ver a continuación cómo los tiempos de ping son estables hasta el cuarto ping cuando comencé la prueba de iperf:

PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=60.1 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=60.1 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=60.2 ms
** iperf test begins **
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=146 ms
64 bytes from 10.0.0.2: icmp_seq=5 ttl=64 time=114 ms
64 bytes from 10.0.0.2: icmp_seq=6 ttl=64 time=85.6 ms
64 bytes from 10.0.0.2: icmp_seq=7 ttl=64 time=176 ms
64 bytes from 10.0.0.2: icmp_seq=8 ttl=64 time=204 ms
64 bytes from 10.0.0.2: icmp_seq=9 ttl=64 time=231 ms
64 bytes from 10.0.0.2: icmp_seq=10 ttl=64 time=197 ms
64 bytes from 10.0.0.2: icmp_seq=11 ttl=64 time=233 ms
64 bytes from 10.0.0.2: icmp_seq=12 ttl=64 time=152 ms
64 bytes from 10.0.0.2: icmp_seq=13 ttl=64 time=216 ms

3. Como se mencionó anteriormente, ejecuté iperf fuera del túnel OpenVPN y el rendimiento fue normal - ~ 88Mbps consistentemente.

Lo que probé:

1. Pensé que la compresión podría estar ensuciando las cosas, así que apagué la compresión al eliminar comp-lzoambas configuraciones y reiniciar OpenVPN. Sin mejora.

2. Aunque anteriormente descubrí que la utilización de la CPU era baja, pensé que el cifrado predeterminado podría ser demasiado intenso para que el sistema lo mantuviera. Así que agregué cipher RC2-40-CBCa ambas configuraciones (un cifrado muy liviano) y reinicié OpenVPN. Sin mejora.

3. Leí en varios foros acerca de cómo ajustar el fragmento, mssfix y mtu-tun podría ayudar con el rendimiento. Jugué con algunas variaciones como se describe en este artículo , pero de nuevo, no hay mejora.

¿Alguna idea sobre lo que podría estar causando un rendimiento tan pobre de OpenVPN?

Elliot B.
fuente
¿Algún enlace, comentario de aquí ayuda? forums.openvpn.net/topic10593.html
Matt
La mayoría de las sugerencias que hay son cosas que ya he probado: 1. verificar el cuello de botella de la CPU, 2. verificar las velocidades de transferencia sin VPN, 3. alternar la compresión, 4. elegir un cifrado más rápido, etc. Sin suerte con ninguno de ellos todavía: - / Es extraño. Además de la velocidad lenta y los tiempos de ping altos / volátiles, no veo otra indicación de dónde podría estar el cuello de botella.
Elliot B.
¿Ambas máquinas están en el mismo centro de datos? 60 ms dentro del mismo centro de datos es bastante alto. Podría sentir la tentación de intentarlo, cipher noneaunque dudo que ayude.
Zoredache
@Zoredache Lo siento, no tenía claras las ubicaciones de los servidores: el servidor A está en Dallas y el servidor B está en Seattle.
Elliot B.
¿Has comprobado MTU? Esp: parámetros tun-mtu, fragment y mssfix? Documentación
Lenniey

Respuestas:

26

Después de muchos ajustes en Google y en el archivo de configuración, encontré la solución. Ahora estoy obteniendo velocidades sostenidas de 60Mbps y hasta 80Mbps. Es un poco más lento que las tasas de transferencia que recibo fuera de la VPN, pero creo que es tan bueno como sea posible.

El primer paso fue establecer sndbuf 0y rcvbuf 0en la configuración de OpenVPN tanto para el servidor como para el cliente.

Hice ese cambio después de ver una sugerencia para hacerlo en una publicación del foro público (que es una traducción al inglés de una publicación original en ruso ) que citaré aquí:

Es julio de 2004. La velocidad habitual de Internet en el hogar en los países desarrollados es de 256-1024 Kbit / s, en los países menos desarrollados es de 56 Kbit / s. Linux 2.6.7 se lanzó no hace mucho tiempo y 2.6.8, donde TCP Windows Size Scaling estaría habilitado de forma predeterminada, solo se lanzará en un mes. OpenVPN está en desarrollo activo desde hace 3 años, la versión 2.0 está casi lanzada. Uno de los desarrolladores decide agregar un código para el buffer de socket, creo que unifica los tamaños de buffer entre los sistemas operativos. En Windows, algo sale mal con la MTU de los adaptadores si se establecen tamaños de búferes personalizados, por lo que finalmente se transformó en el siguiente código:

#ifndef WIN32
o->rcvbuf = 65536;
o->sndbuf = 65536;
#endif

Si usó OpenVPN, debe saber que puede funcionar a través de TCP y UDP. Si establece un valor de búfer de socket TCP personalizado tan bajo como 64 KB, el algoritmo de escala de tamaño de ventana TCP no puede ajustar el tamaño de ventana a más de 64 KB. Qué significa eso? Eso significa que si se está conectando a otro sitio VPN a través de un enlace largo y grueso, es decir, EE. UU. A Rusia con un ping de aproximadamente 100 ms, no puede obtener una velocidad de más de 5.12 Mbit / s con la configuración predeterminada del búfer OpenVPN. Necesita al menos 640 KB de búfer para obtener 50 Mbit / s a ​​través de ese enlace. UDP funcionaría más rápido porque no tiene tamaño de ventana pero tampoco funcionará muy rápido.

Como ya puede suponer, la última versión de OpenVPN todavía utiliza un tamaño de búfer de socket de 64 KB. ¿Cómo debemos solucionar este problema? La mejor manera es no permitir que OpenVPN establezca tamaños de búfer personalizados. Debe agregar el siguiente código en los archivos de configuración del servidor y del cliente:

sndbuf 0
rcvbuf 0

El autor continúa describiendo cómo empujar los ajustes de tamaño del búfer al cliente si usted no tiene el control de la configuración del cliente usted mismo.

Después de hacer esos cambios, mi tasa de rendimiento aumentó a 20Mbps. Luego vi que la utilización de la CPU era un poco alta en un solo núcleo, así que eliminé comp-lzo(compresión) de la configuración tanto en el cliente como en el servidor. Eureka! Las velocidades de transferencia aumentaron hasta 60Mbps sostenidas y 80Mbps en ráfaga.

¡Espero que esto ayude a alguien más a resolver sus propios problemas con la lentitud de OpenVPN!

Elliot B.
fuente
4

Después de algunos intentos, he llegado a una buena solución. En mi caso, la respuesta de @ Elliot no ayudó. Buscando en Google más, descubrí este fragmento para agregar la configuración del servidor que hizo el trabajo

sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"

Tengo un pequeño servidor OpenVPN ejecutándose en un Raspberry PI3 y ahora obtengo un enlace descendente de 71 Mbps y un enlace ascendente de 16Mbps . La descarga es limitada ya que la potencia de la CPU. En este momento, mi configuración es la siguiente:

client-to-client
duplicate-cn
keepalive 10 120
cipher AES-128-CBC
#cipher AES-256-CBC <<<---- lowers the speed to around 50Mbps, still not bad
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
tun-mtu 9000

OpenVPN 2.4.0 arm-unknown-linux-gnueabihf con OpenSSL 1.0.2l

Se siente tan extraño que todavía existe un problema sobre la configuración predeterminada de un búfer.

[EDITAR] Mi archivo client.ovpn está estructurado así:

client
dev tun
proto tcp
remote SERVER.IP.ADDRESS.HERE
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
ns-cert-type server
tun-mtu 9000
key-direction 1
cipher AES-128-CBC
comp-lzo
verb 1
mute 20
<ca>
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN RSA PRIVATE KEY-----
[...]
-----END RSA PRIVATE KEY-----
</key>
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
[...]
-----END OpenVPN Static key V1-----
</tls-auth>
Núcleo
fuente
Establecer el tamaño del búfer me ayudó.
Rolf
¿Qué pusiste en el archivo .ovpn del cliente?
Patoshi パ ト シ
@Patoshi パ ト シ He comentado sndbuf y recbuf, puse el cifrado y la compresión correspondientes y dejé los parámetros predeterminados.
Kernel
@ Kernel, ¿puedes mostrarme lo que tienes en tu cliente? Estoy haciendo una conexión OpenVPN desde Hong Kong a Nueva York y es aleatoriamente lenta y a veces se desconecta. No estoy seguro de por qué.
Patoshi パ ト シ
@Patoshi パ ト シ He editado mi respuesta, compruébalo nuevamente. No obstante, le sugiero que intente utilizar UDP, ya que podría ayudarlo a abordar el problema de un enlace inestable con su servidor. De hecho, es solo una suposición, nunca he tratado de comparar esta solución en esta situación.
Kernel
1

Según la configuración, está utilizando TCP como transporte para el túnel. Considere usar UDP en lugar de TCP ya que las conexiones TCP apiladas tienden a crear problemas en situaciones de pérdida de paquetes.

Como referencia, vea Por qué TCP sobre TCP es una mala idea

Lairsdragon
fuente
Lamentablemente UDP no es una opción para nosotros. Necesitamos asegurarnos de que los paquetes de datos que transmitimos lleguen como se espera. Sin embargo, experimentamos con UDP anteriormente y las bajas tasas de transferencia seguían siendo un problema.
Elliot B.
66
We need to ensure that the data packets we transmit arrive as expected.y no es eso manejado por el protocolo que se está tunelizando? ¿Por qué crees que tu túnel debe ser lo que hace cumplir eso?
Zoredache
Ese es probablemente el caso, pero estamos usando OpenVPN para una implementación DRBD asincrónica de larga distancia (es decir, replicación del sistema de archivos). La integridad de los datos es realmente importante, por lo que aunque DRBD probablemente tenga mecanismos internos para verificar la integridad de la transferencia, prefiero mantenerlo en TCP. De cualquier manera, cuando lo teníamos en UDP todavía teníamos un bajo rendimiento.
Elliot B.
3
@ElliotB. Como DRBD usa TCP para la replicación, se retransmitirá en caso de que se pierda el paquete UDP OpenVPN. En realidad, usando TCP en este caso, harás dos retransferencias en lugar de una ... una de las cuales será descartada. Y puede estar creando una ventana bastante larga sin tráfico DRBD (incluso puede obtener una replicación rota debido a esto). Una vez que obtenga algo de paquete en la ruta, verá cuán malo es pensar esto.
Fox
@Fox ¡Gracias por proporcionar una aclaración! De hecho, DRBD utiliza TCP (drbd.linbit.com/users-guide/s-prepare-network.html). La sugerencia anterior de Lairsdragon de cambiar a UDP no era relevante en ese momento porque UDP también estaba experimentando tasas de transferencia extremadamente bajas, pero desde la implementación de la solución que publiqué anteriormente, hicimos el cambio a UDP y experimentamos otra ganancia de rendimiento de unos pocos Mbps.
Elliot B.
1

Tenemos dos servidores intercontinentales que se vinculan entre sí, las velocidades entre ellos rondan los 220 Mbit / s.

Sin embargo, dentro del túnel OpenVPN (UDP), las velocidades promediarían 21 Mbit / s, aproximadamente 10 veces más lento.

(Hay una latencia significativa entre los servidores: alrededor de 130 ms, y las transferencias se midieron usando Iperf3 en modo TCP).

Intenté todas las sugerencias sobre respuestas aquí a partir de este escrito, y nada ayudó.

Lo único que finalmente ayudó fue este poquito:

--txqueuelen 4000

De acuerdo con el manual de referencia de OpenVPN:

–txqueuelen n 
(Linux only) Set the TX queue length on the TUN/TAP interface. Currently defaults to 100.

Después de configurar este parámetro en el servidor y el cliente, pude alcanzar las mismas velocidades de 'enlace directo' (~ 250Mbit / s) también bajo el túnel OpenVPN.

Ya estaba usando el rcvbuf 0y sndbuf 0, pero al menos solo , no me ayudaron en absoluto.

He encontrado estas recomendaciones en ambos: esta página en los foros de OpenVPN , y también en esta página en el wiki UDPspeeder .

En otra nota: pude alcanzar velocidades más altas usando transferencias UDP en iperf, pero al hacerlo también incurriría en una pérdida de paquetes razonablemente alta.

Si por casualidad necesita usar VPN para hacer un túnel en dos lugares con enlaces con pérdida, le aconsejo que considere usar algún tipo de túnel de corrección de errores hacia adelante (FEC) debajo de la propia VPN. Los dos que he logrado encontrar y trabajar son:

Ambos pueden ayudar mucho con la pérdida de paquetes (al gastar más ancho de banda en primer lugar) y, en última instancia, incluso conducir a un mayor rendimiento de datos, incluso con la sobrecarga adicional, que es realmente genial si me preguntas.

(Esto se debe a que la pérdida de paquetes realmente puede estropear una red , especialmente TCP . Consulte la página 6.)

Hubiera preferido usar OpenVPN en UDP, por todas las razones habituales, pero me ha resultado difícil tratar con UDPspeeder cuando tienes más de 100 ms de latencia y> 10 Mbit / s de velocidad.

Sin embargo, kcptun funcionó muy bien con muy pocos ajustes, y en realidad aumentó el rendimiento de nuestros servidores entre nosotros. =)

En una nota extendida, aquí puede encontrar algunas explicaciones más detalladas sobre cómo modificar algunas partes del rendimiento de OpenVPN.

Vinícius M
fuente
0

Para mí, tenía un servidor VPS con configuración de servidor openvpn en Japón y mi conexión de cliente estaba usando un DDWRT en modo cliente OpenVPN en Nueva York. Estaba obteniendo solo 1-2mbps en una conexión de 100mbit. Lo mejor que pude optimizar fue 5mbps, que fue suficiente para lo que necesitaba, lo más optimizado que puedo hacer, creo.

Mi configuración del servidor OpenVPN:

tun-mtu 9000
sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"
comp-lzo
txqueuelen 4000
######
port 10111
proto udp
dev tun
user nobody
group nobody
persist-key
persist-tun
keepalive 10 120
topology subnet
server x.x.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "dhcp-option DNS 1.0.0.1"
push "dhcp-option DNS 1.1.1.1"
push "redirect-gateway def1 bypass-dhcp"
dh none
ecdh-curve prime256v1
#tls-crypt tls-crypt.key 0
crl-verify crl.pem
ca ca.crt
cert server_IzA1QdFzHLRFfEoQ.crt
key server_IzA1QdFzHLRFfEoQ.key
auth SHA256
#cipher AES-128-GCM
#cipher AES-128-CBC
#ncp-ciphers AES-128-GCM
#ncp-ciphers AES-128-CBC
#tls-server
#tls-version-min 1.2
#tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256
#tls-cipher TLS-DHE-RSA-WITH-AES-128-CBC-SHA
status /var/log/openvpn/status.log
verb 3

Mi configuración de cliente DDWRT OpenVPN también se ve en mi captura de pantalla:

tun-mtu 9000
comp-lzo
##########
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
verify-x509-name server_IzA1QdFzHLRFfEoQ name
auth SHA256
auth-nocache
setenv opt block-outside-dns # Prevent Windows 10 DNS leak
verb 3

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Patoshi パ ト シ
fuente