Ситуация знакомая многим: сервер пингуется, DNS работает, TCP-порт 443 открыт, но curl на HTTPS подвисает, apt update периодически ловит таймауты, а docker pull застревает на скачивании слоёв. Особенно часто это всплывает после включения VPN, GRE-туннеля, WireGuard или после переноса сервиса в сеть с другой схемой маршрутизации.
Одна из самых неприятных причин такого поведения — PMTU black hole. То есть Path MTU Discovery теоретически должен подобрать допустимый размер пакета по пути, но на практике нужные ICMP-ответы не доходят или где-то отфильтровываются. В результате крупные TCP-сегменты теряются молча, а приложение выглядит как «иногда работает, иногда висит».
На Debian и Ubuntu проблема особенно заметна на прикладном уровне: HTTPS зависит от TLS-обмена и передачи сравнительно крупных записей, apt активно использует HTTPS-репозитории, а Docker тянет данные из реестров поверх TLS. Если маленькие пакеты проходят, а большие исчезают, диагностика без понимания MTU может увести совсем не туда — в DNS, сертификаты, прокси, балансировщики и даже в код приложения.
Сразу важный тезис: PMTU-проблемы редко лечатся одним «магическим» числом MTU для всех случаев. Правильный подход — понять, где появляется overhead туннеля, проходит ли ICMP fragmentation needed, кто именно режет путь и на каком интерфейсе нужно ограничить размер пакета.
Что такое PMTU black hole и почему страдает именно HTTPS
У каждого канала есть максимальный размер L3-пакета — MTU. Когда трафик идёт не напрямую, а через PPPoE, GRE, IPsec, VXLAN, WireGuard или цепочку NAT и туннелей, полезная нагрузка уменьшается из-за служебных заголовков. Если отправитель считает, что может слать 1500 байт, а реальный путь допускает меньше, должен сработать механизм Path MTU Discovery.
Классическая схема такая: узел отправляет пакет с флагом DF и, если по пути есть более узкий участок, промежуточный маршрутизатор возвращает ICMP-сообщение о необходимости фрагментации с указанием допустимого размера. Хост уменьшает размер пакетов, и соединение продолжает работать.
Проблема начинается, когда эти ICMP-сообщения отбрасываются. Это может происходить на firewall, в облачной сети, на домашнем роутере, в криво настроенном VPN-шлюзе, в GRE-схеме или даже на стороне провайдера. Тогда отправитель продолжает слать слишком крупные сегменты, а приёмник их не получает. С точки зрения приложения видим «тишину» и повторные передачи.
HTTPS страдает особенно заметно, потому что TCP-соединение может устанавливаться нормально: SYN, SYN-ACK и ACK маленькие. Клиент успевает отправить часть TLS ClientHello, сервер отвечает, затем начинаются пакеты крупнее допустимого пути, и обмен зависает. Внешне это выглядит как случайный таймаут TLS, хотя корень проблемы лежит ниже.
Если HTTP на 80-м порту иногда работает, а HTTPS на 443-м висит, это ещё не значит, что виноват TLS. Часто TLS просто первым упирается в реальный потолок MTU по пути.
Типичные симптомы на Debian/Ubuntu
На практике PMTU black hole редко выглядит как тотальный обрыв. Гораздо чаще появляются плавающие, неочевидные симптомы, которые легко принять за проблемы приложений.
curl -Iк HTTPS-ресурсу зависает или завершается по таймауту, хотя TCP-порт открыт.apt updateиapt installработают нестабильно, особенно с HTTPS-репозиториями.docker pullподключается к registry, но зависает на скачивании слоёв или метаданных.Через VPN всё ломается, а без VPN работает нормально.
На одном провайдере или из одной подсети сервис доступен, а из другой — нет.
Мелкие ответы проходят, крупные загрузки или TLS-обмен — нет.
Пинг маленькими пакетами успешен, а большие с запретом фрагментации не проходят.
Очень характерный сценарий: после поднятия WireGuard-туннеля админ видит, что SSH работает, ICMP тоже, но контейнеры не тянут образы, а пакетный менеджер внезапно тормозит. Или после добавления GRE между площадками часть веб-сервисов открывается, а часть «думает» по 30–60 секунд.
Если вы держите такие туннели на выделенном сервере или VDS, проблему удобнее ловить с полным доступом к маршрутизации, firewall и дампам трафика. На обычном shared-окружении такой разбор часто просто невозможен.

