Debian 13: невідповідність MTU/MSS — чому великі файли зависають і як виправити це правильно

Було корисно?

Ви можете пропінгувати хост. Невеликі сторінки завантажуються через curl. DNS працює. SSH підключається миттєво. А потім ви намагаєтеся
завантажити 4 ГБ образ, відправити резервну копію, rsync’нути VM або завантажити дамп бази даних — і передача сповільнюється до повзання або зовсім зависає.
Індикація прогресу стоїть, ніби чекає дозволу від юридичного відділу.

У Debian 13 це часто зовсім не «проблема Debian». Мережа просто робить те, що ви їй наказали, плюс одна крихітна невідповідність, про яку ви не здогадувалися.
Невідповідності MTU і MSS створюють режими відмови, що працюють вибірково: маленькі пакети проходять, великі — вмирають. Саме так у вас з’являється мережа,
яка у дашбордах виглядає здоровою, але відчуває себе так, ніби боїться великих файлів.

У чому насправді справа (без казок)

MTU — це Maximum Transmission Unit: найбільший розмір IP-пакета, який лінк може передати без фрагментації. Ethernet зазвичай має 1500 байт.
PPPoE часто змушує використовувати 1492. Тунелі (WireGuard, VXLAN, GRE, IPsec) додають накладні заголовки й зменшують ефективний MTU ще більше.

MSS — це Maximum Segment Size: найбільший розмір TCP-даних у сегменті (без урахування заголовків IP/TCP), який хост покладе в один TCP-сегмент.
MSS узгоджується під час TCP-рукопотискання через опції в SYN і SYN-ACK. Якщо path MTU дорівнює 1500, то TCP MSS зазвичай становитиме
1460 (1500 мінус 20 байт IPv4-заголовок мінус 20 байт TCP-заголовок). Для IPv6 MSS зазвичай близько 1440 через більший базовий заголовок.

Схема зависання: чому «маленьке працює, велике — ні»

Ось базова схема:

  • Малі запити та інтерактивні сесії тримають пакети в межах реального path MTU. Вони працюють.
  • Потокові/масові передачі заповнюють канал, відправляють сегменти максимально можливого розміру і врешті натрапляють на пакет, що перевищує реальний path MTU. Такі пакети відкидаються.
  • Якщо відправник ніколи не дізнається правильний MTU (або ігнорує його), він продовжує ретрансмісії тих самих занадто великих сегментів. Тепер у вас «чорна діра».
  • Пропускна здатність TCP падає. Іноді здається, що передача «зависла», іноді вона йде з 3 КБ/с, іноді відбувається таймаут.

Механізм, що мав би вас врятувати, — це Path MTU Discovery (PMTUD). В IPv4 відправник встановлює біт DF (Don’t Fragment). Коли маршрутизатор не може
переслати пакет через надто великий розмір, він повинен надіслати назад ICMP з повідомленням «Fragmentation Needed» і з параметром MTU наступного хопа.
Відправник зменшує розмір і пробує знову.

У ідеальному світі PMTUD — це нудна й непомітна річ. У реальному світі ICMP фільтрують («з міркувань безпеки») міжмережеві екрани, які останній раз
переглядалися ще тоді, коли люди надсилали зміни факсом. Тепер відправник ніколи не отримує підказки «fragmentation needed», і ви отримуєте PMTUD-чорну діру.

Debian 13 тут не виняток — але сучасні параметри за замовчуванням можуть спричиняти появу цієї проблеми частіше:
більше VPN, більше оверлеїв, більше контейнерних мереж, більше IPv6, більше мережевих країв у хмарі, більше «корисних» проміжних пристроїв. Ви шаруєте заголовки, як лазанью,
а потім дивуєтесь, що припущення про 1500 байт перестало працювати.

MTU проти MSS: що саме «неправильне»?

Невідповідність MTU — це властивість лінку/шляху. Невідповідність MSS — це поведінка кінцевого хоста TCP, яку можна підлаштувати під шлях.
Якщо path MTU менший, ніж ви думаєте, ідеально виправити шлях; прагматично — обмежити MSS, щоб TCP ніколи не відправляв пакети, що не вміщаються.

Якщо ви керуєте всією мережею, виправляйте MTU біля джерела: зробіть шлях консистентним, встановіть правильні MTU на тунелях, забезпечте роботу PMTUD.
Якщо ви контролюєте тільки одну сторону (звична корпоративна реальність), MSS clamping на вашому краю часто є найчистішим «ми можемо це відправити сьогодні» рішенням.

Одна перефразована думка від Werner Vogels (надійність/операції): «Усе ламається; проектуйте так, щоб відмови були рутинними і відновлювалися автоматично.»
Проблеми MTU — саме такого роду відмови: рутинні, передбачувані і вирішувані за допомогою запобіжних заходів.

Жарт №1: PMTUD — як офісні плітки: якщо хтось блокує ICMP, ніхто не дізнається важливої новини і всі продовжують приймати ті самі неправильні рішення.

Факти та історія, що пояснюють таку поведінку

