Назад | Перейти на главную страницу

Очень низкая пропускная способность TCP OpenVPN (порт 100 Мбит, низкая загрузка ЦП)

У меня очень низкая скорость передачи данных OpenVPN между двумя серверами. В ответ на этот вопрос я назову серверы Сервер A и Сервер B.

И сервер A, и сервер B работают под управлением CentOS 6.6. Оба расположены в центрах обработки данных с линией 100 Мбит / с, а скорость передачи данных между двумя серверами за пределами OpenVPN приближается к ~ 88 Мбит / с.

Однако, когда я пытаюсь передать какие-либо файлы через соединение OpenVPN, которое я установил между сервером A и сервером B, я получаю примерно 6,5 Мбит / с.

Результаты тестирования от 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

Помимо этих тестов OpenVPN iperf, оба сервера практически полностью простаивают с нулевой нагрузкой.

Серверу A назначен IP 10.0.0.1, и это сервер OpenVPN. Серверу B назначен IP-адрес 10.0.0.2, и он является клиентом OpenVPN.

Конфигурация OpenVPN для Сервера A следующая:

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

Конфигурация OpenVPN для Сервера B следующая:

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

Что заметил:

1. Моей первой мыслью было то, что я был узким местом процессора на сервере. OpenVPN является однопоточным, и оба этих сервера работают с процессорами Intel Xeon L5520, которые не являются самыми быстрыми. Однако я запустил top во время одного из тестов iperf и нажал 1 для просмотра использования ЦП по ядрам и обнаружил, что загрузка ЦП была очень низкой для каждого ядра:

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. Во время работы iperf время пинга значительно увеличивается по туннелю OpenVPN. Когда iperf не запущен, время отклика по туннелю составляет 60 мс (нормальное время). Но когда iperf работает и загружает большой трафик, время пинга становится нестабильным. Ниже вы можете увидеть, как время пинга стабильно до 4-го пинга, когда я запустил тест 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. Как упоминалось выше, я запускал iperf вне туннеля OpenVPN, и пропускная способность была нормальной - ~ 88 Мбит / с постоянно.

Что я пробовал:

1. Я подумал, что сжатие может все испортить, поэтому отключил сжатие, удалив comp-lzo из обоих конфигов и перезапуска OpenVPN. Без улучшения.

2. Несмотря на то, что ранее я обнаружил, что загрузка ЦП была низкой, я подумал, что шифр по умолчанию может быть слишком интенсивным, чтобы система могла с ним справиться. Я добавил cipher RC2-40-CBC в оба конфига (очень легкий шифр) и перезапустил OpenVPN. Без улучшения.

3. Я читал на различных форумах о том, как настройка фрагмента, mssfix и mtu-tun может помочь с производительностью. Я играл с несколькими вариациями, как описано в Эта статья, но опять же без улучшений.

Есть идеи о том, что могло вызвать такую ​​низкую производительность OpenVPN?

После большого количества настроек в Google и файлах конфигурации я нашел решение. Теперь я получаю стабильную скорость 60 Мбит / с и всплеск до 80 Мбит / с. Это немного медленнее, чем скорость передачи, которую я получаю за пределами VPN, но я думаю, что это настолько хорошо, насколько это возможно.

Первым шагом было установить sndbuf 0 и rcvbuf 0 в конфигурации OpenVPN как для сервера, так и для клиента.

Я внес это изменение, увидев предложение сделать это на сообщение на публичном форуме (который является английским переводом Русский оригинальный пост) который я процитирую здесь:

На дворе июль 2004 года. Обычная скорость домашнего интернета в развитых странах составляет 256-1024 Кбит / с, в менее развитых странах - 56 Кбит / с. Linux 2.6.7 был выпущен не так давно, а 2.6.8, где TCP Windows Size Scaling будет включен по умолчанию, будет выпущен только через месяц. OpenVPN находится в активной разработке уже 3 года, почти вышла версия 2.0. Один из разработчиков решает добавить код для буфера сокета, я думаю, чтобы унифицировать размеры буфера между ОС. В Windows что-то идет не так с MTU адаптеров, если заданы настраиваемые размеры буферов, поэтому в итоге он преобразован в следующий код:

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

Если вы использовали OpenVPN, вы должны знать, что он может работать через TCP и UDP. Если вы установите для пользовательского значения буфера сокета TCP значение 64 КБ, алгоритм масштабирования размера окна TCP не сможет настроить размер окна более 64 КБ. Что это значит? Это означает, что если вы подключаетесь к другому VPN-сайту по длинному толстому каналу, то есть из США в Россию с пингом около 100 мс, вы не сможете получить скорость более 5,12 Мбит / с с настройками буфера OpenVPN по умолчанию. Вам потребуется буфер размером не менее 640 КБ, чтобы получить скорость передачи 50 Мбит / с по этой ссылке. UDP будет работать быстрее, потому что у него нет размера окна, но он также не будет работать очень быстро.