Где чаще всего ломается MTU
WireGuard
У WireGuard есть собственный overhead. Если поверх обычного Ethernet с MTU 1500 вы поднимаете туннель и оставляете на нём слишком большой MTU, полезная нагрузка может не помещаться в физический путь. В одних сетях это маскируется, в других — сразу вылезает как нестабильный HTTPS и зависающие загрузки.
Отдельная сложность в том, что WireGuard часто используют поверх мобильных сетей, NAT, PPPoE и облачных провайдеров. Интерфейс поднимется и даже будет «пинговаться», но предельный размер пакета окажется существенно ниже ожидаемого.
GRE
GRE добавляет свои заголовки, а если поверх него ещё идёт IPsec или внутренняя маршрутизация между несколькими узкими сегментами, итоговый MTU может стать заметно меньше 1500. Через такую конфигурацию особенно любят ломаться длинные HTTP-ответы, API и TLS.
VPN и вложенные туннели
Самые неприятные случаи — это туннель в туннеле: например, WireGuard поверх PPPoE, Docker-сеть поверх VPN, GRE через облако с уже существующей инкапсуляцией. Каждый дополнительный заголовок съедает байты, а ICMP на одном из участков может быть заблокирован.
Если проблема проявляется внутри контейнеров, дополнительно проверьте правила фильтрации и NAT на хосте: пересечение MTU и firewall даёт очень неприятные побочные эффекты. По этой теме может пригодиться разбор Docker, iptables и nftables на Linux.
Как быстро проверить, что это именно PMTU
Начинать лучше не с правок, а с подтверждения гипотезы. Иначе можно неделями менять DNS, зеркала репозиториев и параметры приложений, не устраняя источник проблемы.
1. Проверяем маршрут и интерфейсы
ip addr
ip route
ip -d link show
ip route get 1.1.1.1
Нас интересуют MTU на физических и туннельных интерфейсах, а также маршрут до проблемного узла. Иногда уже здесь видно, что, например, на wg0 выставлено 1500, хотя под ним интерфейс с PPPoE и фактический потолок меньше.
2. Используем tracepath
tracepath archive.ubuntu.com
tracepath registry-1.docker.io
tracepath удобен тем, что пытается определить path MTU по дороге. Если утилита показывает уменьшение PMTU, это сильная подсказка. Если значения странные или диагностика обрывается, уже есть повод копать глубже.
3. Пингуем с запретом фрагментации
ping -M do -s 1472 8.8.8.8
ping -M do -s 1460 8.8.8.8
ping -M do -s 1400 8.8.8.8
Для IPv4 число в -s нужно подбирать с учётом заголовков IP и ICMP. Если крупные размеры не проходят, а меньшие проходят стабильно, подозрение на MTU укрепляется. Для тестов по туннелю лучше пинговать именно адрес за туннелем или на удалённой стороне, а не случайный внешний хост.
4. Смотрим tcpdump и ищем ICMP fragmentation needed
tcpdump -ni any 'icmp or icmp6'
tcpdump -ni eth0 'icmp and icmp[0] == 3 and icmp[1] == 4'
Ключевой маркер для IPv4 — ICMP type 3 code 4, то есть fragmentation needed. Если такие пакеты приходят, PMTUD хотя бы пытается работать. Если вы ожидаете их увидеть, но ничего нет, возможно, кто-то их режет.
Параллельно полезно смотреть TCP-поведение:
tcpdump -ni any 'tcp port 443'
Если видно множество повторных передач, паузы, а соединение не двигается после первых пакетов, PMTU black hole вполне вероятен.
5. Проверяем apt и Docker на фоне tcpdump
apt update
docker pull debian:stable
Запускайте проблемную команду и одновременно смотрите захват. Когда apt или Docker зависают, в дампе нередко видны ретрансляции без нормального прогресса, особенно после первых успешных пакетов.
Как исправлять: от правильного решения к временному обходу
Главная цель — сделать так, чтобы отправитель изначально не слал пакеты больше допустимого для реального пути, либо чтобы PMTUD снова начал работать как задумано.
Вариант 1. Исправить фильтрацию ICMP
Это лучший путь, если вы контролируете маршрутизаторы, firewall и туннельные узлы. Для IPv4 должен проходить ICMP с сообщением о необходимости фрагментации, а для IPv6 — соответствующие сообщения Packet Too Big. Если их режут «на всякий случай», PMTUD ломается.
На практике многие старые шаблоны firewall излишне агрессивно блокируют ICMP, после чего начинаются трудноуловимые проблемы с TLS, обновлениями и контейнерными registry.
Вариант 2. Уменьшить MTU на туннельном интерфейсе
Если вы точно знаете, что путь уже уже обычных 1500 байт, имеет смысл выставить меньший MTU на интерфейсе WireGuard или GRE. Тогда ядро будет формировать пакеты безопасного размера ещё до отправки.
Пример для временной проверки:
ip link set dev wg0 mtu 1380
ip link set dev gre1 mtu 1476
Конкретные значения зависят от схемы инкапсуляции. Для WireGuard типовые рабочие числа часто находятся в диапазоне 1280–1420, но копировать чужое значение без измерений не стоит. Для GRE также нужно учитывать, что кроме собственного заголовка могут быть дополнительные накладные расходы по нижележащему каналу.
После смены MTU сразу перепроверьте:
tracepath archive.ubuntu.com
apt update
docker pull debian:stable
Вариант 3. MSS clamp для TCP
Если вы не можете быстро починить ICMP или меняете MTU не на всех участках, помогает ограничение MSS на SYN-пакетах. Это особенно эффективно для HTTPS, apt и Docker, потому что они в основном работают по TCP. Суть в том, чтобы стороны с самого начала договорились о меньшем размере TCP-сегмента.
Пример для iptables:
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -o gre1 -j TCPMSS --clamp-mss-to-pmtu
Пример для nftables:
nft add table inet mangle
nft 'add chain inet mangle forward { type filter hook forward priority mangle; policy accept; }'
nft add rule inet mangle forward oifname "wg0" tcp flags syn tcp option maxseg size set rt mtu
nft add rule inet mangle forward oifname "gre1" tcp flags syn tcp option maxseg size set rt mtu
Если трафик рождается на самом хосте, а не форвардится через него, аналогичное правило может потребоваться в цепочке output.
Вариант 4. Маршрут с принудительным MTU
Иногда проблема проявляется только к отдельной сети или хосту. Тогда можно задать MTU на уровне маршрута:
ip route replace 203.0.113.0/24 via 192.0.2.1 dev eth0 mtu 1400
ip route get 203.0.113.10
Метод удобен для точечной диагностики и для специфичных направлений, но если узкое место — весь туннель, лучше править интерфейс или MSS.
Если после исправления MTU вы параллельно приводите в порядок HTTPS-инфраструктуру, не забудьте и про корректные SSL-сертификаты. Они не решают PMTU-проблему, но помогают исключить лишние переменные при разборе TLS-сбоев.