Декілька конкретних фактів пояснюють, чому ця проблема постійно повторюється, навіть серед досвідчених команд:

  1. Ethernet 1500 байт MTU став де-факто стандартом, бо врівноважував ефективність і апаратні обмеження в ранньому LAN-дизайні; це не святе, а просто поширене.
  2. Класичний MTU PPPoE — 1492, оскільки PPPoE додає 8 байт накладних витрат зверху на Ethernet-кадр, зменшуючи те, що може нести IP.
  3. Маршрутизатори IPv6 не фрагментують пакети в дорозі. Якщо ви перевищуєте path MTU, ви покладаєтеся на ICMPv6 «Packet Too Big», або пакети зникають у чорну діру.
  4. Фрагментація в IPv4 існує, але її широко уникають, бо фрагментований трафік підвищує ампліфікацію втрат і створює проблеми для безпеки/моніторингу.
  5. PMTUD чорні діри були настільки поширені, що реалізації TCP додали евристики типу Packetization Layer PMTUD (PLPMTUD), щоб вгадувати MTU без покладання на ICMP.
  6. MSS clamping став популярним на крайових пристроях у ISP/VPN сценаріях, бо працює навіть коли ICMP фільтрується; це обхід, що став стандартним кроком.
  7. Jumbo-фрейми (9000 MTU) можуть підвищувати пропускну здатність в мережах зберігання, але тільки якщо кожен хоп їх підтримує — один хоп з 1500 MTU перетворює це на фабрику мовчазних відмов.
  8. VXLAN та схожі оверлеї додають близько ~50 байт накладних витрат (часто більше залежно від підкладки), отже 1500 MTU підкладки означає ~1450-ї придатної MTU в оверлеї.
  9. Ефективний MTU WireGuard залежить від транспорту й маршруту; значення «1420» є поширеним типовим вибором, бо воно уникає фрагментації на типових інтернет-шляхах, але це не універсально.

Це не дрібниці. Саме ці причини пояснюють, чому ваша мережа, яка «працювала минулого року», починає підриватися після впровадження VPN, міграції в хмару або оновлення фаєрвола.

Швидкий план діагностики (перший/другий/третій)

Мета — швидко відповісти на одне питання: Чи ми відкидаємо великі пакети, бо реальний path MTU менший, ніж думає відправник?
Ось порядок дій, який економить найбільше часу у продакшні.

Перший крок: підтвердити, що симптом пов’язаний з розміром, а не загальною втратою

  • Спробуйте невелике та велике завантаження з того самого кінцевого пункту.
  • Виконайте ping з встановленим DF (IPv4) або великий ping (IPv6), щоб знайти найбільший робочий розмір.
  • Слідкуйте за ретрансмісіями і поведінкою «чорної діри» за допомогою ss і tcpdump.

Другий крок: знайти, де змінюється MTU (тунелі, оверлеї, PPPoE, краєві сервіси хмари)

  • Перевірте MTU інтерфейсів: фізичний NIC, VLAN, bridge, VPN, контейнерні veth, тунель.
  • Перевірте маршрути на наявність підказок про MTU.
  • Підтвердіть фактичне інкапсуляційне використання (WireGuard? IPsec? VXLAN? GRE?).

Третій крок: вирішити, де найчистіше правити

  • Якщо ви можете виправити шлях — зробіть це (консистентний MTU по всьому шляху; дозволити ICMP для PMTUD).
  • Якщо не можете — обмежте TCP MSS на краю, ближчому до відправника для уражених потоків.
  • Перевірте зміни повторним тестом і зробіть знімок мережевого трафіку (до/після).

Цей план навмисно нудний. Нудне — це добре. Нудне означає, що ви перестанете виконувати «встановіть MTU 1400 скрізь» за звичкою і почнете робити одну правильну зміну.

Практичні завдання: команди, очікуваний вивід і рішення

Нижче — практичні завдання, які можна виконати на Debian 13 (або будь-якому сучасному Debian-подібному) під час інцидентної сесії.
Кожне завдання містить: команду, що означає вивід, і яке рішення прийняти далі.

Завдання 1: швидко перевірити MTU інтерфейсів

cr0x@server:~$ ip -br link
lo               UNKNOWN        00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
enp3s0           UP             3c:ec:ef:12:34:56 <BROADCAST,MULTICAST,UP,LOWER_UP>
wg0              UNKNOWN        9a:bc:de:f0:12:34 <POINTOPOINT,NOARP,UP,LOWER_UP>
br0              UP             02:42:ac:11:00:01 <BROADCAST,MULTICAST,UP,LOWER_UP>
cr0x@server:~$ ip link show dev enp3s0 | grep -i mtu
mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000

Значення: Шукайте підозрілі розбіжності: фізичний NIC має 1500, але тунель/оверлей очікує 1420; або bridge на 1500, а член-інтерфейс — менший.

Рішення: Якщо «вищий» інтерфейс (bridge/тунель) має MTU більше, ніж може нести інкапсульований шлях, ви знайшли головного підозрюваного.

Завдання 2: огляньте маршрути на підказки про MTU

cr0x@server:~$ ip route get 1.1.1.1
1.1.1.1 via 192.0.2.1 dev enp3s0 src 192.0.2.10 uid 1000
    cache

Значення: Linux може зберігати MTU на рівні маршруту, але не завжди покаже його, якщо не встановлено. Все ж корисно, щоб перевірити, яким інтерфейсом йде трафік.

Рішення: Якщо трафік виходить через тунельний інтерфейс або VRF, якого ви не очікували — зупиніться. Діагностуйте цей шлях першочергово.

