OpenVPN: Как смягчить проблемы MTU пути для каждого клиента?

У нас есть десятки встроенных устройств, установленных у клиентов, и все они звонят домой в нашу службу OpenVPN. В целом это работает нормально, но у некоторых наших клиентов есть серьезные проблемы с MTU. Наше влияние на клиентов по исправлению их сетей ограничено, поэтому нам необходим OpenVPN для решения этой проблемы. В двух словах, мой вопрос:

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

Обратите внимание, что в нашем худшем случае это довольно плохо: путь MTU 576, отбрасывает все фрагменты, не фрагментирует себя, не учитывает DF-бит. Вы понимаете, почему я предпочел бы не решать эту проблему глобально.

Страница руководства OpenVPN предлагает несколько опций, связанных с MTU, особенно --link-mtu, --tun-mtu, --fragment and --mssfix, Но это также говорит

--link-mtu [...] Лучше не устанавливать этот параметр, если вы не знаете, что делаете.

--tun-mtu [...] Лучше всего использовать опции --fragment и / или --mssfix для решения проблем с размером MTU.

Итак, я начал экспериментировать с --fragment а также --mssfix но вскоре пришлось осознать, что по крайней мере первое должно быть установлено не только на стороне клиента, но и на стороне сервера. Затем я посмотрел в серверной конфигурации для каждого клиента через --client-config-dir но это говорит

Следующие параметры допустимы в контексте конкретного клиента: --push, --push-reset, --iroute, --ifconfig-push и --config.

Никаких упоминаний о параметрах MTU!

Итак, вот мои более конкретные вопросы:

  • Почему именно link-mtu а также tun-mtu обескуражены? Каковы потенциальные проблемы с этими вариантами? Обратите внимание, что мне вполне комфортно с низким уровнем IP-заголовков.
  • Какой из вариантов link-mtu tun-mtu fragment mssfix должны быть отражены на стороне сервера, чтобы работать?
  • Какой из вариантов link-mtu tun-mtu fragment mssfix может быть использован в client-config-dir?
  • В случае, если все четыре варианта должны быть отражены на стороне сервера, и не могут использоваться внутри client-config-dir: Есть ли альтернативы для борьбы с MTU по низкому пути на клиента?

Заметки:

  • Части моих вопросов уже задавались здесь 5 лет назад, но тогда на них действительно не было ответа, поэтому я смею их дублировать.
  • Сервер OpenVPN в настоящее время 2.2.1 на Ubuntu 12.04. Мы готовим обновление до 2.3.2 на Ubuntu 14.04
  • Клиенты OpenVPN являются 2.2.1 на Debian 7.6
  • Я рад, что сам определяю путь клиента -MTU вручную
  • В настоящее время мы не можем тестировать много на стороне сервера. Но мы строим полный отдельный испытательный стенд, должен быть готов в ближайшее время.

Я благодарен за любые полезные советы.

3 ответа

Я решил проблему на стороне клиента, добавив опцию mssfix 1300 в файл конфигурации.

Со страницы руководства openvpn:

--mssfix max
    Announce to TCP sessions running over the tunnel that they should limit their send packet sizes such that after OpenVPN has encapsulated them, the resulting UDP packet size that OpenVPN sends to its peer will not exceed max bytes. 

Оригинальная идея для моего решения пришла от personalvpn.org

Не уверен, что это поможет со встроенными устройствами, но я делюсь своим опытом на случай, если это поможет другим.

TL;DR: перейдите к последнему вопросу/ответу для возможного решения.


  • Почему именно link-mtu и tun-mtu не рекомендуются? Каковы потенциальные проблемы с этими вариантами? Обратите внимание, что меня вполне устраивает низкоуровневая обработка IP-заголовков.

По моему опыту пользователя OpenVPN, в большинстве распространенных случаев лучше не возиться со значениями и/или, т. е. вопреки тому, что указано в документации.

и значения вычисляются относительно друг друга в зависимости от того, какой шифр (если таковой имеется) используется для туннеля. По умолчанию подразумеваются классические 1500 байт, хотя они и являются производными от этого, но вы можете установить любой из них и, таким образом, соответствующим образом пересчитать другой. В этом отношении существует одно вполне определенное эмпирическое правило : никогда не устанавливайте оба параметра : устанавливайте только один из них, потому что другой просто последует его примеру.