Практический сценарий: WireGuard, apt и docker pull зависают
Представим типичную схему: сервер Debian выходит в интернет через wg0, SSH работает, сайты открываются не все, apt update иногда ждёт по минуте, а docker pull часто зависает.
Смотрите MTU интерфейсов:
ip addrиip -d link show wg0.Проверяете путь:
tracepath registry-1.docker.io.Снимаете дамп:
tcpdump -ni any 'host registry-1.docker.io or icmp or icmp6'.Временно ставите меньший MTU, например
ip link set dev wg0 mtu 1380.Повторяете
apt updateиdocker pull.
Если после снижения MTU проблема исчезла, почти наверняка упёрлись в туннельный overhead или сломанный PMTUD. Дальше уже доводите решение до постоянного: фиксируете MTU в конфигурации WireGuard и, если нужно, добавляете MSS clamp.
Практический сценарий: GRE между площадками, HTTPS открывается через раз
В GRE-кейсе типичен другой симптом: внутренние сервисы доступны, но веб-панели, API и репозитории через HTTPS работают нестабильно. Особенно если между площадками есть смешанные каналы, провайдерские ограничения или вложенный IPsec.
Здесь важно не угадывать, а измерять. Сначала определяете фактический допустимый размер пакета до удалённого адреса, затем уменьшаете MTU на GRE-интерфейсе и проверяете, не исчезли ли ретрансляции. Если после этого длинные HTTPS-ответы и пакетные операции ожили, причина найдена.
Как закрепить решение в Debian/Ubuntu
Временная команда ip link set полезна для проверки, но после перезагрузки изменения пропадут. Постоянная настройка зависит от того, чем управляется сеть: systemd-networkd, Netplan, ifupdown или конфигурацией самого WireGuard.
Для WireGuard MTU обычно задают прямо в конфигурации интерфейса. Для Netplan и networkd — в описании конкретного линка или туннеля. Принцип один: зафиксировать рабочее значение и убедиться, что после рестарта сети оно действительно применяется.
После внесения постоянных изменений полезно сохранить мини-чеклист в документации проекта:
какой интерфейс ограничен по MTU;
почему выбрано именно это значение;
нужен ли
MSS clamp;какие тесты подтверждают исправление;
какие ICMP-пакеты должны быть разрешены firewall.
Типичные ошибки при диагностике
Первая ошибка — проверять только обычным ping. Без запрета фрагментации он может ничего не показать, потому что пакеты будут резаться по пути и тест окажется ложноположительным.
Вторая — снижать MTU наугад до слишком маленьких значений. Да, это часто «чинит» связь, но может ухудшить производительность, особенно на нагруженных TCP-соединениях. Лучше найти минимально достаточное значение.
Третья — надеяться, что проблема касается только одного приложения. Если висит docker pull, а чуть позже начинает глючить и apt, почти всегда стоит проверять общий сетевой путь, а не сами программы.
Четвёртая — забывать про IPv6. В dual-stack среде часть запросов может идти по IPv6, и симптомы будут отличаться от IPv4. Если у вас включён IPv6, проверяйте PMTU и для него тоже.
Когда MTU-проблема особенно вероятна
после включения WireGuard, OpenVPN, IPsec или GRE;
после переноса сервера в другую сеть или к другому провайдеру;
после добавления PPPoE, VLAN stacking или иной инкапсуляции;
когда SSH и ping работают, а HTTPS и загрузки зависают;
когда проблема проявляется только через конкретный маршрут или офисный VPN.
Короткий runbook для продакшена
Подтвердить симптом на реальной команде:
apt update,curl -v,docker pull.Посмотреть интерфейсы и MTU:
ip addr,ip -d link show.Проверить путь:
tracepath.Сделать тесты
ping -M doс разными размерами.Запустить
tcpdumpи поискать ICMPfragmentation neededи TCP retransmissions.Временно уменьшить MTU на туннеле.
Если помогло — зафиксировать MTU постоянно и при необходимости включить
MSS clamp.Проверить firewall: не режет ли он критичные ICMP-сообщения.
Итог
PMTU black hole — одна из самых коварных сетевых проблем в Debian/Ubuntu, потому что маскируется под «странные таймауты» приложений. На деле зависающие HTTPS, apt и docker pull очень часто упираются не в DNS, не в сертификаты и не в registry, а в неправильный MTU по пути, особенно при использовании VPN, GRE и WireGuard.
Рабочая стратегия простая: сначала подтвердить гипотезу инструментами вроде tracepath, ping -M do, tcpdump и анализа маршрутов, затем выбрать корректное исправление — восстановить PMTUD через ICMP, уменьшить MTU на туннеле, применить MSS clamp или задать MTU на конкретном маршруте.
Если после изменения MTU внезапно оживают TLS-соединения, обновления пакетов и загрузка контейнеров — это почти всегда не совпадение, а найденный корень проблемы.


