Передать фиксированный внутренний пакет 1,500 байт через VPN
Фиксированный внутренний пакет 1,500 байт не помещается во внешний путь 1,500 байт. Измерьте накладные расходы, затем выберите больший MTU нижнего уровня или поддерживаемую фрагментацию.
У вас есть требование, которое не согнуть: удалённая сторона должна получить тот же IP-пакет 1,500 байт, который выпускает отправитель, включая заголовки. Туннель не может упаковать этот пакет вместе со своим кадрированием во второй IP-пакет 1,500 байт, поэтому что-то в проекте должно уступить. Порядок ниже — тот, который я использую в окне изменений: записать бюджет в байтах, доказать, что нижележащая сеть действительно может пронести, затем выбрать ровно один механизм переноса и подтвердить внутренний пакет на другой стороне.
Запишите бюджет в байтах до правки профиля
Инкапсуляция добавляет байты на нескольких уровнях, и итог — свойство вашего профиля, а не константа, которую можно найти. Семейство адресов, выбор шифра, транспортный протокол и любая опция сжатия или кадрирования сдвигают число, поэтому вычитание, скопированное из другого развёртывания, бесполезно как бюджет. Начните с внутреннего требования, добавьте измеренные накладные расходы на пакет собственной конфигурации и запишите получившийся внешний размер в заявку на изменение до того, как кто-то отредактирует файл.
Проект решают два числа: самый большой внешний пакет, который путь несёт без фрагментации, и дополнительные байты, нужные вашей инкапсуляции. Когда первое меньше второго плюс 1,500, одно из них должно измениться. Тогда выбор становится узким, а не творческим, поэтому я записываю оба числа до обсуждения вариантов. Ничто на уровне туннеля не сжимает эти байты, и никакое одно целое значение MTU не снимает данное вам требование.
Проверьте нижележащую сеть ping с do-not-fragment
Измеряйте путь, а не доверяйте MTU интерфейса, потому что важен самый маленький участок внешнего пути. В Linux, -M do устанавливает бит do-not-fragment и -s принимает полезную нагрузку ICMP, поэтому кадр 1,500 байт отвечает при 1,472 байтах полезной нагрузки, если вычесть заголовок IP 20 байт и заголовок ICMP 8 байт. Поднимайте нагрузку, пока проверка не провалится, затем прыгните к jumbo-размеру, чтобы увидеть, несёт ли путь его вообще.
ping -M do -s 1472 -c 2 198.51.100.10 ping -M do -s 8972 -c 2 198.51.100.10 tracepath -n 198.51.100.10
Путь, который проходит 1,472 и проваливается на 8,972, не может пронести внутренний пакет 1,500 байт вместе с накладными расходами в одном внешнем пакете. Это ответ, который был нужен до открытия конфигурации VPN. Он же определяет, какой из двух следующих разделов относится к вам, поэтому держите оба результата проверки рядом с заявкой. Догадка здесь стоит окна обслуживания, потому что туннель, который сообщает о себе up, ничего не говорит о самом большом пакете, который примет путь.
Поднимайте MTU пути только там, где согласен каждый переход
Jumbo-кадры — свойство end-to-end, а не настройка, которую вы включаете на двух конечных точках, которыми случайно управляете. Каждый коммутатор, маршрутизатор и стык провайдера на внешнем пути должны согласиться на больший размер, и один переход 1,500 байт молча отбросит пакет, который вы только что увеличили. Поднять только локальный интерфейс — классическая половинчатая правка, из-за которой туннель выглядит сломанным, пока нижележащая сеть тихо теряет пакеты.
ip link set dev eth1 mtu 9000 ip link show dev eth1 ping -M do -s 8972 -c 2 198.51.100.10
Измените интерфейс, затем проверьте тот же путь снова, прежде чем менять что-то ещё. Если проверка всё ещё проваливается, откатите с помощью ip link set dev eth1 mtu 1500 и перейдите к фрагментации, вместо того чтобы спорить с провайдером о канале, который вам не принадлежит.
Используйте фрагментацию туннеля, когда нижележащая сеть не может вырасти
Поддерживаемый механизм фрагментации ниже внутреннего пакета позволяет нескольким внешним пакетам нести один внутренний, и противоположная конечная точка туннеля собирает их заново, прежде чем отдать оригинал в стек. Опция UDP fragment в Community OpenVPN — одна реализация этой идеи, и это не то же самое, что обычная IP-фрагментация внешнего пакета. Оба узла должны работать на версии, поддерживающей формат, и путь данных должен быть тем, о котором вы думаете: клиенты OpenVPN 3 и ускоренные ядром каналы данных имеют разные ограничения, поэтому профиль, работающий на одном клиенте, может отказать на другом.
openvpn --config client.ovpn --tun-mtu 1500 --fragment 1400 --verb 4
Обычная внешняя фрагментация — другой вариант, и он слабее. Маршрутизаторы IPv6 вовсе не фрагментируют пересылаемый пакет, поэтому слишком большой внешний пакет просто умирает, и отправитель узнаёт об этом, только если соответствующие сообщения ICMPv6 выживут на пути. Фрагменты также приглашают фильтрацию и усиление потерь, поэтому я отношусь к этому как к запасному варианту, а не плану.
Внешний переносчик на основе потока обходит вопрос размера, сегментируя собственный поток байтов, и восстановленный внутренний пакет всё ещё может быть 1,500 байт. Это транспортное решение со своей ценой, включая известное поведение TCP внутри TCP, поэтому принимайте его осознанно, а не как побочный эффект спора об MTU.
Подтвердите, что внутренний пакет приходит неизменным
Проверка — это не успешное рукопожатие. Снимите трафик на интерфейсе туннеля с обеих сторон и сравните размер и содержимое пакета, который приложение действительно отправило, с тем, что получила удалённая сторона.
ip link show dev tun0 ping -M do -s 1472 -c 2 10.8.0.1 tcpdump -ni tun0 -c 5 'icmp and greater 1000'
Если запись показывает внутренний пакет полного размера на дальнем конце, выбор переноса работает, и остаётся его зафиксировать. Если она ничего не показывает, пока туннель сообщает о себе up, внешний пакет отбрасывается где-то между конечными точками, что возвращает вас к проверке, а не к настройкам шифра.
Запишите в заявку на изменение три вещи, прежде чем закроете её: измеренный внешний бюджет, выбранный механизм и команду, которая доказала, что внутренний пакет выжил. Следующему человеку, который тронет этот туннель, понадобятся все три, и ни одну из них нельзя восстановить только из файла конфигурации.