Завдання 3: підтвердити, що зависання залежить від розміру за допомогою curl

cr0x@server:~$ curl -o /dev/null -s -w "time=%{time_total} size=%{size_download}\n" https://repo.example.net/small.bin
time=0.18 size=1048576
cr0x@server:~$ curl -o /dev/null -v https://repo.example.net/large.iso
* Connected to repo.example.net (203.0.113.20) port 443
> GET /large.iso HTTP/1.1
> Host: repo.example.net
...
< HTTP/1.1 200 OK
...
  0 4096M    0 1024k    0     0   890k      0  1:18:33  0:00:01  1:18:32  0:00:00
  0 4096M    0 1024k    0     0      0      0 --:--:--  0:00:10 --:--:--     0

Значення: Велика передача стартує, а потім пропускна здатність падає. Це класичний випадок «деякі пакети проходять, потім чорна діра».

Рішення: Перейдіть до тестування PMTUD і захоплення пакетів. Не витрачайте час на DNS, сертифікати CA чи «можливо сервер повільний».

Завдання 4: IPv4 PMTUD тест за допомогою ping з DF (знайти максимальний payload)

cr0x@server:~$ ping -M do -s 1472 -c 2 203.0.113.20
PING 203.0.113.20 (203.0.113.20) 1472(1500) bytes of data.
ping: local error: message too long, mtu=1492
ping: local error: message too long, mtu=1492

--- 203.0.113.20 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1007ms

Значення: Ваш хост вже знає (або якийсь інтерфейс примушує) MTU=1492 при відправленні. Payload 1472 припускає MTU 1500;
воно падає і підказує 1492.

Рішення: Повторіть тест з -s 1464 (1492-28) і подивіться, чи пройде. Якщо пройде — ви в зоні PPPoE або тунелю.

Завдання 5: бінарний пошук path MTU (IPv4)

cr0x@server:~$ ping -M do -s 1464 -c 2 203.0.113.20
PING 203.0.113.20 (203.0.113.20) 1464(1492) bytes of data.
1472 bytes from 203.0.113.20: icmp_seq=1 ttl=51 time=22.1 ms
1472 bytes from 203.0.113.20: icmp_seq=2 ttl=51 time=22.0 ms

--- 203.0.113.20 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms

Значення: End-to-end path MTU становить не більше за 1492 (для IPv4 на цьому шляху).

Рішення: Якщо відправні хости використовують MTU 1500 і не адаптуються, обмежуйте MSS або налаштуйте MTU відповідно до цієї реальності.

Завдання 6: базовий IPv6 PMTU тест

cr0x@server:~$ ping -6 -s 1452 -c 2 2001:db8:100::20
PING 2001:db8:100::20(2001:db8:100::20) 1452 data bytes
From 2001:db8:200::1 icmp_seq=1 Packet too big: mtu=1420
From 2001:db8:200::1 icmp_seq=2 Packet too big: mtu=1420

--- 2001:db8:100::20 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1002ms

Значення: IPv6 каже вам path MTU (1420). Це найкращий випадок: ICMPv6 не блокується і PMTUD працює.

Рішення: Узгодьте MTU тунелю/інтерфейсу і/або застосуйте MSS clamp також для IPv6. Не «виправляйте лише IPv4» і вважайте проблему вирішеною.

Завдання 7: спостерігайте TCP ретрансмісії на клієнті під час зависання

cr0x@server:~$ ss -ti dst 203.0.113.20:443
ESTAB 0 0 192.0.2.10:52144 203.0.113.20:https
	 cubic wscale:7,7 rto:1000 rtt:24.1/4.2 ato:40 mss:1460 pmtu:1500 rcvmss:536 advmss:1460 cwnd:10 bytes_sent:1048576 bytes_acked:1048576 bytes_retrans:65536 retrans:12

Значення: Кількість ретрансмісій зростає. MSS = 1460 і PMTU показує 1500, але ваші попередні тести свідчать про менший MTU. Така невідповідність — суть проблеми.

Рішення: Доведіть, чи відсутні ICMP «frag needed», або чи неправильно налаштований MTU тунелю. Перейдіть до tcpdump.

Завдання 8: захопіть PMTUD-пов’язані ICMP під час відтворення

cr0x@server:~$ sudo tcpdump -ni enp3s0 '(icmp and (icmp[0]=3 and icmp[1]=4)) or (tcp and host 203.0.113.20 and port 443)'
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp3s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:01:10.112233 IP 192.0.2.10.52144 > 203.0.113.20.443: Flags [P.], seq 1:1449, ack 1, win 501, length 1448
12:01:10.212244 IP 192.0.2.10.52144 > 203.0.113.20.443: Flags [P.], seq 1449:2897, ack 1, win 501, length 1448
12:01:11.312255 IP 192.0.2.10.52144 > 203.0.113.20.443: Flags [P.], seq 1449:2897, ack 1, win 501, length 1448
12:01:12.412266 IP 192.0.2.10.52144 > 203.0.113.20.443: Flags [P.], seq 1449:2897, ack 1, win 501, length 1448

Значення: Ви бачите повторні ретрансмісії того самого сегмента, але немає ICMP type 3/code 4 у відповідь. Це підпис PMTUD-чорної діри.

