Openvpn большое время отклика и низкая скорость. Ускоряем OpenVPN за $9.99* или встраиваем Orange Pi One в роутер

18.04.2019

Время от времени, мне встречаются темы на форумах, в которых люди соединяют несколько офисов с использованием OpenVPN и получают низкую скорость, сильно ниже скорости канала. У кого-то это может быть 20 Мбит/с при канале в 100 Мбит/с с обеих сторон, а кто-то еле получает и 400 Кбит/с на 2 Мбит/с ADSL/3G и высоким пингом. Зачастую, таким людям советуют увеличить MTU на VPN-интерфейсе до чрезвычайно больших значений, вроде 48000, или же поиграться с параметром mssfix. Частично это помогает, но скорость внутри VPN все еще очень далека от канальной. Иногда все сваливают на то, что OpenVPN — userspace-решение, и это его нормальная скорость, учитывая всякие шифрования и HMAC"и. Абсурд!

Немного истории

На дворе июль 2004 года. Типичная скорость домашнего интернета в развитых странах составляет 256 Кбит/с-1 Мбит/с, в менее развитых — 56 Кбит/с. Ядро Linux 2.6.7 вышло не так давно, а 2.6.8, в котором TCP Window Scale включен по умолчанию, выйдет только через месяц. Проект OpenVPN развивается уже 3 года как, к релизу готовится версия 2.0.
Один из разработчиков добавляет код, который устанавливает буфер приема и отправки сокета по умолчанию в 64 КБ, вероятно, чтобы хоть как-то унифицировать размер буфера между платформами и не зависеть от системных настроек. Однако в Windows что-то поломали, и указание размера буферов у сокета приводит к странным проблемам с MTU на всех адаптерах в системе. В конечном итоге, в релиз OpenVPN 2.0-beta8 попадает следующий код:
#ifndef WIN32 o->rcvbuf = 65536; o->sndbuf = 65536; #endif

Немного технической информации

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

Что делать?

Как вы могли уже догадаться, данный размер буфера все еще применяется в самом последнем релизе OpenVPN. Как же нам исправить ситуацию? Самый корректный вариант — запретить OpenVPN менять размер буферов у сокета.
Нужно добавить следующие строки как в серверный, так и в клиентский конфигурационные файлы:
sndbuf 0 rcvbuf 0
В этом случае, размер буфера будет задаваться настройками ОС. Для Linux и TCP это значение будет меняться согласно значениям из net.ipv4.tcp_rmem и net.ipv4.tcp_wmem, а для UDP — фиксированное значение net.core.rmem_default и net.core.wmem_default, деленное на два.

Если же по какой-то причине нет возможности поменять конфигурационные файлы клиента, следует отдавать достаточно большие размеры буферов с сервера:
sndbuf 0 rcvbuf 0 push "sndbuf 393216" push "rcvbuf 393216"
UDP несколько отличается от TCP. У него нет аналога Window Scale, ему не требуются подтверждения о доставке пакета на транспортном уровне, но низкий размер буфера приема может замедлить и его, если буфер забивается раньше, чем OpenVPN успевает его считывать. Если скорость внутри туннеля кажется вам низкой даже с изменениями, описанными выше, то, возможно, имеет смысл либо увеличить размер буфера для всей системы целиком, увеличив net.core.rmem_default и net.core.wmem_default, либо всегда указывать определенный размер буфера в конфигурационном файле:
sndbuf 393216 rcvbuf 393216 push "sndbuf 393216" push "rcvbuf 393216"

Но у меня Windows!

Если у вас и OpenVPN-сервер работает на Windows-машине, и все клиенты подключаются только из-под Windows, то поздравляю — вам ничего менять не нужно, у вас и так все должно работать быстро.

Время от времени, мне встречаются темы на форумах, в которых люди соединяют несколько офисов с использованием OpenVPN и получают низкую скорость, сильно ниже скорости канала. У кого-то это может быть 20 Мбит/с при канале в 100 Мбит/с с обеих сторон, а кто-то еле получает и 400 Кбит/с на 2 Мбит/с ADSL/3G и высоким пингом. Зачастую, таким людям советуют увеличить MTU на VPN-интерфейсе до чрезвычайно больших значений, вроде 48000, или же поиграться с параметром mssfix. Частично это помогает, но скорость внутри VPN все еще очень далека от канальной. Иногда все сваливают на то, что OpenVPN - userspace-решение, и это его нормальная скорость, учитывая всякие шифрования и HMAC"и. Абсурд!

Немного истории