Единственный случай, когда я столкнулся с проблемами при их изменении, - это когда я установил для конечных точек очень разные значения, а сервер имел очень низкое значение, например, 576 на нем, а 1500 на клиенте. Эти установки просто вообще не поддерживают рукопожатие, и я никогда не проводил дальнейших исследований, потому что, честно говоря, такие установки у меня были только в искусственных лабораторных испытаниях. Противоположный случай, т.е. очень низкое значение на клиенте и нормальное/высокое значение на сервере, работает нормально.

Фактически, я нашел эту настройку либо или(Я в основном предпочитаю настройку ) на самом деле прекрасно решает большинство распространенных случаев, т.е. туннель работает так, как должен, включая любой трафик, отличный от TCP.

Конечно, настройки и/или значения ( если они также заданы явно) должны учитывать явные значения link-mtu/tun-mtu, но я обнаружил, что просто оставить их в покое (т. е. даже не упомянуть в конфигурации) обычно Лучше всего, потому что они просто автоматически настраиваются в соответствии со значениями link-mtu/tun-mtu.

Тем не менее, это правда, что только настройка (таким образом, link-mtu/tun-mtu остается неуказанным) решает все, что связано с TCP, но все остальные протоколы обязательно испытывают проблемы, и это единственная причина, по которой они обычно этого не делают. Это просто потому, что большая часть трафика, отличного от TCP, представляет собой либо DNS на UDP, который обычно имеет небольшой размер, либо эхо-запросы/ответы ICMP, которые по умолчанию снова представляют собой небольшие пакеты.

Однако обратите внимание, что я имею в виду OpenVPN в Linux; на других ОС, особенно на устройствах серии Windows и iOS, это может быть другая история, т.е. изменение link-mtu/tun-mtu может быть неуместным или даже разрушительным, и вам, возможно, придется прибегнуть к изменению фрагмента/mssfix, как предложено в документации.. Особенно враждебными могут быть случаи, когда либо сервер, либо клиенты (или оба) не поддерживают фрагментацию/пересборку IP, что может быть вызвано искусственным понижением link-mtu/tun-mtu, и поэтому в таких случаях вы можете прибегнуть к включению только в ОпенВПН.


  • Какой из параметров link-mtutun-mtu фрагмент mssfix должен быть зеркалирован на стороне сервера, чтобы работать?

Согласно предупреждающим сообщениям, выдаваемым OpenVPN в свой журнал, когда вы устанавливаете link-mtu/tun-mtu, не зеркалируя их на конечную точку, значения link-mtu и tun-mtu должны быть точно зеркалированы, явно или неявно . Однако в реальных случаях у меня никогда не возникало проблем с изменением какого-либо значения, даже если в конечном итоге между конечными точками туннеля были очень разные значения.

должен либо присутствовать на обеих сторонах, либо отсутствовать на обеих сторонах , поскольку его наличие позволяет осуществлять фрагментацию, выполняемую самим OpenVPN с использованием собственного внутреннего алгоритма (а не IP-фрагментацию), и поэтому он должен быть согласован обеими конечными точками. Однако, когда он присутствует, он может иметь асимметричные значения.

не нуждается в зеркальном отображении, а также может иметь асимметричные значения между конечными точками.


  • Какой из параметров link-mtutun-mtu фрагмент mssfix можно использовать в client-config-dir?

Никто


Возможное решение

  • В случае, если все четыре параметра должны быть зеркалированы на стороне сервера и не могут использоваться внутри client-config-dir: есть ли какие-либо альтернативы для борьбы с низким MTU пути для каждого клиента?

Один из способов — использовать настройки Linux для каждого маршрута, которые позволяют произвольно устанавливать значения MTU, вплоть до MTU фактического интерфейса. Это происходит следующим образом:

Для начала выполните обнаружение Path MTU вручную (например, с помощьюкоманды от сервера к удаленным клиентам), чтобы узнать правильное значение MTU между сервером и каждым конкретным удаленным клиентом. Затем,

на стороне клиента , предполагая, что это просто клиент, а не маршрутизатор для других хостов в его локальной сети, просто установите значение OpenVPN на фактическое значение MTU минус 28. Например, на удаленном клиенте, имеющем фактическое значение MTU 576,сделает свое дело.

Обратите внимание, что это подойдет для всего трафика (не только TCP), исходящего от клиента, поскольку это значение используется OpenVPN в качестве верхней границы размера для его собственных полезных данных (порт UDP 1194), отправляемых в удаленную конечную точку, следовательно, для удаленного клиента. фактический MTU (определенный вручную) минус 20 (размер внешнего заголовка IP без опций) минус 8 (размер внешнего заголовка UDP).