Рішення: Або дозволіть потрібні ICMP-повідомлення назад, або обмежте MSS, щоб ніколи не відправляти занадто великі сегменти.

Завдання 9: перевірте локальний фаєрвол на предмет блокування PMTUD ICMP

cr0x@server:~$ sudo nft list ruleset | sed -n '1,120p'
table inet filter {
	chain input {
		type filter hook input priority filter; policy drop;
		ct state established,related accept
		iif "lo" accept
		tcp dport { 22 } accept
	}
	chain forward {
		type filter hook forward priority filter; policy drop;
	}
	chain output {
		type filter hook output priority filter; policy accept;
	}
}

Значення: Політика INPUT за замовчуванням кидає пакети, але приймає established,related. ICMP-помилки зазвичай класифікуються як «related» до існуючого потоку;
це добре, але не гарантовано залежно від налаштувань conntrack і типу ICMP.

Рішення: Якщо ви бачите явні відкидання ICMP або ICMPv6 — виправте це перш за все. PMTUD залежить від цих повідомлень.

Завдання 10: підтвердьте накладні витрати тунелю і MTU у WireGuard

cr0x@server:~$ ip link show dev wg0 | grep -i mtu
mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
cr0x@server:~$ sudo wg show wg0
interface: wg0
  public key: 3rY...redacted
  listening port: 51820

peer: q8S...redacted
  endpoint: 198.51.100.77:51820
  allowed ips: 10.10.0.0/16
  latest handshake: 1 minute, 2 seconds ago
  transfer: 1.32 GiB received, 2.01 GiB sent

Значення: wg0 вже встановлений на 1420. Якщо внутрішні інтерфейси мають 1500 і маршрутизують туди, ви все одно можете відправляти занадто великі пакети
всередині namespace/bridge перед досягненням межі тунелю.

Рішення: Переконайтеся, що відправний інтерфейс для трафіку в тунелі має MTU ≤ MTU wg0 (або застосуйте MSS clamp для трафіку, що входить у wg0).

Завдання 11: перевірте MTU bridge/veth для хостів з контейнерами

cr0x@server:~$ ip -d link show br0 | sed -n '1,25p'
7: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
    link/ether 02:42:ac:11:00:01 brd ff:ff:ff:ff:ff:ff
    bridge forward_delay 1500 hello_time 200 max_age 2000 stp_state 0 priority 32768
cr0x@server:~$ ip -br link | grep veth | head
veth9f2a2c3       UP             9a:3c:1d:aa:bb:cc <BROADCAST,MULTICAST,UP,LOWER_UP>
veth6a1b7d8       UP             4e:55:66:77:88:99 <BROADCAST,MULTICAST,UP,LOWER_UP>

Значення: br0 має MTU 1500. Якщо підкладка маршруту має ~1450 через оверлей, ваші поди/контейнери можуть генерувати 1500-байт пакети, які потім відкидаються.

Рішення: В оверлейних середовищах встановлюйте MTU для подів/bridge відповідно (або застосовуйте MSS clamp на виході вузла).

Завдання 12: перевірте узгоджений MSS у реальному з’єднанні (tcpdump SYN опції)

cr0x@server:~$ sudo tcpdump -ni enp3s0 -c 6 'tcp port 443 and host 203.0.113.20 and (tcp[tcpflags] & (tcp-syn|tcp-ack) != 0)'
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp3s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:05:01.000111 IP 192.0.2.10.52210 > 203.0.113.20.443: Flags [S], seq 111111111, win 64240, options [mss 1460,sackOK,TS val 123 ecr 0,nop,wscale 7], length 0
12:05:01.020222 IP 203.0.113.20.443 > 192.0.2.10.52210: Flags [S.], seq 222222222, ack 111111112, win 65160, options [mss 1440,sackOK,TS val 456 ecr 123,nop,wscale 8], length 0

Значення: Ваш хост запропонував MSS 1460. Сервер відповів 1440. Якщо реальний path MTU менший (наприклад 1492 або 1420),
ви хочете, щоб MSS це відображав (1460 підходить для 1500; для 1492 MSS має бути 1452).

Рішення: Якщо ви не можете покладатися на PMTUD, обмежте MSS до безпечного значення на основі виміряного path MTU (і зробіть це для v4 і v6).

Завдання 13: перевірте поведінку ядра щодо MTU/MTU probing

cr0x@server:~$ sysctl net.ipv4.tcp_mtu_probing net.ipv4.ip_no_pmtu_disc
net.ipv4.tcp_mtu_probing = 0
net.ipv4.ip_no_pmtu_disc = 0

Значення: tcp_mtu_probing=0 означає, що ядро не буде активно пробувати менші MTU при чорній дірі; ip_no_pmtu_disc=0 означає, що PMTUD увімкнено.

Рішення: Не «виправляйте» це відключенням PMTUD глобально. Розгляньте ввімкнення MTU probing вибірково, якщо не можете швидко виправити мережу, але ставтесь до цього як до запасного рішення.

Завдання 14: переконайтеся, що ICMP дозволено через фаєрвол (IPv4 + IPv6)

cr0x@server:~$ sudo nft list chain inet filter input
table inet filter {
	chain input {
		type filter hook input priority filter; policy drop;
		ct state established,related accept
		iif "lo" accept
		ip protocol icmp accept
		ip6 nexthdr ipv6-icmp accept
		tcp dport 22 accept
	}
}