На дворе июль 2004 года. Типичная скорость домашнего интернета в развитых странах составляет 256 Кбит/с-1 Мбит/с, в менее развитых - 56 Кбит/с. Ядро Linux 2.6.7 вышло не так давно, а 2.6.8, в котором TCP Window Scale включен по умолчанию, выйдет только через месяц. Проект OpenVPN развивается уже 3 года как, к релизу готовится версия 2.0.
Один из разработчиков добавляет код, который устанавливает буфер приема и отправки сокета по умолчанию в 64 КБ, вероятно, чтобы хоть как-то унифицировать размер буфера между платформами и не зависеть от системных настроек. Однако в Windows что-то поломали, и указание размера буферов у сокета приводит к странным проблемам с MTU на всех адаптерах в системе. В конечном итоге, в релиз OpenVPN 2.0-beta8 попадает следующий код:

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

Немного технической информации

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

Что делать?

Как вы могли уже догадаться, данный размер буфера все еще применяется в самом последнем релизе OpenVPN. Как же нам исправить ситуацию? Самый корректный вариант - запретить OpenVPN менять размер буферов у сокета.
Нужно добавить следующие строки как в серверный, так и в клиентский конфигурационные файлы:

Sndbuf 0 rcvbuf 0

В этом случае, размер буфера будет задаваться настройками ОС. Для Linux и TCP это значение будет меняться согласно значениям из net.ipv4.tcp_rmem и net.ipv4.tcp_wmem, а для UDP - фиксированное значение net.core.rmem_default и net.core.wmem_default, деленное на два.

Если же по какой-то причине нет возможности поменять конфигурационные файлы клиента, следует отдавать достаточно большие размеры буферов с сервера:

Sndbuf 0 rcvbuf 0 push "sndbuf 393216" push "rcvbuf 393216"

UDP несколько отличается от TCP. У него нет аналога Window Scale, ему не требуются подтверждения о доставке пакета на транспортном уровне, но низкий размер буфера приема может замедлить и его, если буфер забивается раньше, чем OpenVPN успевает его считывать. Если скорость внутри туннеля кажется вам низкой даже с изменениями, описанными выше, то, возможно, имеет смысл либо увеличить размер буфера для всей системы целиком, увеличив net.core.rmem_default и net.core.wmem_default, либо всегда указывать определенный размер буфера в конфигурационном файле:

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

Но у меня Windows!

Если у вас и OpenVPN-сервер работает на Windows-машине, и все клиенты подключаются только из-под Windows, то поздравляю - вам ничего менять не нужно, у вас и так все должно работать быстро.

Производительность OpenVPN является для многих администраторов больной темой. Очень часто скорость внутри туннеля в разы отличается от скорости канала в меньшую сторону. К сожалению многие сетевые ресурсы дают по этому поводу неверные или вообще вредные советы, либо заявляют, что это "нормально", мол шифрование, работа в userspace, накладные расходы и т.д., и т.п. Мало кто пытается разобраться в реальных механизмах, влияющих на производительность OpenVPN, другая же часть просто дает готовые рекомендации, не поясняя откуда они получены и почему надо делать именно так.

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

Стали разбираться вместе и обнаружили, что при реальной скорости канала около 15 Мбит/с OpenVPN не разгоняется свыше 3-4 Мбит/с, да и это, по словам нашего коллеги, еще "хорошая" скорость.

Перед тем, как обратиться за помощью наш знакомый перепробовал массу рекомендаций из сети, но ни одна из них не принесла успеха. При этом выяснилось, что доступ к двум новым точкам осуществляется по радиоканалу и пинг, в зависимости от погодных условий, находится в пределах 100-200 мс, в то время как к остальным филиалам он гораздо ниже, около 50 мс.

А теперь самое время вспомнить о таком параметре, как размер буферов приема и отправки. Если не вдаваться в подробности работы сетевых протоколов, то размер буфера определяет максимальный объем данных, которые могут быть переданы за единицу времени. Наиболее чувствительный к размеру буфера протокол TCP, так как размер окна TCP, т.е. количества одновременно отправляемых пакетов не может превышать размер буфера. Протокол UDP работает иначе, но и его производительность также ограничена размерами буферов.

Проведем простую аналогию. Нам нужно перевезти некий груз из пункта A в пункты Б и В, в пункт Б ведет хорошая автомагистраль со средней скоростью 90 км/ч, а в пункт B грунтовка, разогнаться на которой можно до 45 км/ч. Понятно, что, используя один и тот-же транспорт за одно и тоже время в пункт Б удастся доставить в два раза больше груза, чем в пункт В.

В сетях все происходит аналогично. Исторически сложилось так, что размер буфера OpenVPN составляет 64 КБ, в Linux системах это значение устанавливается принудительно, в Windows вроде бы как отдается на откуп ОС, но по факту чаще всего мы имеем все те же 64 КБ. В этом несложно убедиться заглянув в лог:

Socket Buffers: R= S=