Значение MSS, которое OpenVPN будет автоматически ограничивать внутритуннельным TCP-трафиком, будет тогда минус собственные издержки OpenVPN (которые варьируются в зависимости от используемого шифрования), минус 20 (размер внутреннего заголовка IP без параметров) минус 20 (размер внутреннего заголовка TCP без параметров)..

на стороне сервера установите по одному маршруту для каждого клиента с «низким MTU», чтобы установить правильный MTU для каждого из них. Каждое правильное значение, устанавливаемое в настройках каждого маршрута, должно соответствовать значению, установленному вами для значения удаленного клиента (как было определено ранее), за вычетом собственных накладных расходов OpenVPN. Последнее может быть получено из значения link-mtu минус значение tun-mtu, сообщаемое сервером OpenVPN для этого конкретного туннеля. Например, если предположить, что сервер OpenVPN сообщает link-mtu 1541 и tun-mtu 1500, то на компьютере, на котором размещен ваш сервер OpenVPN, вы должны сделать что-то вроде:

      ip route add <client's-*vpn*-address> via <your-openvpn-server's-*vpn*-address> mtu 507

Такую операцию можно легко выполнить по требованию с помощьюскрипт, который получает эти значения (а также многие другие) в переменных среды, динамически устанавливаемых OpenVPN. На языке шелл-скриптов это будет так:

      ip route replace "$ifconfig_pool_remote_ip" via "$ifconfig_local" mtu "$(( 576 - 28 - (link_mtu - tun_mtu) ))"

С этого момента исходящий трафик к VPN- адресу этого конкретного клиента будет учитывать этот MTU, а не интерфейс Tun.

Более того, если ваш сервер OpenVPN также действует как маршрутизатор () между его локальной сетью и удаленными клиентами, тогда настройки каждого маршрута, примененные к серверу OpenVPN (его ядру Linux), также будут запускать правильные сообщения ICMP (тип 3, код 4, необходима фрагментация) к машинам в локальной сети, когда они отправляют DF трафик к удаленным клиентам, и в этом случае эти другие машины в локальной сети должны соответствовать этим сообщениям ICMP, а также выполнять фрагментацию IP внутри туннеля от имени компьютеров в локальной сети, когда они отправляют трафик, отличный от DF, и в этом случае ваш удаленные клиенты должны поддерживать повторную сборку IP-адресов для IP-фрагментов, выходящих из туннеля.

Также обратите внимание, что в Ubuntu 14.04 HWE и новее (или эквивалентных ядрах до версии 5.7.x) вам также необходимо будет установитьчтобы Linux выполнял указанную ICMP/фрагментацию при пересылке трафика других машин, тогда как это дополнительноене требуется для исходящего трафика, исходящего от самого сервера.

Наконец, обратите внимание, что для полностью правильной конфигурации вам также следует установить(при условии, что MTU базового интерфейса равен 1500) на стороне сервера . На самом деле я делаю это в любое время и в любом месте в качестве базовой конфигурации, за исключением особых случаев, требующих особых обходных путей. Это связано с тем, что OpenVPN не рассматривает MTU базового интерфейса в качестве начального значения для своего link-mtu/tun-mtu и не выполняет обнаружение PMTU, даже еслиопция установлена ​​нав ОС, которые его поддерживают. Поэтому, явно устанавливаязначение, отражающее MTU базового интерфейса (с использованием формул, которые я описал выше), для меня является истинным и самым серьезным значением по умолчанию, по крайней мере, в Linux.

ХТХ

Учитывая отсутствие ответов, я публикую сейчас решение, которое не очень элегантно, но просто: запустить другой экземпляр OpenVPN по TCP для "плохих клиентов"

proto tcp

и снизить TCP MSS на клиенте, например

iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o ${OUT_DEV} -j TCPMSS --set-mss ${PATH-MTU-MINUS-40}

Преимущество этого решения заключается в том, что каждый клиент может установить свою индивидуальную MSS.

По общему признанию это TCP-over-TCP, но он должен работать достаточно хорошо во многих сценариях.

Обратите внимание, что я все еще очень заинтересован в решениях, которые не требуют proto tcpи я отмечу их как действительный ответ, если они более или менее соответствуют моим изложенным требованиям.

Другие вопросы по тегам