Значення: Це правило «не ускладнюйте»: дозвольте ICMP і ICMPv6, принаймні для помилок і PMTUD-повідомлень, бажано з розумними обмеженнями.

Рішення: Якщо ICMP не дозволено — виправте це. Якщо не можете (корпоративний фаєрвол вище), MSS clamping стає вашим надійним обхідним шляхом.

Завдання 15: впровадити MSS clamping за допомогою nftables (IPv4/IPv6) і перевірити лічильники

cr0x@server:~$ sudo nft add table inet mssclamp
cr0x@server:~$ sudo nft 'add chain inet mssclamp forward { type filter hook forward priority mangle; policy accept; }'
cr0x@server:~$ sudo nft add rule inet mssclamp forward tcp flags syn tcp option maxseg size set rt mtu
cr0x@server:~$ sudo nft add rule inet mssclamp forward ip6 nexthdr tcp tcp flags syn tcp option maxseg size set rt mtu
cr0x@server:~$ sudo nft -a list chain inet mssclamp forward
table inet mssclamp {
	chain forward {
		type filter hook forward priority mangle; policy accept;
		tcp flags syn tcp option maxseg size set rt mtu # handle 2
		ip6 nexthdr tcp tcp flags syn tcp option maxseg size set rt mtu # handle 3
	}
}

Значення: Це обмежує MSS у SYN-пакетах до MTU маршруту автоматично. Зазвичай це чистіше, ніж жорстко задавати число, бо адаптується під маршрут.

Рішення: Використовуйте обмеження MSS на підставі маршруту на шлюзах/маршрутизаторах. На окремих хостах можна обмежувати в ланцюгу output, якщо саме хост ініціює потоки.

Завдання 16: якщо потрібно, задайте жорстко відоме MSS

cr0x@server:~$ sudo nft add rule inet mssclamp forward ip protocol tcp tcp flags syn tcp option maxseg size set 1360
cr0x@server:~$ sudo nft add rule inet mssclamp forward ip6 nexthdr tcp tcp flags syn tcp option maxseg size set 1360

Значення: MSS 1360 часто безпечний для «Інтернет + тунелі + невідомі фактори», але це грубий інструмент. Він обмінює продуктивність на надійність.

Рішення: Віддавайте перевагу обмеженню за маршрутом. Жорстке встановлення — тільки якщо ви не можете отримати консистентну інформацію по маршруту.

Завдання 17: зробіть MTU-правки постійними в Debian (приклад systemd-networkd)

cr0x@server:~$ sudo sed -n '1,120p' /etc/systemd/network/10-enp3s0.network
[Match]
Name=enp3s0

[Network]
DHCP=yes

[Link]
MTUBytes=1492
cr0x@server:~$ sudo systemctl restart systemd-networkd
cr0x@server:~$ ip link show dev enp3s0 | grep -i mtu
mtu 1492 qdisc mq state UP mode DEFAULT group default qlen 1000

Значення: Ви вирівняли MTU хоста під реальну вимогу шляху (типово для PPPoE або відомого тунелю).

Рішення: Якщо лише певні призначення уражені (деякі шляхи, деякі місця), не знижуйте глобально MTU на всіх інтерфейсах. Використовуйте MTU на маршруті або MSS clamping на краю.

Завдання 18: перевірте виправлення повторюваним тестом передачі

cr0x@server:~$ curl -o /dev/null -s -w "time=%{time_total} speed=%{speed_download}\n" https://repo.example.net/large.iso
time=43.22 speed=101234567

Значення: Передача завершилася і швидкість стабільна. Симптом зависання зник.

Рішення: Зніміть короткий tcpdump «після» і зафіксуйте зміни з чіткою нотаткою інциденту: що ламалося, що ви змінили, як довели виправлення.

Жарт №2: Проблеми MTU — єдині мережеві проблеми, де «просто зменшіть» одночасно є поганою порадою і, на диво, іноді правильним рішенням.

Три короткі корпоративні історії з практики

Міні-історія 1: інцидент через хибне припущення

Команда розгорнула новий VPN site-to-site між двома офісами. Новий пристрій «підтримував jumbo frames», і хтось вирішив, що оскільки LAN вже використовує MTU 9000 для зберігання,
VPN теж має відповідати. Узгодженість, правда?

Увімкнення пройшло гладко першу годину. Моніторинг показував чисті пінги і нормальну затримку. SSH працював. Люди тихо святкували, бо ніхто не довіряє гучним святкуванням.
Потім почався нічний бекап, і робота зависла на кількох відсотках. ПЗ для бекапу логувало повторні спроби і «connection reset». Команда зберігання запевняла, що їхня частина ок;
мережники казали, що тунель піднятий. Обидві команди були праві і водночас були неправі.

Проблема: інтерфейс VPN був встановлений на 9000, але ISP-аплінк посередині — ні. PMTUD мав би це вирішити, якби не те, що upstream фаєрвол фільтрував повідомлення ICMP fragmentation-needed.
Тож відправник продовжував надсилати величезні пакети, які зникали без сліду. Малий контрольний трафік працював, великий — помирав.

