Передати фіксований внутрішній пакет 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, зовнішній пакет відкидається десь між кінцевими точками, що повертає вас до перевірки, а не до налаштувань шифру.
Запишіть у заявку на зміну три речі, перш ніж закриєте її: виміряний зовнішній бюджет, обраний механізм і команду, яка довела, що внутрішній пакет вижив. Наступній людині, яка торкнеться цього тунелю, знадобляться всі три, і жодну з них не можна відновити лише з файлу конфігурації.