Теперь вооружимся калькулятором и посчитаем. Объем данных отправляемых или принимаемых за одну передачу не может превышать объем буфера, а количество отправок в единицу времени ограничено скоростью прохождения пакетов (пингом). Таким образом при пинге в 50 мс мы можем осуществить 20 передач в секунду, а при 200 мс только пять. Отправить за один раз мы можем 64 КБ, считаем, при 50 мс это будет 1280 КБ/сек (1,25 МБ/с) или 10 Мбит/с. Результат довольно неплохой и при общей скорости канала филиалов в 15-20 Мбит/с данное ограничение легко списать на служебный трафик, шифрование и т.п.

При пинге в 200 мс все гораздо более печально, мы упремся в потолок 320 КБ/с или 2,5 Мбит/с. Таким образом, путем несложных математических вычислений мы ответили на главный вопрос: "Почему тормозит OpenVPN". Как видим, ни шифрование, ни "накладные расходы" тут не причем, проблема в физических ограничениях канала.

Что же делать? Ответ прост - увеличивать размер буферов. Сделать это просто, откройте конфигурационный файл сервера и добавьте туда строки:

Sndbuf 524288
rcvbuf 524288

Это установит объем буферов в размере 512 КБ и позволит достичь скоростей при 50 мс - 80 Мбит/с, а при 200 мс - 20 Мбит/с.

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

Push "sndbuf 524288"
push "rcvbuf 524288"

Чтобы убедиться, что настройки работают заглянем в лог на клиенте, там мы должны обнаружить примерно следующее:

Socket Buffers: R= S=

Также в ряде источников выражается мнение, что данная проблема (размеров буфера) актуальна только для Linux систем, а в Windows все должно работать быстро, однако уже у другого клиента мы обнаружили что в одном из филиалов, при проводном подключении, Windows Server 2008 R2 устанавливал размеры буферов в 8 КБ:

Socket Buffers: R= S=

А это даже при хорошем пинге в 50 мс не более 1,25 МБит/с, при скорости канала в десятки раз превышающем это значение.

В нашем же случае увеличение буфера до 512 КБ позволило достичь скоростей 11-12 Мбит/с, что вполне соответствует реальной скорости канала.

Поэтому мы советуем не полагаться на значения по умолчанию, а взять управление в свои руки, и реально оценив условия доступа рассчитать и установить необходимые значения буферов приема и отправки, что позволит полностью утилизировать канал и более не задаваться вопросом: "Почему OpenVPN тормозит?".

Описанная проблема присуща только ветке OpenVPN 2.3, в 2.4 размеры буферов не меняются без требования пользователя.

Время от времени, мне встречаются темы на форумах, в которых люди соединяют несколько офисов с использованием OpenVPN и получают низкую скорость, сильно ниже скорости канала. У кого-то это может быть 20 Мбит/с при канале в 100 Мбит/с с обеих сторон, а кто-то еле получает и 400 Кбит/с на 2 Мбит/с ADSL/3G и высоким пингом. Зачастую, таким людям советуют увеличить MTU на VPN-интерфейсе до чрезвычайно больших значений, вроде 48000, или же поиграться с параметром mssfix. Частично это помогает, но скорость внутри VPN все еще очень далека от канальной. Иногда все сваливают на то, что OpenVPN - userspace-решение, и это его нормальная скорость, учитывая всякие шифрования и HMAC"и. Абсурд!

Немного истории

На дворе июль 2004 года. Типичная скорость домашнего интернета в развитых странах составляет 256 Кбит/с-1 Мбит/с, в менее развитых - 56 Кбит/с. Ядро Linux 2.6.7 вышло не так давно, а 2.6.8, в котором TCP Window Scale включен по умолчанию, выйдет только через месяц. Проект OpenVPN развивается уже 3 года как, к релизу готовится версия 2.0.
Один из разработчиков добавляет код, который устанавливает буфер приема и отправки сокета по умолчанию в 64 КБ, вероятно, чтобы хоть как-то унифицировать размер буфера между платформами и не зависеть от системных настроек. Однако в Windows что-то поломали, и указание размера буферов у сокета приводит к странным проблемам с MTU на всех адаптерах в системе. В конечном итоге, в релиз OpenVPN 2.0-beta8 попадает следующий код:
#ifndef WIN32 o->rcvbuf = 65536; o->sndbuf = 65536; #endif

Немного технической информации

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

Что делать?

Как вы могли уже догадаться, данный размер буфера все еще применяется в самом последнем релизе OpenVPN. Как же нам исправить ситуацию? Самый корректный вариант - запретить OpenVPN менять размер буферов у сокета.
Нужно добавить следующие строки как в серверный, так и в клиентский конфигурационные файлы:
sndbuf 0 rcvbuf 0
В этом случае, размер буфера будет задаваться настройками ОС. Для Linux и TCP это значение будет меняться согласно значениям из net.ipv4.tcp_rmem и net.ipv4.tcp_wmem, а для UDP - фиксированное значение net.core.rmem_default и net.core.wmem_default, деленное на два.