Виправлення було майже принизливо простим: встановити MTU тунелю на значення, що поміститься в реальний шлях (або застосувати MSS clamp на вході тунелю), і дозволити потрібні типи ICMP.
Кореневою причиною не була «нестабільність VPN». Це було «ми припустили, що Інтернет поважає наш LAN MTU». Інтернет не переймається вашими припущеннями.

Важливішою зміною, ніж технічний фікс, було культурне: вони додали валідацію MTU/PMTU до кожного розгортання тунелю і припинили вважати ICMP опційним шумом. Жодних героїчних дій.
Просто менше дзвінків о 2-й ночі.

Міні-історія 2: оптимізація, що відклалася боком

Інша компанія мала сервіс високої пропускної здатності для переміщення артефактів між билд-агентами і центральним кешем. Хтось помітив, що NICи, свічи та гіпервізори підтримують jumbo frames.
Сервіс чутливий до пропускної здатності, тож вони ввімкнули MTU 9000 на серверах. У тій же стійці результати були хороші. Усі кивнули.

Через кілька тижнів новий набір билд-агентів у іншому DC почав повідомляти про періодичні таймаути під час завантаження великих артефактів. Болісний момент:
падали лише «великі» збірки. Малі проходили. Команда шукала CPU steal, TLS-настройки і налаштування балансувальника. Оновлювали ядра. Змінювали рівень стиснення артефактів.
Проблеми лишалися.

У підґрунті шлях між DC мав єдиний сегмент з MTU 1500. Сервери з jumbo щасливо відправляли великі сегменти, які фрагментувалися або відкидалися в залежності від хопа.
Деякі потоки переживали через інше маршрутування, деякі — помирали через ECMP, що обирав більш строгий шлях. Нові билд-агенти «нещасливо» часто потрапляли на поганий маршрут.

Вони виправили це, відкотивши jumbo frames на сервісі артефактів і стандартизувавши MTU по між-DC шляху перед повторним увімкненням.
Jumbo frames не були поганими самі по собі; вони стали проблемою як оптимізація, застосована лише частково по топології. Приріст продуктивності був реальним,
але витрати на надійність виявилися вищими, ніж хто-небудь оцінив.

Висновок постмортему був різким: не впроваджуйте частково зміни MTU. Або ви дотримуєтесь скрізь, або лишаєте 1500 і витрачаєте бюджет продуктивності в іншому місці.

Міні-історія 3: нудна, але правильна практика, що врятувала ситуацію

Фінансова організація мала практику, що виглядала бюрократичною: коли мережеві зміни стосувалися тунелів, оверлеїв або WAN-ліній, вимагали pre-flight чекліст.
Там був пункт, який інженери любили ненавидіти:
«Перевірити PMTUD або застосувати MSS clamp; додати докази».

Під час міграції на нову платформу віддаленого доступу інженер пройшов чекліст і виявив, що великі DF ping-и падали через певного провайдера шляху.
Малі пакети були в порядку. Край провайдера фільтрував певні типи ICMP (звісно), але лише в одному регіоні. Інженер додав MSS clamp на VPN-концентратор для того регіону і прикріпив знімки «до/після».
Міграція продовжилася.

Через два тижні інша команда повідомила про «зависання великих завантажень» з того регіону. На черговому виклику інженер відкрив нотатки про міграцію,
побачив MSS clamp і тестові докази і одразу виключив MTU-чорну діру як нову причину. Вони сфокусувалися на регресії в додатку і швидко її виправили.

Нудна практика не лише запобігла аварії. Вона запобігла хибній діагностиці під час пізнішого інциденту, що майже однаково корисно. Добрі нотатки — операційний мультиплікатор.

Виправити правильно: пріоритетні рішення

Існує десяток способів «виправити» невідповідність MTU/MSS. Лише кілька з них чисті. Ось порядок, який я рекомендую в продакшні, із сильним ухилом до
змін, які можна пояснити о 3-й ночі і відкотити опівдні.

1) Вирівняйте MTU по шляху (найкраще, найскладніше)

Якщо ви володієте мережею end-to-end, стандартизуйте MTU по всьому шляху. Для оверлеїв збільшіть MTU підкладки, щоб оверлей міг залишатися на 1500.
Приклад: якщо VXLAN додає ~50 байт, встановіть MTU підкладки >=1550, щоб оверлей міг працювати при 1500 без фрагментації.

Це «зробити правильно» виправлення. Воно також вимагає координації між командами і постачальниками, тому не завжди єдине доступне.

2) Забезпечте роботу PMTUD (дозвольте потрібні ICMP)

PMTUD не є опцією, якщо ви очікуєте коректної роботи сучасних мереж. Дозвольте ICMP type 3/code 4 в IPv4 («fragmentation needed»).
Дозвольте ICMPv6 «packet too big» та інші необхідні повідомлення в IPv6.

Головне — не «дозволяйте весь ICMP назавжди». Головне — “не ламайте протокол, а потім дивуйтеся”.
Якщо потрібно — робіть rate-limit обережно і тестуйте.

3) Обмежте TCP MSS на краю (найкраще прагматичне рішення)

MSS clamping змінює TCP MSS під час SYN, щоб кінцеві точки погодилися на менші сегменти, які вміщуються в path MTU.
Це працює навіть коли ICMP фільтрується. Не вимагає змін на хостах. Це зворотне, легко локалізується і масштабоване.

