Усередині контейнера за корпоративним VPN DNS розв'язується, сторінка входу завантажується, кінцева точка перевірки здоров'я відповідає, і далі запит HTTPS зависає до вичерпання часу. Перебудова образу й зміна змінних проксі нічого не змінюють, бо зламана частина не в образі. Клієнт автентифікується через один транспорт і перевозить великі дані через інший, і зламаний лише другий.

Два транспорти, один заплутаний симптом

Корпоративний клієнт на базі TLS зазвичай автентифікується через звичайне TLS-з'єднання, а потім узгоджує другий канал даних на базі UDP для сеансу. Коли це друге плече працює, пропускна здатність і затримка поліпшуються. Коли його фільтрують або воно не вміщається в шлях, усе до масового передавання проходить успішно, а саме передавання спиняється, що точно відповідає картині вище.

Контейнер не змінює ці переговори; він змінює шлях зовнішніх пакетів. Хост транслює потік контейнера, тож дейтаграми UDP виходять з іншого вихідного порту, ніж локальний сокет клієнта, і повертаються через запис трансляції, що спливає за значно коротшим таймером, ніж усталений потік TCP. Якщо тунель працює на хості й не працює в контейнері, порівняйте ці два потоки, перш ніж звинувачувати застосунок. Це порівняння вирішує більше, ніж будь-яка перебудова образу.

Вирішуйте експериментом, а не інтуїцією

Найдешевший експеримент вимикає канал даних UDP і повторює запит. Використовуйте клієнт командного рядка, а не настільну обгортку, щоб прапорець справді застосувався: openconnect vpn.example.net --user=you --interface=tun0 --no-dtls. Якщо запит, що зависав, тепер завершується, проблемою було плече DTLS, а решта був шум.

Підтвердьте результат в обидва боки з одного й того самого контейнера: один великий запит із прапорцем і один без. Зміна поведінки, що йде за прапорцем, є доказом; сторінка, яка зрештою завантажується, ні.

Якщо прапорець це виправляє, вирішіть чому

Три умови дають той самий симптом і вимагають різних відповідей. Шлях може повністю фільтрувати UDP, що робить прапорець правильною постійною відповіддю для цієї мережі. Шлях може дозволяти UDP, але відкидати великі дейтаграми, що вказує на MTU, а не на фільтрування. Або шлях може бути настільки схильним до втрат, що плече UDP працює гірше за TCP, а це рішення про ємність, а не про доступність.

Розрізніть їх, перш ніж документувати обхід. Фільтрування виживає за будь-якого розміру пакета, проблеми MTU з'являються лише вище порогу, а втрати виглядають як повторне передання й змінна затримка, а не як чисте зависання. Кожен тест звужує причину, не змінюючи конфігурацію клієнта.

Перевірте розмір пакета, перш ніж залишати обхід

Якщо причина в розмірі, інтерфейс тунелю приймає пакети, які шлях не може нести, і проблема повертається на будь-якому транспорті, щойно навантаження зростає. Порівняйте інтерфейси: ip link show tun0 на хості, потім docker network inspect bridge, щоб прочитати MTU, записаний у параметрах мережі. Міст контейнера, що досі на 1500 байтах під тунелем, який несе менше, це звичайна знахідка.

Зондуйте вгору від відомого доброго розміру тестом заборони фрагментації всередині тунелю, потім знизьте MTU мережі контейнера або обмежте TCP MSS на тунелі. Кожна з цих правок часто знову робить шлях UDP придатним і прибирає потребу в прапорці, що є кращим результатом, коли причина не фільтрування.

Вирішіть, чим ви готові поступитися

З вимкненим каналом даних тунель несе навантаження всередині з'єднання TCP. На чистому шляху це просто повільніше; на шляху з втратами один втрачений сегмент затримує все за ним, і зовнішнє повторне передання конкурує з внутрішнім. Такий обмін пасує інтерактивній розробці й малим викликам API і погано пасує масовим передаванням або довгим сеансам через мобільні канали.

Хоч би який варіант ви обрали, зафіксуйте, який транспорт зрештою використав тунель і чому. Контейнер, який мовчки залежить від прапорця, доданого кимось місяці тому, це наступна аварія, і той, хто її розбиратиме, не знатиме, чи прапорець був обходом для фільтрування, чи залишком експерименту з MTU.

Схожі статті