Если же по какой-то причине нет возможности поменять конфигурационные файлы клиента, следует отдавать достаточно большие размеры буферов с сервера:
sndbuf 0 rcvbuf 0 push "sndbuf 393216" push "rcvbuf 393216"
UDP несколько отличается от TCP. У него нет аналога Window Scale, ему не требуются подтверждения о доставке пакета на транспортном уровне, но низкий размер буфера приема может замедлить и его, если буфер забивается раньше, чем OpenVPN успевает его считывать. Если скорость внутри туннеля кажется вам низкой даже с изменениями, описанными выше, то, возможно, имеет смысл либо увеличить размер буфера для всей системы целиком, увеличив net.core.rmem_default и net.core.wmem_default, либо всегда указывать определенный размер буфера в конфигурационном файле:
sndbuf 393216 rcvbuf 393216 push "sndbuf 393216" push "rcvbuf 393216"

Но у меня Windows!

Если у вас и OpenVPN-сервер работает на Windows-машине, и все клиенты подключаются только из-под Windows, то поздравляю - вам ничего менять не нужно, у вас и так все должно работать быстро.

Описанная проблема присуща только ветке OpenVPN 2.3, в 2.4 размеры буферов не меняются без требования пользователя.

Время от времени, мне встречаются темы на форумах, в которых люди соединяют несколько офисов с использованием OpenVPN и получают низкую скорость, сильно ниже скорости канала. У кого-то это может быть 20 Мбит/с при канале в 100 Мбит/с с обеих сторон, а кто-то еле получает и 400 Кбит/с на 2 Мбит/с ADSL/3G и высоким пингом. Зачастую, таким людям советуют увеличить MTU на VPN-интерфейсе до чрезвычайно больших значений, вроде 48000, или же поиграться с параметром mssfix. Частично это помогает, но скорость внутри VPN все еще очень далека от канальной. Иногда все сваливают на то, что OpenVPN - userspace-решение, и это его нормальная скорость, учитывая всякие шифрования и HMAC"и. Абсурд!

Немного истории

На дворе июль 2004 года. Типичная скорость домашнего интернета в развитых странах составляет 256 Кбит/с-1 Мбит/с, в менее развитых - 56 Кбит/с. Ядро Linux 2.6.7 вышло не так давно, а 2.6.8, в котором TCP Window Scale включен по умолчанию, выйдет только через месяц. Проект OpenVPN развивается уже 3 года как, к релизу готовится версия 2.0.
Один из разработчиков добавляет код, который устанавливает буфер приема и отправки сокета по умолчанию в 64 КБ, вероятно, чтобы хоть как-то унифицировать размер буфера между платформами и не зависеть от системных настроек. Однако в Windows что-то поломали, и указание размера буферов у сокета приводит к странным проблемам с MTU на всех адаптерах в системе. В конечном итоге, в релиз OpenVPN 2.0-beta8 попадает следующий код:
#ifndef WIN32 o->rcvbuf = 65536; o->sndbuf = 65536; #endif

Немного технической информации

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

Что делать?

Как вы могли уже догадаться, данный размер буфера все еще применяется в самом последнем релизе OpenVPN. Как же нам исправить ситуацию? Самый корректный вариант - запретить OpenVPN менять размер буферов у сокета.
Нужно добавить следующие строки как в серверный, так и в клиентский конфигурационные файлы:
sndbuf 0 rcvbuf 0
В этом случае, размер буфера будет задаваться настройками ОС. Для Linux и TCP это значение будет меняться согласно значениям из net.ipv4.tcp_rmem и net.ipv4.tcp_wmem, а для UDP - фиксированное значение net.core.rmem_default и net.core.wmem_default, деленное на два.

Если же по какой-то причине нет возможности поменять конфигурационные файлы клиента, следует отдавать достаточно большие размеры буферов с сервера:
sndbuf 0 rcvbuf 0 push "sndbuf 393216" push "rcvbuf 393216"
UDP несколько отличается от TCP. У него нет аналога Window Scale, ему не требуются подтверждения о доставке пакета на транспортном уровне, но низкий размер буфера приема может замедлить и его, если буфер забивается раньше, чем OpenVPN успевает его считывать. Если скорость внутри туннеля кажется вам низкой даже с изменениями, описанными выше, то, возможно, имеет смысл либо увеличить размер буфера для всей системы целиком, увеличив net.core.rmem_default и net.core.wmem_default, либо всегда указывать определенный размер буфера в конфигурационном файле:
sndbuf 393216 rcvbuf 393216 push "sndbuf 393216" push "rcvbuf 393216"

Но у меня Windows!

Если у вас и OpenVPN-сервер работает на Windows-машине, и все клиенты подключаются только из-под Windows, то поздравляю - вам ничего менять не нужно, у вас и так все должно работать быстро.