Використовуйте обмеження MSS на основі маршруту там, де можливо (приклад в nftables). Жорстке встановлення MSS прийнятне в хаотичних середовищах, але розглядайте його як тимчасову пластир.

4) Знижуйте MTU на хості лише якщо хост дійсно живе на обмеженому шляху

Зниження MTU на інтерфейсі хоста є правильним, коли основний вихід цього хоста дійсно обмежений (клаcичний PPPoE з 1492).
Це не правильно, якщо лише деякі призначення обмежені. Тоді ви караєте весь трафік, щоб виправити один шлях.

5) Увімкніть TCP MTU probing як тактичний обхід, а не стратегію

Увімкнення net.ipv4.tcp_mtu_probing може дозволити Linux відновитися з чорних дір, пробуючи менші сегменти.
Це може допомогти, якщо ви не контролюєте фаєрвол посередині і потрібне швидке полегшення.

Але не плутайте «ядро вгадало проблему» з «мережа здорова». Якщо можна — застосуйте MSS clamp або відновіть ICMP.

Поширені помилки: симптом → причина → виправлення

Це патерни, які я постійно бачу у реальних організаціях. Виправлення конкретні, бо невизначені поради перетворюють інциденти на «таємниці».

1) Великі HTTPS-завантаження зависають, а малі сторінки відкриваються

Симптом: Браузер відкриває сайт; завантаження ISO зависає на кількох МБ.

Корінь проблеми: PMTUD-чорна діра: fragmentation-needed ICMP блокується десь; відправник продовжує використовувати великий MSS/MTU.

Виправлення: Дозвольте ICMP type 3/code 4 (IPv4) і ICMPv6 Packet Too Big; або застосуйте MSS clamp на шлюзі для TCP/443.

2) SSH працює, scp/rsync зависає або повзе

Симптом: Інтерактивний SSH нормальний; копіювання файлів зависає або дуже повільне.

Корінь проблеми: Дані пакети досягають обмеження path MTU; ретрансмісії вибухають; інтерактивні пакети маленькі і проходять.

Виправлення: Підтвердіть DF ping; обмежте MSS для TCP/22 на шляху; перевірте, що ретрансмісії зменшилися після фіксу.

3) Kubernetes: деякі поди можуть завантажувати образи, інші таймаутять

Симптом: Вузол A у порядку; вузол B не може завантажити великі шари; перезавантаження іноді «вирішує» проблему.

Корінь проблеми: Змішаний MTU у CNI оверлеї/підкладках; ECMP виокремлює різні шляхи з різними ефективними MTU.

Виправлення: Узгодьте MTU CNI з підкладкою; або обмежте MSS на виході вузла; стандартизуйте MTU на вузлах.

4) «Ми ввімкнули jumbo frames і тепер між-DC реплікація нестабільна»

Симптом: Сесії реплікації скидаються, великі передачі іноді падають.

Корінь проблеми: Jumbo frames ввімкнено лише на частині сегментів; один 1500-хоп викликає фрагментацію/відкидання.

Виправлення: Відкотіть до 1500, поки весь шлях не підтримає jumbo; потім повторно увімкніть з end-to-end валідацією.

5) IPv6 повільніший або падає лише для великих передач

Симптом: Двостековий хост віддає перевагу IPv6; великі передачі зависають, а IPv4 працює.

Корінь проблеми: ICMPv6 Packet Too Big блокується; IPv6-маршрутизатори не фрагментують; утворюється чорна діра.

Виправлення: Дозвольте ICMPv6 правильно; обмежте MSS для IPv6; перевірте за допомогою ping -6 і tcpdump.

6) «Ми поставили MTU 1400 скрізь» і продуктивність впала

Симптом: Усе працює, але пропускна здатність знизилась і CPU завантаження зросло.

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

Виправлення: Виміряйте фактичний PMTU; встановіть MTU/MSS мінімально потрібні, а не за довільним забобоном.

Контрольні списки / покроковий план

Чекліст A: коли велика передача зависла прямо зараз

  1. Відтворіть проблемою одним командним викликом (curl або scp) і зафіксуйте час.
  2. Запустіть DF ping (IPv4) або великий ping (IPv6) до того ж призначення; знайдіть найбільший робочий розмір.
  3. Перевірте ss -ti на ретрансмісії та значення MSS/PMTU під час зависання.
  4. Зробіть короткий tcpdump, шукаючи повторні ретрансмісії і відсутність ICMP «too big».
  5. Якщо ICMP блокується й ви контролюєте край: застосуйте MSS clamping (на основі маршруту, якщо можливо).
  6. Повторіть тест передачі; захопіть «після» докази; зафіксуйте зміни постійно.

Чекліст B: перед розгортанням тунелю/оверлею

  1. Розрахуйте накладні витрати (тунель + інкапсуляція + можливі VLAN теги) і визначте цільовий MTU.
  2. Встановіть MTU підкладки, щоб підтримати MTU оверлею (переважно), або зменшіть MTU оверлею (допустимо).
  3. Переконайтеся, що ICMP/ICMPv6, потрібні для PMTUD, дозволені крізь межі безпеки.
  4. Підтвердіть за допомогою DF ping і реального тесту великої передачі через тунель.
  5. Документуйте обране MTU, де воно застосоване, і які докази ви захопили.