Как вы уже догадались, последняя версия OpenVPN по-прежнему использует размер буфера сокета 64 КБ. Как нам исправить эту проблему? Лучший способ - запретить OpenVPN устанавливать собственные размеры буфера. Вы должны добавить следующий код в файлы конфигурации сервера и клиента:

sndbuf 0
rcvbuf 0

Далее автор описывает, как передать клиенту настройки размера буфера, если вы сами не контролируете конфигурацию клиента.

После того как я внес эти изменения, моя пропускная способность увеличилась до 20 Мбит / с. Затем я увидел, что загрузка ЦП на одном ядре была немного высокой, поэтому я удалил comp-lzo (сжатие) из конфигурации как на клиенте, так и на сервере. Эврика! Скорость передачи данных выросла до 60 Мбит / с при постоянной и до 80 Мбит / с серийно.

Надеюсь, это поможет кому-то еще решить свои проблемы с медлительностью OpenVPN!

После нескольких попыток я нашел хорошее решение. В моем случае ответ @Elliot не помог. Погуглив больше, я обнаружил, что этот фрагмент нужно добавить в конфигурацию сервера, которая выполнила задание

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

У меня есть небольшой сервер OpenVPN, работающий на Малина PI3 и теперь я получаю 71 Мбит / с нисходящий канал и 16 Мбит / с восходящий канал. Загрузка ограничена из-за мощности процессора. Прямо сейчас моя конфигурация следующая:

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 с OpenSSL 1.0.2l

Это так странно, что проблема с конфигурацией буфера по умолчанию все еще существует.

[РЕДАКТИРОВАТЬ] Мой файл client.ovpn имеет такую ​​структуру:

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>

Согласно конфигурации, вы используете TCP в качестве транспорта для туннеля. Рассмотрите возможность использования UDP вместо TCP, так как сложенные TCP-соединения создают проблемы в ситуациях потери пакетов.

Как ссылку см. Почему TCP поверх TCP - плохая идея

У нас есть два межконтинентальных сервера, которые связаны друг с другом, скорость между ними колеблется около 220 Мбит / с.

Однако внутри туннеля (UDP) OpenVPN скорость будет в среднем 21 Мбит / с - примерно в 10 раз медленнее.

(Между серверами существует значительная задержка: около 130 мс, а передачи измерялись с помощью Iperf3 в режиме TCP.)

Пробовал все предложения по ответам здесь на момент написания этой статьи, и ничего не помогло.

Единственное, что наконец-то помогло, это немного:

--txqueuelen 4000

Согласно справочному руководству OpenVPN:

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

После установки этого параметра на сервере и клиенте я смог достичь той же скорости прямого соединения (~ 250 Мбит / с) и в туннеле OpenVPN.

Я уже использовал rcvbuf 0 и sndbuf 0, но хотя бы в одиночестве, они совсем не помогли.

Я нашел эти рекомендации в обоих: эта страница на форумах OpenVPN, а также в эта страница в вики UDPspeeder.

С другой стороны: я смог достичь более высоких скоростей, используя передачу UDP в iperf, но это также привело бы к достаточно высокой потере пакетов.

Если по какой-то причине вам нужно использовать VPN для туннелирования двух мест с потерями ссылок, я бы посоветовал подумать об использовании какого-то туннеля с прямым исправлением ошибок (FEC) под самой VPN. Мне удалось найти два, с которыми мне удалось поработать:

  • Вышеупомянутое UDPspeeder, который туннелирует UDP-соединения;
  • kcptun, который туннелирует TCP-соединения;

Оба могут очень помочь с потерей пакетов (в первую очередь за счет увеличения пропускной способности) и, в конечном итоге, даже привести к более высокой пропускной способности данных, даже с дополнительными накладными расходами, что действительно здорово, если вы спросите меня.

(Это потому что потеря пакетов действительно может испортить сеть, особенно TCP. См. Страницу 6.)

Я бы предпочел использовать OpenVPN на UDP по всем обычным причинам, но мне было трудно иметь дело с UDPspeeder, когда у вас и задержка более 100 мс, и скорость> 10 Мбит / с.

kcptun, однако, отлично работал с очень небольшими настройками, и на самом деле действительно увеличили пропускную способность наших серверов друг с другом. знак равно

В расширенном примечании, Вот вы можете найти более подробные объяснения по настройке некоторых частей производительности OpenVPN.

Для меня у меня был VPS-сервер с настройкой openvpn-сервера в Японии, и мое клиентское соединение использовало DDWRT в клиентском режиме OpenVPN в Нью-Йорке. Я получал только 1-2 Мбит / с на 100-битном соединении. Лучшее, для чего мне удалось оптимизировать, было 5 Мбит / с, чего было достаточно для того, что мне было нужно, и оптимизировано настолько, насколько я могу это сделать, я считаю.

Мои настройки сервера 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

Мои настройки клиента DDWRT OpenVPN также видны на моем снимке экрана:

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