Пользователь
46,9
рейтинг
28 декабря 2014 в 23:38

Администрирование → Почему OpenVPN тормозит?

Время от времени, мне встречаются темы на форумах, в которых люди соединяют несколько офисов с использованием 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
@ValdikSS
карма
631,0
рейтинг 46,9
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (60)

  • –16
    В свое время решил проблему таким способом: sudo apt-get install pptpd

    Кстати, ставится примитивно на сервер: help.ubuntu.com/community/PPTPServer
    А клиенты везде предустановлены.
    Для большинства будет лучшим выбором.
    • +14
      PPTP не обеспечивает должный уровень безопасности, не всегда проходит через firewall и, честно говоря, это, пожалуй, самый неудачный туннель, который можно использовать в реалиях сего дня. Зато поддерживается практически везде, да. Но если вам нужна поддержка как можно большего количества устройств, то стоит использовать IPsec без L2TP (лучше IKEv2, но можно и IKEv1). Про него скоро будет статья.
      • +1
        Про него скоро будет статья.
        Спасибо. А то, увидев ник, сразу захотел напомнить про обещание насчёт IKEv2 в habrahabr.ru/post/243915/#comment_8161967

        А то у меня уже выкипел мой «гуманитарный» мозг на стадии поднятия BIND и добавлении подсети (виртуальной) для StrongSwan VPN на Амазоне, «не выходит каменный цветок».
      • 0
        Да, я тоже очень хочу рецепт для ikev2. У меня так и не получилось сертификаты нужные самовыдать, а с обычным ssl-сертификатом мой win server 2k8r2 отказывается этот vpn хостить.
      • +1
        ИМХО не корректно сравнивать ipsec с pptp. Это протоколы разных уровней.
  • 0
    А зачем собственно использовать TCP? Это противоестественно для openvpn, и не рекомендуется. Да может в каких-то случаях это и нужно (если заблокирован UDP), но так нужно и написать: «как настраивать openvpn если приходится использовать TCP».
    • +4
      Эти изменения актуальны и для UDP. Возможно, я неоднозначно составил последнее предложение в конце технической информации, надо бы переписать. Это изменение повысило скорость с 30 до 80 МБит/с через UDP.
      • 0
        в таком случае просто не понятно почему это влияет на UDP, описан только TCP юзкейс.
        • +3
          Дополнил статью. Надеюсь, так станет чуточку понятнее.
    • 0
      А через прокси только TCP работать будет?
      • 0
        Это как? Через какой прокси?
        • 0
          Через HTTPS или Socks4/5.
          BigD, да.
          • 0
            По логике, если нет ограничений от OpenVPN, через сокс и UDP должен работать.
        • 0
          https
      • 0
        Через SOCKS5 в режиме UDP отлично работает OpenVPN :)
    • 0
      Мне tcp пришлось использовать из-за того, что в филиале стоит Mikrotik, который умеет только tcp openvpn.
  • 0
    Имеет ли смысл прописывать sndbuf 0 и rcvbuf 0 со стороны клиента при подключении через VPN-провайдер? Прописать эти настройки на стороне сервера возможности нет.
    • +1
      Да, безусловно, имеет.
  • +2
    Вы никогда не добьётесь скорости канала по ВПН-соединению, т.к. есть такое понятие, как overhead, который складывается из заголовков, в которые инкапсулируются данные. А у ВПН их много, много больше, чем у обычного IP-трафика, т.к. если используется тунель, это как минимум пара IP-заголовков и пара транспортных. И чем меньше пакеты, тем больше доля оверхеда. Если пакеты совсем крошечные, скажем, меньше 100 байт, что характерно для VoIP, оверхеад может достигать 50%, т.е. на канале 100 мегабит 50 будет уходить на служебную информацию. Это первое. Второе. Установка значения MTU большим, чем минимальное на маршруте приведёт только фрагментации уже шифрованных пакетов, что в случае cisco, например, должно избегаться, т.к. это приводит к деградации производительности. В случае openVPN не уверен насчёт деградации, но никакого положительного эффекта от такой манипуляции не будет определённо.
    • 0
      Все, в целом, верно. OpenVPN по умолчанию настроен так, чтобы TCP-пакеты проходили через линк с MTU >= 1450 без фрагментации. Увеличение MTU туннеля до огромных значений уменьшает загрузку CPU, что часто помогает добиться больших скоростей в случае маломощных устройств, вроде домашних роутеров, либо же серверов на линках около гигабита.
      А оверхед у OpenVPN может быть около 80 байт, т.е. около 80% для VoIP-трафика из вашего примера, но обычно он меньше.
      • 0
        По поводу фрагментации ещё одно интересное наблюдение. Если выставить MTU больше минимального на маршруте, то, как я писал выше, будет выполняться фрагментация пакетов после шифрования. При этом, все дополнительные заголовки ВПН, которые формируют значительную долю оверхеада, будут представлены только в первом фрагменте, все остальные фрагменты будут без доп. ВПН заголовков. Т.е. теоретически, больший MTU может позволить уменьшить оверхеад, но только для больших пакетов. Но за этим сразу же следует негативный эффект, по крайней мере в случае с ipsec — деградация производительности. Причина следующая — при фрагментации пакетов после шифрования, терминирующий канал роутер перед расшифровкой пакета должен сначала его собрать, т.е. сборка всех пакетов, фрагментированных таким образом, ложиться на плечи роутера. Если же пакеты будут фрагментироваться до шифрования, они могут быть расшифрованы без сборки на стороне роутера, сборкой в этом случае будет заниматься конечный узел.
  • 0
    Занятное наследство.
    На багтрекере у них проголосовать за баг нельзя, как я понял? Патч есть, что им ещё нужно-то.
    • 0
      Голосовать нельзя. Они обсудили в IRC эти изменения, но как-то процесс заглох. Возможно, думают над решением.
  • 0
    А вот спасибо за ценную информацию, обязательно опробую, у меня как раз клиенты и сервер на разных ОС.
  • 0
    с сервером под Linux после изменений скорость внутри тоннеля выросла более чем в два раза. с сервером под FreeBSD улучшение всего 10-15%, что можно списать на статистическую погрешность. клиенты в обоих случаях Windows 7. за статью спасибо, пошёл было ставить в карму, а там уже.
  • 0
    Интересно, мы как-то соединяли два офиса через 100-мегабитный канал и OpenVPN. Криво, конечно, но тогда это был лучший вариант, GRE over IPSEC не было возможности настроить. Я тестировал тогда использование канала и пришел к выводу, что существенного снижения скорости по сравнению с «сырым» линком нет. Вроде было 70-80 мбит/с, разницу я списал на оверхед. А оказывается, вот оно как )
    • 0
      Если вы использовали UDP, и пинг между офисами был в пределах 20 мс, то это вполне возможно.
      • 0
        Вы правы, был именно UDP и пинг был в пределах 3-5 мс (внутригородская сеть провайдера).
  • +1
    Статья супер! Но в статье совершенно не упомянут совершенно необходимый момент — нагрузка на процессор от OpenVPN. Если при 100 мегабитах более-менее средний проц сможет отработать, то на гигабите и более — уже точно начнутся проблемы даже у серверных процессоров. Кроме того, не уверен, что OpenVPN хорошо распределит нагрузка по ядрам отработает при наличии большого числа ядер, а не просто съест одно ядро целиком и начнет дропать пакеты.

    Вот этот момент был бы даже более интересен, чем домашнее использование.
    • +11
      OpenVPN однопоточный, и для того, чтобы нагрузка распределялась по ядрам, запускают несколько OpenVPN'ов и объединяют их через bonding или teaming.
      Вообще, насколько странным бы это не казалось, тормозит больше всего не шифрование, а код изменения TCP MSS! Если отключить его параметром mssfix 0, то на моем стареньком компьютере скорость взлетает с 300 Мбит/с до ~750 Мбит/с при прямом гигабитном подключении.
      Если нужна такая статья, могу написать.
      • +4
        Напишите, пожалуйста. Интересно.
        • +4
          Я тоже думаю, что очень нужна :) Что-то в стиле «гигабит по OpenVPN» — это будет ну очень круто.
        • +1
          Поддерживаю!
      • 0
        Да, напишите пожалуйста. Интересуют все возможные советы по увелечению скорости, не в ущерб безопасности.

        Спасибо за статью, скорость на tcp выросла минимум в три раза.
      • 0
        что то не помогло mssfix 0
        не подскажите поподробнее??
        • 0
          Не помогло чему?
          • 0
            ну в ветке речь про нагрузку на процессор.
            • 0
              Ну, я прогоняю гигабит с AES-128-CBC, SHA1, буфферами в 0 и mssfix 0 без проблем на одном процессоре с загрузкой не под 100. У вас какого порядка скорости-то?
  • 0
    А с Android, в случае приложения OpenVPN Connecот команды OpenVPN что либо надо делать и можно ли вообще?
    • 0
      Это нужно спрашивать у разработчиков, т.к. исходников этого продукта нет, и он использует OpenVPN 3.
      • 0
        Благодарю, ну по крайней мере в исходниках подобного кода не нашлось.
      • 0
        Можешь порекомендовать какую-то достойную открытую альтернативу OpenVPN Connect?
        • 0
          Если для Android, то OpenVPN for Android. У него открыты исходные коды и он основан на OpenVPN git-срезе, но подключается, как правило, дольше, чем OpenVPN Connect, и статистика у него не очень, зато настроек больше, и можно вручную все настроить, даже есть нет конфиг-файла, а только ключи.
          • 0
            Спасибо.
  • 0
    Использую ssh как сокс5 прокси. Подтормаживает, если сразу открывать много вкладок в браузере. Можно ли как-то это все ускорить?
    • +1
      Можно. Но причем тут ssh?
      • 0
        Спасибо за hpn-ssh — стало получше.
    • 0
      Можете попробовать sshuttle: Transparent proxy server that works as a poor man's VPN. Forwards over ssh. Doesn't require admin. Works with Linux and MacOS. Supports DNS tunneling.
      • 0
        Не подходит, у меня виндовс. Но я поставил на сервер hpn-ssh, как советовал ValdikSS — вроде стало лучше.
  • 0
    А какие недостатки у большого буфера? Т.е. почему 393216, а не, к примеру, 2097152?
    • 0
      В случае с UDP, я предполагаю, чуть увеличится задержка (latency), что негативно скажется, например, на VoIP. Т.е. ОС вместо того, чтобы отбрасывать пакеты, будет копить их в буфере. В случае с TCP, хм, вроде особых проблем нет.
    • 0
      Еще в текущей стабильной версии OpenVPN нельзя задать буфер больше 999999. Будет исправлено в 2.3.9.
  • 0
    Дейсвительно OpenVPN стал летать, спасибо!
  • 0
    А у меня не стал летать, как ни старался… На мегабитной линии smb разгоняется только до 120 килобит, остальной канал свободен. Пинг 150. Ничего не дают ни попытки увеличить буфера (в смысле, буферы) — от 0 до 500К, ни загадочный mssfix, ни тип порта c UDP на TCP и обратно… Кстати, на плохом канале tcp ощутимо помогает — потери падают почти до нуля. Правда, пинг вырастает до одной секунды (*нервный смех*)
    • 0
      Вы не путаете биты и байты?
      • 0
        Путаю иногда. 11 КБ — это биты, или байты? ))

        Шучу. iperf показывает загрузку канала на 1/10… Так что всё правильно.
        • 0
          *** iftop
    • 0
      Привет, у меня на такой линии, тоже много траблов, даже без openvpn много проблем. Что удалось выяснить — windows, до 10, к такому каналу не приспособлен. Можно тюнить, но не сильно поможет. Почитайте, если интересно. Samba у меня даже на 50-70 мс уже тупит.
      Имхо, основная проблема, в данном контексте(Samba), это то, что она для локальной сети разрабатывалась где пинги маленькие. Я столкнулся с этим не только на примере самбы. Вы можете попробовать без openvpn на длинной линии запустить самбу, даже интересно что будет. Опять же имхо, основная проблема алгоритм разгона TCP. Если сделать быстрый старт, вроде есть такие настройки, то начинаются много потерь, на коротких линиях, то есть, либо одно либо другое. Максимальная скорость у iperf на длинных линиях при "-l 1M"(маленькая L), максимально для TCP. В общем я бросил эти попытки с вердиктом, не судьба. Возможно надо тюнить самбу, а не openvpn. Если что-то получится напишите пару строк, можно в личку, буду при много благодарен.
      • 0
        Шестое чувство настаивает, что тюнить эту штуку обойдётся себе дороже. Оптимист внутри меня считает необходимым рассмотреть вариант бросить самбу вообще и перейти на WebDav. Он поддерживается в windows без дополнительного софта, и его можно смонтировать как сетевой диск. Единственное ограничение — 4 гигабайта на файл.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.