Чекліст C: вибір «чистого» виправлення

  • Ви контролюєте весь шлях: стандартизуйте MTU end-to-end; утримуйте оверлей на 1500 якщо можливо; забезпечуйте роботу PMTUD.
  • Ви контролюєте лише свій край: route-based MSS clamping + перевірка PMTU; опційно налаштуйте локальний MTU для відомих обмежених лінків.
  • Ви контролюєте лише один хост: налаштуйте MTU на відповідному інтерфейсі, якщо цей хост завжди використовує обмежений шлях; інакше розгляньте local MSS clamp у output.

Питання й відповіді (FAQ)

1) Чому ping-и проходять, а великі TCP-передачі падають?

Тому що типовий ping малий (payload за замовчуванням 56 байт). Він ніколи не перевищує path MTU. Великі TCP-передачі використовують сегменти близькі до MTU,
що викликає відкидання, коли реальний path MTU менший.

2) Це дійсно MTU/MSS, чи може це бути загальною втратою пакетів?

Загальні втрати зазвичай шкодять усім: інтерактивні сесії, малі завантаження, API-запити. PMTUD-чорні діри вибіркові: мале працює, велике зависає.
Доведіть це DF ping тестами і tcpdump з повторними ретрансмісіями без ICMP «too big».

3) У чому різниця між виправленням MTU і обмеженням MSS?

Виправлення MTU робить мережевий шлях здатним переносити пакети, які ви надсилаєте, послідовно. Обмеження MSS повідомляє TCP-ендпоінтам відправляти менші дані,
щоб пакети вміщалися у наявний шлях. Виправлення MTU — архітектурне; MSS clamp — прагматичне операційне.

4) Чи варто просто встановити MTU 1400 скрізь?

Ні. Це може приховати симптом, але це податок на продуктивність і може зламати внутрішні шляхи, що підтримують 1500 або jumbo frames.
Виміряйте реальний PMTU і зробіть мінімальну зміну, що відновлює коректність.

5) Чи змінює Debian 13 щось у поведінці MTU?

Debian 13 використовує сучасні ядра і інструменти (systemd-networkd, nftables, сучасні TCP-поведінки). Проблема не специфічна для Debian.
Але Debian 13 полегшує реалізацію чистих виправлень (nftables MSS clamp, консистентна конфігурація мережі), якщо правильно використовувати стек.

6) Чи безпечно дозволяти ICMP через фаєрволи?

«Дозволити весь ICMP» — це ліниве рішення. «Блокувати весь ICMP» — гірше. Слід дозволити необхідні типи ICMP/ICMPv6 для повідомлень про помилки і PMTUD,
бажано з обмеженнями по швидкості. Якщо ви їх блокуєте, ви ламаєте базову поведінку Інтернету і платите за це у вигляді інцидентів.

7) Яке MSS значення обмежувати?

Віддавайте перевагу route-based MSS clamping (set rt mtu), щоб він адаптувався. Якщо потрібно жорстко задавати, обчисліть з path MTU:
IPv4 MSS ≈ MTU-40, IPv6 MSS ≈ MTU-60 (залежно від опцій). Коли не впевнені — оберіть консервативне значення і уточнюйте його вимірюванням.

8) Чому це відбувається лише для деяких призначень?

Різні призначення можуть проходити різними шляхами (ECMP, різні пірингові точки, різні VPN-виходи), кожен з яких має різний обмежувальний MTU або фільтрацію ICMP.
Тому один хост може «працювати до A, падати до B».

9) Чи можуть проміжні пристрої переписувати MSS?

Так. Деякі фаєрволи і балансувальники MSS обмежують автоматично. Це може маскувати проблему — або ускладнити її, якщо лише частина шляхів обмежує.
Розглядайте MSS як те, що може змінюватися в дорозі, і перевіряйте це за допомогою tcpdump SYN опцій.

10) А якщо це UDP (наприклад, деякі storage або стрімінг протоколи)?

MSS clamping — тільки для TCP. Для UDP-навантажень потрібне правильне налаштування MTU і/або контроль фрагментації на рівні програми.
На практиці виправте path MTU або налаштуйте застосунок на менші дейтаграми.

Наступні кроки, які можна зробити сьогодні

Якщо у вас зависають великі передачі на Debian 13, розглядайте це як реальну мережеву помилку, а не як привид.
Зробіть три речі, у такому порядку:

  1. Доведіть path MTU. Запустіть DF ping тести (IPv4) і/або IPv6 «packet too big» тести. Зафіксуйте найбільший робочий розмір.
  2. Захопіть докази. 30-секундний tcpdump з повторними ретрансмісіями і відсутністю ICMP важить більше тисячі Slack-сперечань.
  3. Застосуйте одне чисте виправлення. Переважно: вирівняти MTU по шляху і дозволити PMTUD ICMP. Якщо не можна — обмежте MSS на краю через nftables.

Після виправлення повторіть той самий тест потокової передачі, потім збережіть виводи і захоплення разом з записом змін. Різниця між «ми виправили» і «нам пощастило» — це документація і відтворюваність.
А ще — майбутній ви буде вдячний.

← Попередня
MySQL проти Elasticsearch для пошуку в e‑commerce: чому SQL ламається під фільтрами
Наступна →
Debian 13: Нова назва інтерфейсу зламала мережу — стабільні імена, що витримують перезавантаження (справа №67)

Залишити коментар