"Быстрый
<br />
Ping идёт, сайты не открываются — проблема в MTU/MSS. Сначала проверь размер пакета, потом ставь Clamping. Дальше — почему это работает и где именно ломается.<br />
<p>Проверка MTU:</p>
<pre><code class="language-bash">ping -M do -s 1472 8.8.8.8
</code></pre>
<p>Если пакеты не проходят — включай Clamping. На Linux:</p>
<pre><code class="language-bash">iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
</code></pre>
<p>На MikroTik:</p>
<pre><code class="language-bash">/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn \
action=change-mss new-mss=clamp-to-pmtu
</code></pre>
<h2>Симптомы: узнаёшь себя?</h2>
<p>Не лезь в теорию, пока не сверился со списком. Если хотя бы один пункт совпадает <a title="0.0.0.0 — что это такое: адрес, маска, подсеть и default route" href="https://it-apteka.com/0-0-0-0-chto-jeto-takoe-adres-maska-podset-i-default-route/" target="_blank" rel="noopener" data-wpil-monitor-id="1435">— ты по адресу</a>.</p>
<ul>
<li>Ping на 8.8.8.8 проходит, сайты не открываются. Или открываются частично — шапка есть, контент не грузится</li>
<li>VPN поднялся, IP получен, handshake прошёл — но браузер крутит загрузку и молчит</li>
<li>Маленькие страницы работают. Большие — нет. Картинки не грузятся, текст есть</li>
<li>Через мобильный интернет всё летает. Через домашний роутер — не работает ничего</li>
<li>После подключения PPPoE большие команды в SSH зависают. Маленькие — ок</li>
<li>OpenVPN или <a title="VPN на MikroTik: полный гайд 2026 — WireGuard, L2TP/IPsec, IKEv2, настройка сервера и клиента" href="https://it-apteka.com/vpn-na-mikrotik-polnyj-gajd-2026-wireguard-l2tp-ipsec-ikev2-nastrojka-servera-i-klienta/" target="_blank" rel="noopener" data-wpil-monitor-id="1432">WireGuard поднялся —</a> но браузер пустой</li>
<li>HTTPS не работает, HTTP иногда работает. Или наоборот — зависит от фазы луны</li>
</ul>
<p>Всё это — одна болезнь. MTU mismatch. Лечится одним способом — MSS Clamping. Читай дальше.</p>
<h2>MTU и MSS: два числа, один смысл</h2>
<p><strong>MTU (Maximum Transmission Unit)</strong> — максимальный размер пакета на уровне L2/L3. Ethernet: 1500 байт. PPPoE отъедает 8 байт на свой заголовок — остаётся 1492. WireGuard отъедает ещё больше. Каждый туннель — это минус несколько байт к MTU.</p>
<p><strong>MSS (Maximum Segment Size)</strong> — максимальный размер TCP-данных в одном сегменте. Без IP и TCP заголовков. Формула одна на всю жизнь:</p>
<pre><code class="language-bash">MSS = MTU - 20 (IP-заголовок) - 20 (TCP-заголовок)
MSS = MTU - 40
Стандартный Ethernet:
MSS = 1500 - 40 = 1460 байт
PPPoE:
MSS = 1492 - 40 = 1452 байт
WireGuard (типичный):
MSS = 1420 - 40 = 1380 байт
</code></pre>
<p>MSS передаётся в SYN-пакете при установке соединения. Клиент говорит серверу: «не шли мне сегменты больше X байт». Сервер отвечает своим значением. Оба берут меньшее — и работают с ним.</p>
<p>Вот тут важно: MSS договаривается один раз, в самом начале. Если где-то на пути есть звено с меньшим MTU — и никто об этом не знает — начинается то, что ты сейчас читаешь эту статью.</p>
<h2>Почему PMTUD не работает — и при чём тут ICMP</h2>
<p>В теории есть механизм Path MTU Discovery. Должен сам находить минимальный MTU на всём пути. Работает через ICMP: если пакет слишком большой для какого-то звена — роутер отправляет ICMP Fragmentation Needed (Type 3, Code 4) и сообщает максимальный размер.</p>
<p>Звучит хорошо. На практике — ломается постоянно. Причина банальная: кто-то заблокировал ICMP.</p>
<p>Кто-то режет весь ICMP «из соображений безопасности» — и не думает что сломал PMTUD. Кто-то пропускает ping (Echo/Reply) но режет Type 3 Code 4 — именно тот который нужен. Это называется ICMP Black Hole. Дыра, в которую падают твои соединения.</p>
<p>Итог: отправитель шлёт пакет 1500 байт. Роутер на PPPoE-участке видит — не пролезет в 1492. Пытается отправить ICMP Fragmentation Needed. Пакет дропается по дороге. Отправитель ничего не знает. Продолжает слать 1500-байтные пакеты. Они продолжают дропаться. Соединение висит.</p>
<p>Поэтому ping работает — ICMP Echo маленький, влезает везде. А большие страницы не открываются — TCP-сегменты данных не влезают, и никто никому об этом не говорит. Всё не так плохо как ты думаешь. Всё намного хуже — потому что диагностировать это без понимания механики почти невозможно.</p>
<h2>Что делает MSS Clamping — и почему это работает</h2>
<p>MSS Clamping — workaround для сломанного PMTUD. Роутер перехватывает SYN-пакет в самом начале TCP-соединения и уменьшает MSS до безопасного значения. До того как пошли данные.</p>
<p>Четыре вещи которые нужно понять:</p>
<ul>
<li>Роутер не фрагментирует пакеты — он <em>предотвращает</em> их появление. Уменьшает MSS на этапе согласования, до передачи данных</li>
<li>Сервер получает урезанный MSS и думает что клиент сам его предложил. Никого не обманывают — просто подсказывают правильное число</li>
<li>Ни клиент, ни <a title="Настройка NTP на MikroTik: клиент и сервер — шпаргалка для ROS 6 и 7" href="https://it-apteka.com/nastrojka-ntp-na-mikrotik-klient-i-server-shpargalka-dlja-ros-6-i-7/" target="_blank" rel="noopener" data-wpil-monitor-id="1433">сервер не знают о Clamping —</a> операция прозрачная</li>
<li>Срабатывает один раз на соединение — в SYN. Данные роутер не трогает</li>
</ul>
<h2>Как это работает на уровне TCP handshake</h2>
<p>Смотри по шагам — что происходит когда на роутере настроен Clamping:</p>
<ol>
<li>Клиент отправляет <strong>SYN</strong> с <code>MSS=1460</code> — стандарт для Ethernet</li>
<li>Роутер перехватывает SYN. Видит: MSS=1460, но туннель позволяет только 1380. Надо исправить</li>
<li>Роутер переписывает MSS прямо в пакете: <code>MSS=1380</code></li>
<li>Сервер получает SYN с <code>MSS=1380</code> — думает что клиент сам так захотел</li>
<li>Сервер отвечает <strong>SYN-ACK</strong> со своим MSS. Роутер при необходимости урезает и его</li>
<li>Клиент отправляет <strong>ACK</strong> — соединение установлено</li>
<li>Все сегменты данных теперь ≤ 1380 байт. В туннель влезают. Интернет работает</li>
</ol>
<p>Почему именно SYN? Потому что MSS передаётся только в SYN и SYN-ACK. После этого оба конца уже договорились — менять нечего.</p>
<h2>Когда без Clamping не обойтись</h2>
<p>Три схемы — наглядно показывают разницу.</p>
<h3>Схема 1: без MSS Clamping — пакет дропается</h3>
<pre class="mermaid">%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Клиент
MSS = 1460"]
B["Туннель / PPPoE
MTU = 1420"]
C["Сервер"]
D["DROP"]
E["ICMP Fragmentation Needed
заблокирован"]
A -->|"пакет 1500 байт"| B
B -.->|"не доходит"| C
B -->|"не влезает"| D
D -.->|"клиент не узнает"| E
E -.-> A
style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style B fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
style C fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#94a3b8
style D fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#b91c1c
style E fill:#f8fafc,stroke:#fbbf24,stroke-width:1px,color:#92400e
</pre>
<h3>Схема 2: с MSS Clamping — пакет проходит</h3>
<pre class="mermaid">%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Клиент
MSS = 1460"]
B["Роутер
Clamping: MSS 1460 → 1380"]
C["Сервер
шлёт сегменты ≤ 1380 байт"]
D["Соединение установлено
все пакеты проходят туннель"]
A -->|"SYN MSS=1460"| B
B -->|"SYN MSS=1380"| C
C -->|"данные ≤ 1420 байт"| B
B -->|"данные ≤ 1420 байт"| A
C --> D
style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style B fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style C fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style D fill:#f0fdf4,stroke:#22c55e,stroke-width:2px,color:#15803d
</pre>
<h3>Схема 3: TCP handshake с подменой MSS</h3>
<pre class="mermaid">%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#f8fafc',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'noteBkgColor': '#fefce8',
'noteTextColor': '#713f12',
'noteBorderColor': '#fbbf24',
'actorBkg': '#f8fafc',
'actorBorder': '#94a3b8',
'actorTextColor': '#1e293b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'sequence': {
'mirrorActors': false,
'messageAlign': 'center',
'actorMargin': 120,
'width': 160,
'noteMargin': 12
}
}}%%
sequenceDiagram
participant C as Клиент
participant R as Роутер
participant S as Сервер
C->>R: SYN — MSS=1460
Note right of R: MSS 1460 → 1380
R->>S: SYN — MSS=1380
S->>R: SYN-ACK — MSS=1460
Note right of R: MSS 1460 → 1380
R->>C: SYN-ACK — MSS=1380
C->>S: ACK
Note over C,S: Соединение установлено — MSS=1380
</pre>
<p>ACK в третьем шаге MSS не содержит — Clamping к нему не применяется. MSS передаётся только в SYN и SYN-ACK. Запомни раз и навсегда.</p>
<p>Список сценариев где Clamping обязателен — не опционален, а обязателен:</p>
<ul>
<li><strong>PPPoE</strong> — самый частый случай. PPPoE съедает 8 байт заголовка, MTU падает с 1500 до 1492. MSS должен быть 1452 или ниже</li>
<li><strong>OpenVPN</strong> — overhead: UDP + OpenVPN-заголовок + шифрование. Типичный MTU внутри туннеля: 1400–1440</li>
<li><strong>WireGuard</strong> — overhead около 60 байт на IPv4. Рекомендованный MTU внутри: 1420</li>
<li><strong>IPsec/GRE</strong> — GRE добавляет 24 байта, ESP ещё больше. MTU зависит от алгоритма шифрования</li>
<li><strong>VXLAN / облачные <a class="wpil_keyword_link" href="https://it-apteka.com/category/networks/" target="_blank" rel="noopener" title="Сети" data-wpil-keyword-link="linked" data-wpil-monitor-id="1448">сети</a></strong> — AWS, GCP, Azure используют VXLAN с overhead 50+ байт. Без Clamping часть трафика в облачных VPC тихо дропается</li>
<li><strong>CGNAT / DS-Lite</strong> — двойной NAT у мобильных операторов и кабельщиков добавляет ещё один слой инкапсуляции</li>
<li><strong>Туннель поверх туннеля</strong> — каждый слой отъедает MTU. Чем глубже в туннели, тем меньше остаётся</li>
</ul>
<h2>MSS Clamping на Linux через iptables</h2>
<p>Самый распространённый вариант. Работает на любом Linux-роутере, VPS-шлюзе, OpenWrt. Одна команда решает проблему.</p>
<h3>Базовая команда</h3>
<pre><code class="language-bash">iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
</code></pre>
<p>Разбор — потому что понимать важнее чем копировать:</p>
<ul>
<li><code>-t mangle</code> — таблица mangle. Не filter (там фильтруют), не nat (там адреса меняют). Mangle — для модификации полей пакета. Именно сюда</li>
<li><code>-A FORWARD</code> — цепочка FORWARD. Для пакетов которые проходят через роутер транзитом. Напишешь INPUT или OUTPUT — не сработает для клиентов за роутером. Классическая ошибка</li>
<li><code>-p tcp --tcp-flags SYN,RST SYN</code> — только TCP с флагом SYN и без RST. Именно первый SYN при установке соединения</li>
<li><code>-j TCPMSS --clamp-mss-to-pmtu</code> — ядро само вычисляет PMTU для исходящего интерфейса и ставит MSS = PMTU — 40. Не угадывай значение — пусть считает сам</li>
</ul>
<h3>Если нужно зафиксировать конкретное значение</h3>
<pre><code class="language-bash"># Вместо автоматического clamp-to-pmtu — конкретное значение
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1360
# Для PPPoE (MTU 1492):
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1452
# Для WireGuard (MTU 1420):
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1380
</code></pre>
<h3>Применить только на конкретном интерфейсе</h3>
<pre><code class="language-bash"># Только для трафика уходящего в туннель WireGuard
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o wg0 -j TCPMSS --clamp-mss-to-pmtu
# Для PPPoE
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o ppp0 -j TCPMSS --clamp-mss-to-pmtu
</code></pre>
<p>Указывать <code>-o ИНТЕРФЕЙС</code> — правильная практика. Меньше побочных эффектов чем вешать правило на весь FORWARD без фильтрации.</p>
<h3>Сохранить после перезагрузки</h3>
<pre><code class="language-bash">apt install iptables-persistent -y
iptables-save > /etc/iptables/rules.v4
</code></pre>
<p>Или добавь в post-up <a class="wpil_keyword_link" href="https://it-apteka.com/category/scripts/" target="_blank" rel="noopener" title="Скрипты" data-wpil-keyword-link="linked" data-wpil-monitor-id="1446">скрипт</a> туннеля — WireGuard и OpenVPN оба это поддерживают.</p>
<h2>MSS Clamping в nftables</h2>
<p>nftables — замена iptables по умолчанию в <a class="wpil_keyword_link" href="https://it-apteka.com/tag/debian/" target="_blank" rel="noopener" title="Debian" data-wpil-keyword-link="linked" data-wpil-monitor-id="1447">Debian</a> 11+, Ubuntu 22.04+. Синтаксис другой, логика та же.</p>
<pre><code class="language-bash"># Создать таблицу и цепочку
nft add table ip mangle
nft add chain ip mangle FORWARD { type filter hook forward priority mangle \; }
# Добавить правило
nft add rule ip mangle FORWARD tcp flags syn tcp option maxseg size set rt mtu
# Проверить
nft list ruleset
</code></pre>
<p>Для постоянного применения — в <code>/etc/nftables.conf</code>:</p>
<pre><code class="language-bash">table ip mangle {
chain FORWARD {
type filter hook forward priority mangle; policy accept;
tcp flags syn tcp option maxseg size set rt mtu
}
}
</code></pre>
<pre><code class="language-bash">systemctl enable nftables
systemctl restart nftables
</code></pre>
<h2>MSS Clamping в MikroTik</h2>
<p>Через CLI RouterOS:</p>
<pre><code class="language-bash">/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn \
action=change-mss new-mss=clamp-to-pmtu \
comment="MSS Clamping"
</code></pre>
<p>Через Winbox: IP → Firewall → Mangle → Add. Chain: forward, Protocol: tcp, TCP Flags: syn, Action: change mss, New MSS: clamp to pmtu. Сохранить.</p>
<p>Для PPPoE с фиксированным значением:</p>
<pre><code class="language-bash">/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn \
action=change-mss new-mss=1452 \
comment="MSS Clamping PPPoE"
</code></pre>
<p>Для WireGuard — указать интерфейс:</p>
<pre><code class="language-bash">/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn \
out-interface=wireguard1 \
action=change-mss new-mss=clamp-to-pmtu \
comment="MSS Clamping WireGuard"
</code></pre>
<p>Проверить что правило работает — счётчики должны расти при активных соединениях:</p>
<pre><code class="language-bash">/ip firewall mangle print stats
</code></pre>
<h2>MSS Clamping в Cisco IOS</h2>
<p>На интерфейсе куда уходит туннель или PPP:</p>
<pre><code class="language-bash">interface GigabitEthernet0/0
ip tcp adjust-mss 1452
! Для туннельного интерфейса:
interface Tunnel0
ip tcp adjust-mss 1360
</code></pre>
<p><code>ip tcp adjust-mss</code> работает на уровне интерфейса — переписывает MSS в SYN-пакетах в обоих направлениях.</p>
<h2>Диагностика: сначала проверь, потом настраивай</h2>
<p>Не ставь Clamping наугад. Сначала убедись что проблема именно в MTU.</p>
<h3>Тест ping с фиксированным размером</h3>
<pre><code class="language-bash"># Linux — не фрагментировать, payload 1472 байта
ping -M do -s 1472 8.8.8.8
# macOS
ping -D -s 1472 8.8.8.8
# Windows
ping -f -l 1472 8.8.8.8
</code></pre>
<p>Почему 1472: это 1500 (Ethernet MTU) минус 28 (20 байт IP + 8 байт ICMP). Пакет проходит — Ethernet MTU в порядке. Не проходит — где-то MTU меньше 1500. Ищи туннель.</p>
<h3>Бинарный поиск правильного MTU</h3>
<pre><code class="language-bash"># Начни с 1472, уменьшай пока не пройдёт
ping -M do -s 1472 8.8.8.8 # MTU 1500
ping -M do -s 1452 8.8.8.8 # MTU 1480 (PPPoE?)
ping -M do -s 1432 8.8.8.8 # MTU 1460
ping -M do -s 1380 8.8.8.8 # MTU 1408 (WireGuard?)
ping -M do -s 1350 8.8.8.8 # MTU 1378
# Автоматически найти максимальный размер:
for size in 1472 1452 1432 1412 1392 1372 1352 1332; do
result=$(ping -M do -s $size -c 1 -W 2 8.8.8.8 2>&1)
if echo "$result" | grep -q "1 received"; then
echo "MTU работает: $((size + 28)) (payload: $size)"
break
else
echo "MTU $((size + 28)) — дроп"
fi
done
</code></pre>
<h3>tcpdump: смотрим MSS в SYN-пакетах</h3>
<pre><code class="language-bash"># Запусти на роутере, потом открой браузер
tcpdump -i eth0 -n 'tcp[tcpflags] & (tcp-syn) != 0' -v | grep "mss"
# Что ищем в выводе:
# "mss 1460" на чистом Ethernet — норма
# "mss 1452" на PPPoE после Clamping — норма
# "mss 1460" на PPPoE — Clamping не работает
</code></pre>
<h3>Проверить что Clamping сработал</h3>
<pre><code class="language-bash"># Счётчики правила — должны расти при открытии новых соединений
iptables -t mangle -L FORWARD -v -n | grep TCPMSS
# Если pkts = 0 — правило не срабатывает
# Причины: не тот интерфейс, не SYN, цепочка FORWARD пустая
</code></pre>
<h2>Из жизни: WireGuard поднялся, сайты не открываются</h2>
<p>Классика жанра. Офис подключён через WireGuard к корпоративному шлюзу. Туннель поднялся, IP получен, ping до внутренних хостов идёт. Открываешь браузер — крутит загрузку, таймаут. Звонок в поддержку: «у нас VPN не работает». По факту — VPN работает. Не работает MSS Clamping.</p>
<p>Что происходит по шагам:</p>
<ul>
<li>Клиент внутри туннеля имеет MTU 1420 — WireGuard overhead ~80 байт от 1500</li>
<li>Клиент шлёт SYN с <code>MSS=1460</code> — не знает про туннель, живёт в своём Ethernet-мире</li>
<li>Сервер отвечает SYN-ACK, соединение устанавливается с MSS=1460</li>
<li>Сервер начинает слать TCP-сегменты по 1460 байт</li>
<li>Пакет с заголовками = 1500 байт. Плюс WireGuard overhead = 1580 байт</li>
<li>В физический MTU 1500 не влезает. DF-бит установлен — пакет дропается</li>
<li>ICMP Fragmentation Needed уходит и теряется где-то в firewall провайдера</li>
<li>Сервер продолжает слать 1460-байтные сегменты. Они продолжают дропаться</li>
<li>Браузер ждёт. Потом таймаут. Звонок в поддержку</li>
</ul>
<p>Почему ping работал? ICMP Echo — маленький пакет, влезает с любым overhead. А TCP-сегменты данных — нет.</p>
<p>Решение <a title="Docker Compose — установка, команды и настройка контейнеров" href="https://it-apteka.com/docker-compose-ustanovka-komandy-i-nastrojka-kontejnerov/" target="_blank" rel="noopener" data-wpil-monitor-id="1436">— одна команда</a> на шлюзе:</p>
<pre><code class="language-bash"># На Linux-шлюзе
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o wg0 -j TCPMSS --clamp-mss-to-pmtu
# Или зафиксировать явно: 1420 - 40 = 1380
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o wg0 -j TCPMSS --set-mss 1380
</code></pre>
<p>После этого все новые TCP-соединения через туннель используют MSS ≤ 1380. Сегменты + заголовки = 1420 байт. WireGuard overhead = ≤ 1500. Всё влезает. Сайты открываются. Звонок в поддержку не состоялся.</p>
<p>Для OpenVPN та же логика: MTU туннеля 1400–1440, MSS = MTU_туннеля — 40, ставишь через <code>--set-mss</code>.</p>
<h2>Типичные ошибки — и как их не сделать</h2>
"Правило
<br />
Поставил без -o или на внутренний интерфейс. Трафик через туннель мимо этого правила. Решение: всегда указывай -o ИНТЕРФЕЙС — исходящий интерфейс туннеля. Если pkts не растут — правило не работает.<br />
<pre><code class="language-bash">iptables -t mangle -L -v | grep TCPMSS
</code></pre>
"Не
<br />
Написал —tcp-flags SYN SYN вместо —tcp-flags SYN,RST SYN. Первый вариант срабатывает на любой пакет с SYN включая SYN+ACK. Нужна маска SYN,RST — проверяем оба флага. Условие SYN — установлен только SYN, RST не установлен. Не перепутай.<br />
"Забыл
<br />
Поставил в INPUT или OUTPUT вместо FORWARD. INPUT — пакеты адресованные роутеру. OUTPUT — пакеты от роутера. FORWARD — транзитные пакеты между интерфейсами. Клиенты за роутером идут через FORWARD. Только туда.<br />
"Заблокировал
<br />
Заблокировал весь ICMP включая Type 3. PMTUD мёртв. Clamping закроет большинство проблем, но не все. Разблокируй хотя бы Type 3 Code 4:<br />
<pre><code class="language-bash">iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
</code></pre>
"MSS
<br />
Поставил —set-mss 576 на всякий случай. Работает, но производительность в разы ниже из-за мелких сегментов. Считай правильно: MTU — 40. WireGuard <a title="MSS на MikroTik: почему половина сайтов не открывается и как это исправить" href="https://it-apteka.com/mss-na-mikrotik-pochemu-polovina-sajtov-ne-otkryvaetsja-i-kak-jeto-ispravit/" target="_blank" rel="noopener" data-wpil-monitor-id="1430">MTU 1420 → MSS</a> 1380. PPPoE MTU 1492 → MSS 1452. Не угадывай — используй clamp-to-pmtu.<br />
<h2>Найти MTU на каждом хопе</h2>
<p>Ping не идёт с 1472, но непонятно где именно режется — используй tracepath.</p>
<pre><code class="language-bash"># Linux — tracepath сам определяет MTU на каждом хопе
tracepath -n 8.8.8.8
# В выводе ищи:
# "pmtu 1492" — ограничение 1492, PPPoE
# "pmtu 1420" — ограничение 1420, туннель
# Альтернатива — traceroute без фрагментации:
traceroute -F -m 30 8.8.8.8
</code></pre>
<pre><code class="language-bash"># Windows
pathping -n 8.8.8.8
# PowerShell
Test-NetConnection -ComputerName 8.8.8.8 -Port 80
</code></pre>
<p>Смотри где трассировка обрывается. Обычно это граница между твоей сетью и провайдером, или вход в туннель.</p>
<h2>Справочник: MSS для популярных конфигураций</h2>
<table>
<thead>
<tr>
<th>Тип подключения</th>
<th>MTU</th>
<th>Overhead</th>
<th>Рекомендованный MSS</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ethernet (стандарт)</td>
<td>1500</td>
<td>0</td>
<td>1460</td>
</tr>
<tr>
<td>PPPoE</td>
<td>1492</td>
<td>8</td>
<td>1452</td>
</tr>
<tr>
<td>WireGuard (IPv4)</td>
<td>1420</td>
<td>60+</td>
<td>1380</td>
</tr>
<tr>
<td>OpenVPN UDP</td>
<td>1400–1440</td>
<td>зависит от конфига</td>
<td>1360–1400</td>
</tr>
<tr>
<td>IPsec ESP (AES)</td>
<td>~1418</td>
<td>~82</td>
<td>1378</td>
</tr>
<tr>
<td>GRE</td>
<td>1476</td>
<td>24</td>
<td>1436</td>
</tr>
<tr>
<td>VXLAN</td>
<td>1450</td>
<td>50</td>
<td>1410</td>
</tr>
<tr>
<td>Туннель в туннеле</td>
<td>~1360</td>
<td>140+</td>
<td>1320 или ниже</td>
</tr>
</tbody>
</table>
<p>Значения приблизительные — overhead зависит от конфигурации. Всегда проверяй реальный MTU через ping-тест, не угадывай по таблице.</p>
<h2>FAQ</h2>
<h3>Что такое MSS в TCP?</h3>
<p>MSS (Maximum Segment Size) — максимальный размер данных в одном TCP-сегменте. Без IP и TCP заголовков — только payload. Передаётся в SYN-пакете при установке соединения. Для стандартного Ethernet: 1460 байт (1500 MTU минус 40 байт заголовков).</p>
<h3>Чем MSS отличается от MTU?</h3>
<p>MTU <a title="DHCP Snooping — что это такое и как защитить сеть от Rogue DHCP сервера" href="https://it-apteka.com/dhcp-snooping-chto-jeto-takoe-i-kak-zashhitit-set-ot-rogue-dhcp-servera-2/" target="_blank" rel="noopener" data-wpil-monitor-id="1437">— ограничение на уровне сети</a>, весь пакет включая заголовки. <a title="Change MSS: что такое TCP MSS, почему не работает HTTPS" href="https://it-apteka.com/change-mss-chto-takoe-tcp-mss-pochemu-ne-rabotaet-https/" target="_blank" rel="noopener" data-wpil-monitor-id="1431">MSS — ограничение на уровне TCP</a>, только данные без заголовков. Связь простая: MTU = MSS + 40. MTU задаётся на интерфейсе, MSS договаривается между двумя хостами при TCP handshake.</p>
<h3>Какое значение MSS ставить?</h3>
<p>Используй <code>--clamp-mss-to-pmtu</code> — ядро само считает по MTU исходящего интерфейса. Если нужно фиксированное: MTU_туннеля − 40. PPPoE (MTU 1492) → MSS 1452. WireGuard (MTU 1420) → MSS 1380. OpenVPN — узнай реальный MTU через ping и вычти 40.</p>
<h3>Зачем Clamping если есть PMTUD?</h3>
<p>PMTUD работает через ICMP Type 3 Code 4 (Fragmentation Needed). Этот тип ICMP блокируется повсеместно — намеренно или по незнанию. Без него PMTUD не работает и отправитель никогда не узнает о проблеме. MSS Clamping решает проблему до начала передачи данных — не полагаясь на ICMP вообще.</p>
<h3>Clamping влияет на производительность?</h3>
<p>Минимально. Правило срабатывает только на SYN — один раз на соединение. Данные не трогает. Единственный риск: если поставить слишком маленький MSS вручную — производительность упадёт из-за мелких сегментов. Используй clamp-to-pmtu и не думай об этом.</p>
<h3>Почему через мобильный работает, а через роутер нет?</h3>
<p>Мобильные операторы делают MSS Clamping на своей стороне — исторически потому что их сети имели нестандартный MTU и они давно это знают. Твой домашний роутер этого не делает пока ты не настроишь. Добавь Clamping — симптом уйдёт.</p>
<h2>Итог</h2>
<p>MSS Clamping — одна из тех настроек которую делаешь один раз и забываешь о целом классе проблем. Ping есть, HTTP нет — сразу MTU. VPN поднялся но ничего не работает — сразу Clamping. Рождённый в туннеле без Clamping стабильной работы не видит.</p>
<p>Команда которую нужно помнить наизусть:</p>
<pre><code class="language-bash">iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
</code></pre>
<p>Всё остальное — вариации. Понял механику <a title="DynDNS: полный гайд по настройке динамического DNS на роутере, Keenetic и MikroTik — бесплатно и без боли" href="https://it-apteka.com/dyndns-polnyj-gajd-po-nastrojke-dinamicheskogo-dns-na-routere-keenetic-i-mikrotik-besplatno-i-bez-boli/" target="_blank" rel="noopener" data-wpil-monitor-id="1434">— не запутаешься ни в MikroTik</a>, ни в Cisco, ни в nftables. Синтаксис разный, смысл один.</p>
"Не
<br />
Включи tcpdump, смотри MSS в SYN-пакетах до и после. Счётчик правила не растёт — правило не срабатывает: проверь интерфейс, цепочку, флаги. MSS изменился но всё равно не работает — проблема в ICMP Black Hole или где-то глубже. Описывай симптомы в комментариях — разберёмся.<br />
Быстрый ответ
Ping идёт, сайты не открываются — проблема в MTU/MSS. Сначала проверь размер пакета, потом ставь Clamping. Дальше — почему это работает и где именно ломается.
Проверка MTU:
ping -M do -s 1472 8.8.8.8
Если пакеты не проходят — включай Clamping. На Linux:
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
На MikroTik:
/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn \
action=change-mss new-mss=clamp-to-pmtu
Симптомы: узнаёшь себя?
Не лезь в теорию, пока не сверился со списком. Если хотя бы один пункт совпадает — ты по адресу.
- Ping на 8.8.8.8 проходит, сайты не открываются. Или открываются частично — шапка есть, контент не грузится
- VPN поднялся, IP получен, handshake прошёл — но браузер крутит загрузку и молчит
- Маленькие страницы работают. Большие — нет. Картинки не грузятся, текст есть
- Через мобильный интернет всё летает. Через домашний роутер — не работает ничего
- После подключения PPPoE большие команды в SSH зависают. Маленькие — ок
- OpenVPN или WireGuard поднялся — но браузер пустой
- HTTPS не работает, HTTP иногда работает. Или наоборот — зависит от фазы луны
Всё это — одна болезнь. MTU mismatch. Лечится одним способом — MSS Clamping. Читай дальше.
MTU и MSS: два числа, один смысл
MTU (Maximum Transmission Unit) — максимальный размер пакета на уровне L2/L3. Ethernet: 1500 байт. PPPoE отъедает 8 байт на свой заголовок — остаётся 1492. WireGuard отъедает ещё больше. Каждый туннель — это минус несколько байт к MTU.
MSS (Maximum Segment Size) — максимальный размер TCP-данных в одном сегменте. Без IP и TCP заголовков. Формула одна на всю жизнь:
MSS = MTU - 20 (IP-заголовок) - 20 (TCP-заголовок)
MSS = MTU - 40
Стандартный Ethernet:
MSS = 1500 - 40 = 1460 байт
PPPoE:
MSS = 1492 - 40 = 1452 байт
WireGuard (типичный):
MSS = 1420 - 40 = 1380 байт
MSS передаётся в SYN-пакете при установке соединения. Клиент говорит серверу: «не шли мне сегменты больше X байт». Сервер отвечает своим значением. Оба берут меньшее — и работают с ним.
Вот тут важно: MSS договаривается один раз, в самом начале. Если где-то на пути есть звено с меньшим MTU — и никто об этом не знает — начинается то, что ты сейчас читаешь эту статью.
Почему PMTUD не работает — и при чём тут ICMP
В теории есть механизм Path MTU Discovery. Должен сам находить минимальный MTU на всём пути. Работает через ICMP: если пакет слишком большой для какого-то звена — роутер отправляет ICMP Fragmentation Needed (Type 3, Code 4) и сообщает максимальный размер.
Звучит хорошо. На практике — ломается постоянно. Причина банальная: кто-то заблокировал ICMP.
Кто-то режет весь ICMP «из соображений безопасности» — и не думает что сломал PMTUD. Кто-то пропускает ping (Echo/Reply) но режет Type 3 Code 4 — именно тот который нужен. Это называется ICMP Black Hole. Дыра, в которую падают твои соединения.
Итог: отправитель шлёт пакет 1500 байт. Роутер на PPPoE-участке видит — не пролезет в 1492. Пытается отправить ICMP Fragmentation Needed. Пакет дропается по дороге. Отправитель ничего не знает. Продолжает слать 1500-байтные пакеты. Они продолжают дропаться. Соединение висит.
Поэтому ping работает — ICMP Echo маленький, влезает везде. А большие страницы не открываются — TCP-сегменты данных не влезают, и никто никому об этом не говорит. Всё не так плохо как ты думаешь. Всё намного хуже — потому что диагностировать это без понимания механики почти невозможно.
Что делает MSS Clamping — и почему это работает
MSS Clamping — workaround для сломанного PMTUD. Роутер перехватывает SYN-пакет в самом начале TCP-соединения и уменьшает MSS до безопасного значения. До того как пошли данные.
Четыре вещи которые нужно понять:
- Роутер не фрагментирует пакеты — он предотвращает их появление. Уменьшает MSS на этапе согласования, до передачи данных
- Сервер получает урезанный MSS и думает что клиент сам его предложил. Никого не обманывают — просто подсказывают правильное число
- Ни клиент, ни сервер не знают о Clamping — операция прозрачная
- Срабатывает один раз на соединение — в SYN. Данные роутер не трогает
Как это работает на уровне TCP handshake
Смотри по шагам — что происходит когда на роутере настроен Clamping:
- Клиент отправляет SYN с
MSS=1460 — стандарт для Ethernet
- Роутер перехватывает SYN. Видит: MSS=1460, но туннель позволяет только 1380. Надо исправить
- Роутер переписывает MSS прямо в пакете:
MSS=1380
- Сервер получает SYN с
MSS=1380 — думает что клиент сам так захотел
- Сервер отвечает SYN-ACK со своим MSS. Роутер при необходимости урезает и его
- Клиент отправляет ACK — соединение установлено
- Все сегменты данных теперь ≤ 1380 байт. В туннель влезают. Интернет работает
Почему именно SYN? Потому что MSS передаётся только в SYN и SYN-ACK. После этого оба конца уже договорились — менять нечего.
Когда без Clamping не обойтись
Три схемы — наглядно показывают разницу.
Схема 1: без MSS Clamping — пакет дропается
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Клиент
MSS = 1460"]
B["Туннель / PPPoE
MTU = 1420"]
C["Сервер"]
D["DROP"]
E["ICMP Fragmentation Needed
заблокирован"]
A -->|"пакет 1500 байт"| B
B -.->|"не доходит"| C
B -->|"не влезает"| D
D -.->|"клиент не узнает"| E
E -.-> A
style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style B fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
style C fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#94a3b8
style D fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#b91c1c
style E fill:#f8fafc,stroke:#fbbf24,stroke-width:1px,color:#92400e
Схема 2: с MSS Clamping — пакет проходит
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Клиент
MSS = 1460"]
B["Роутер
Clamping: MSS 1460 → 1380"]
C["Сервер
шлёт сегменты ≤ 1380 байт"]
D["Соединение установлено
все пакеты проходят туннель"]
A -->|"SYN MSS=1460"| B
B -->|"SYN MSS=1380"| C
C -->|"данные ≤ 1420 байт"| B
B -->|"данные ≤ 1420 байт"| A
C --> D
style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style B fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style C fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style D fill:#f0fdf4,stroke:#22c55e,stroke-width:2px,color:#15803d
Схема 3: TCP handshake с подменой MSS
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#f8fafc',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'noteBkgColor': '#fefce8',
'noteTextColor': '#713f12',
'noteBorderColor': '#fbbf24',
'actorBkg': '#f8fafc',
'actorBorder': '#94a3b8',
'actorTextColor': '#1e293b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'sequence': {
'mirrorActors': false,
'messageAlign': 'center',
'actorMargin': 120,
'width': 160,
'noteMargin': 12
}
}}%%
sequenceDiagram
participant C as Клиент
participant R as Роутер
participant S as Сервер
C->>R: SYN — MSS=1460
Note right of R: MSS 1460 → 1380
R->>S: SYN — MSS=1380
S->>R: SYN-ACK — MSS=1460
Note right of R: MSS 1460 → 1380
R->>C: SYN-ACK — MSS=1380
C->>S: ACK
Note over C,S: Соединение установлено — MSS=1380
ACK в третьем шаге MSS не содержит — Clamping к нему не применяется. MSS передаётся только в SYN и SYN-ACK. Запомни раз и навсегда.
Список сценариев где Clamping обязателен — не опционален, а обязателен:
- PPPoE — самый частый случай. PPPoE съедает 8 байт заголовка, MTU падает с 1500 до 1492. MSS должен быть 1452 или ниже
- OpenVPN — overhead: UDP + OpenVPN-заголовок + шифрование. Типичный MTU внутри туннеля: 1400–1440
- WireGuard — overhead около 60 байт на IPv4. Рекомендованный MTU внутри: 1420
- IPsec/GRE — GRE добавляет 24 байта, ESP ещё больше. MTU зависит от алгоритма шифрования
- VXLAN / облачные сети — AWS, GCP, Azure используют VXLAN с overhead 50+ байт. Без Clamping часть трафика в облачных VPC тихо дропается
- CGNAT / DS-Lite — двойной NAT у мобильных операторов и кабельщиков добавляет ещё один слой инкапсуляции
- Туннель поверх туннеля — каждый слой отъедает MTU. Чем глубже в туннели, тем меньше остаётся
MSS Clamping на Linux через iptables
Самый распространённый вариант. Работает на любом Linux-роутере, VPS-шлюзе, OpenWrt. Одна команда решает проблему.
Базовая команда
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Разбор — потому что понимать важнее чем копировать:
-t mangle — таблица mangle. Не filter (там фильтруют), не nat (там адреса меняют). Mangle — для модификации полей пакета. Именно сюда
-A FORWARD — цепочка FORWARD. Для пакетов которые проходят через роутер транзитом. Напишешь INPUT или OUTPUT — не сработает для клиентов за роутером. Классическая ошибка
-p tcp --tcp-flags SYN,RST SYN — только TCP с флагом SYN и без RST. Именно первый SYN при установке соединения
-j TCPMSS --clamp-mss-to-pmtu — ядро само вычисляет PMTU для исходящего интерфейса и ставит MSS = PMTU — 40. Не угадывай значение — пусть считает сам
Если нужно зафиксировать конкретное значение
# Вместо автоматического clamp-to-pmtu — конкретное значение
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1360
# Для PPPoE (MTU 1492):
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1452
# Для WireGuard (MTU 1420):
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1380
Применить только на конкретном интерфейсе
# Только для трафика уходящего в туннель WireGuard
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o wg0 -j TCPMSS --clamp-mss-to-pmtu
# Для PPPoE
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o ppp0 -j TCPMSS --clamp-mss-to-pmtu
Указывать -o ИНТЕРФЕЙС — правильная практика. Меньше побочных эффектов чем вешать правило на весь FORWARD без фильтрации.
Сохранить после перезагрузки
apt install iptables-persistent -y
iptables-save > /etc/iptables/rules.v4
Или добавь в post-up скрипт туннеля — WireGuard и OpenVPN оба это поддерживают.
MSS Clamping в nftables
nftables — замена iptables по умолчанию в Debian 11+, Ubuntu 22.04+. Синтаксис другой, логика та же.
# Создать таблицу и цепочку
nft add table ip mangle
nft add chain ip mangle FORWARD { type filter hook forward priority mangle \; }
# Добавить правило
nft add rule ip mangle FORWARD tcp flags syn tcp option maxseg size set rt mtu
# Проверить
nft list ruleset
Для постоянного применения — в /etc/nftables.conf:
table ip mangle {
chain FORWARD {
type filter hook forward priority mangle; policy accept;
tcp flags syn tcp option maxseg size set rt mtu
}
}
systemctl enable nftables
systemctl restart nftables
MSS Clamping в MikroTik
Через CLI RouterOS:
/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn \
action=change-mss new-mss=clamp-to-pmtu \
comment="MSS Clamping"
Через Winbox: IP → Firewall → Mangle → Add. Chain: forward, Protocol: tcp, TCP Flags: syn, Action: change mss, New MSS: clamp to pmtu. Сохранить.
Для PPPoE с фиксированным значением:
/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn \
action=change-mss new-mss=1452 \
comment="MSS Clamping PPPoE"
Для WireGuard — указать интерфейс:
/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn \
out-interface=wireguard1 \
action=change-mss new-mss=clamp-to-pmtu \
comment="MSS Clamping WireGuard"
Проверить что правило работает — счётчики должны расти при активных соединениях:
/ip firewall mangle print stats
MSS Clamping в Cisco IOS
На интерфейсе куда уходит туннель или PPP:
interface GigabitEthernet0/0
ip tcp adjust-mss 1452
! Для туннельного интерфейса:
interface Tunnel0
ip tcp adjust-mss 1360
ip tcp adjust-mss работает на уровне интерфейса — переписывает MSS в SYN-пакетах в обоих направлениях.
Диагностика: сначала проверь, потом настраивай
Не ставь Clamping наугад. Сначала убедись что проблема именно в MTU.
Тест ping с фиксированным размером
# Linux — не фрагментировать, payload 1472 байта
ping -M do -s 1472 8.8.8.8
# macOS
ping -D -s 1472 8.8.8.8
# Windows
ping -f -l 1472 8.8.8.8
Почему 1472: это 1500 (Ethernet MTU) минус 28 (20 байт IP + 8 байт ICMP). Пакет проходит — Ethernet MTU в порядке. Не проходит — где-то MTU меньше 1500. Ищи туннель.
Бинарный поиск правильного MTU
# Начни с 1472, уменьшай пока не пройдёт
ping -M do -s 1472 8.8.8.8 # MTU 1500
ping -M do -s 1452 8.8.8.8 # MTU 1480 (PPPoE?)
ping -M do -s 1432 8.8.8.8 # MTU 1460
ping -M do -s 1380 8.8.8.8 # MTU 1408 (WireGuard?)
ping -M do -s 1350 8.8.8.8 # MTU 1378
# Автоматически найти максимальный размер:
for size in 1472 1452 1432 1412 1392 1372 1352 1332; do
result=$(ping -M do -s $size -c 1 -W 2 8.8.8.8 2>&1)
if echo "$result" | grep -q "1 received"; then
echo "MTU работает: $((size + 28)) (payload: $size)"
break
else
echo "MTU $((size + 28)) — дроп"
fi
done
tcpdump: смотрим MSS в SYN-пакетах
# Запусти на роутере, потом открой браузер
tcpdump -i eth0 -n 'tcp[tcpflags] & (tcp-syn) != 0' -v | grep "mss"
# Что ищем в выводе:
# "mss 1460" на чистом Ethernet — норма
# "mss 1452" на PPPoE после Clamping — норма
# "mss 1460" на PPPoE — Clamping не работает
Проверить что Clamping сработал
# Счётчики правила — должны расти при открытии новых соединений
iptables -t mangle -L FORWARD -v -n | grep TCPMSS
# Если pkts = 0 — правило не срабатывает
# Причины: не тот интерфейс, не SYN, цепочка FORWARD пустая
Из жизни: WireGuard поднялся, сайты не открываются
Классика жанра. Офис подключён через WireGuard к корпоративному шлюзу. Туннель поднялся, IP получен, ping до внутренних хостов идёт. Открываешь браузер — крутит загрузку, таймаут. Звонок в поддержку: «у нас VPN не работает». По факту — VPN работает. Не работает MSS Clamping.
Что происходит по шагам:
- Клиент внутри туннеля имеет MTU 1420 — WireGuard overhead ~80 байт от 1500
- Клиент шлёт SYN с
MSS=1460 — не знает про туннель, живёт в своём Ethernet-мире
- Сервер отвечает SYN-ACK, соединение устанавливается с MSS=1460
- Сервер начинает слать TCP-сегменты по 1460 байт
- Пакет с заголовками = 1500 байт. Плюс WireGuard overhead = 1580 байт
- В физический MTU 1500 не влезает. DF-бит установлен — пакет дропается
- ICMP Fragmentation Needed уходит и теряется где-то в firewall провайдера
- Сервер продолжает слать 1460-байтные сегменты. Они продолжают дропаться
- Браузер ждёт. Потом таймаут. Звонок в поддержку
Почему ping работал? ICMP Echo — маленький пакет, влезает с любым overhead. А TCP-сегменты данных — нет.
Решение — одна команда на шлюзе:
# На Linux-шлюзе
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o wg0 -j TCPMSS --clamp-mss-to-pmtu
# Или зафиксировать явно: 1420 - 40 = 1380
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o wg0 -j TCPMSS --set-mss 1380
После этого все новые TCP-соединения через туннель используют MSS ≤ 1380. Сегменты + заголовки = 1420 байт. WireGuard overhead = ≤ 1500. Всё влезает. Сайты открываются. Звонок в поддержку не состоялся.
Для OpenVPN та же логика: MTU туннеля 1400–1440, MSS = MTU_туннеля — 40, ставишь через --set-mss.
Типичные ошибки — и как их не сделать
Правило на не том интерфейсе
Поставил без -o или на внутренний интерфейс. Трафик через туннель мимо этого правила. Решение: всегда указывай -o ИНТЕРФЕЙС — исходящий интерфейс туннеля. Если pkts не растут — правило не работает.
iptables -t mangle -L -v | grep TCPMSS
Не тот флаг SYN — правило ломает соединения
Написал —tcp-flags SYN SYN вместо —tcp-flags SYN,RST SYN. Первый вариант срабатывает на любой пакет с SYN включая SYN+ACK. Нужна маска SYN,RST — проверяем оба флага. Условие SYN — установлен только SYN, RST не установлен. Не перепутай.
Забыл FORWARD — Clamping только для роутера, не для клиентов
Поставил в INPUT или OUTPUT вместо FORWARD. INPUT — пакеты адресованные роутеру. OUTPUT — пакеты от роутера. FORWARD — транзитные пакеты между интерфейсами. Клиенты за роутером идут через FORWARD. Только туда.
Заблокировал ICMP — сломал PMTUD и Clamping не поможет
Заблокировал весь ICMP включая Type 3. PMTUD мёртв. Clamping закроет большинство проблем, но не все. Разблокируй хотя бы Type 3 Code 4:
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
MSS слишком маленький — работает, но медленно
Поставил —set-mss 576 на всякий случай. Работает, но производительность в разы ниже из-за мелких сегментов. Считай правильно: MTU — 40. WireGuard
MTU 1420 → MSS 1380. PPPoE MTU 1492 → MSS 1452. Не угадывай — используй clamp-to-pmtu.
Найти MTU на каждом хопе
Ping не идёт с 1472, но непонятно где именно режется — используй tracepath.
# Linux — tracepath сам определяет MTU на каждом хопе
tracepath -n 8.8.8.8
# В выводе ищи:
# "pmtu 1492" — ограничение 1492, PPPoE
# "pmtu 1420" — ограничение 1420, туннель
# Альтернатива — traceroute без фрагментации:
traceroute -F -m 30 8.8.8.8
# Windows
pathping -n 8.8.8.8
# PowerShell
Test-NetConnection -ComputerName 8.8.8.8 -Port 80
Смотри где трассировка обрывается. Обычно это граница между твоей сетью и провайдером, или вход в туннель.
Справочник: MSS для популярных конфигураций
| Тип подключения |
MTU |
Overhead |
Рекомендованный MSS |
| Ethernet (стандарт) |
1500 |
0 |
1460 |
| PPPoE |
1492 |
8 |
1452 |
| WireGuard (IPv4) |
1420 |
60+ |
1380 |
| OpenVPN UDP |
1400–1440 |
зависит от конфига |
1360–1400 |
| IPsec ESP (AES) |
~1418 |
~82 |
1378 |
| GRE |
1476 |
24 |
1436 |
| VXLAN |
1450 |
50 |
1410 |
| Туннель в туннеле |
~1360 |
140+ |
1320 или ниже |
Значения приблизительные — overhead зависит от конфигурации. Всегда проверяй реальный MTU через ping-тест, не угадывай по таблице.
FAQ
Что такое MSS в TCP?
MSS (Maximum Segment Size) — максимальный размер данных в одном TCP-сегменте. Без IP и TCP заголовков — только payload. Передаётся в SYN-пакете при установке соединения. Для стандартного Ethernet: 1460 байт (1500 MTU минус 40 байт заголовков).
Чем MSS отличается от MTU?
MTU — ограничение на уровне сети, весь пакет включая заголовки. MSS — ограничение на уровне TCP, только данные без заголовков. Связь простая: MTU = MSS + 40. MTU задаётся на интерфейсе, MSS договаривается между двумя хостами при TCP handshake.
Какое значение MSS ставить?
Используй --clamp-mss-to-pmtu — ядро само считает по MTU исходящего интерфейса. Если нужно фиксированное: MTU_туннеля − 40. PPPoE (MTU 1492) → MSS 1452. WireGuard (MTU 1420) → MSS 1380. OpenVPN — узнай реальный MTU через ping и вычти 40.
Зачем Clamping если есть PMTUD?
PMTUD работает через ICMP Type 3 Code 4 (Fragmentation Needed). Этот тип ICMP блокируется повсеместно — намеренно или по незнанию. Без него PMTUD не работает и отправитель никогда не узнает о проблеме. MSS Clamping решает проблему до начала передачи данных — не полагаясь на ICMP вообще.
Clamping влияет на производительность?
Минимально. Правило срабатывает только на SYN — один раз на соединение. Данные не трогает. Единственный риск: если поставить слишком маленький MSS вручную — производительность упадёт из-за мелких сегментов. Используй clamp-to-pmtu и не думай об этом.
Почему через мобильный работает, а через роутер нет?
Мобильные операторы делают MSS Clamping на своей стороне — исторически потому что их сети имели нестандартный MTU и они давно это знают. Твой домашний роутер этого не делает пока ты не настроишь. Добавь Clamping — симптом уйдёт.
Итог
MSS Clamping — одна из тех настроек которую делаешь один раз и забываешь о целом классе проблем. Ping есть, HTTP нет — сразу MTU. VPN поднялся но ничего не работает — сразу Clamping. Рождённый в туннеле без Clamping стабильной работы не видит.
Команда которую нужно помнить наизусть:
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Всё остальное — вариации. Понял механику — не запутаешься ни в MikroTik, ни в Cisco, ни в nftables. Синтаксис разный, смысл один.
Не помогло — пиши
Включи tcpdump, смотри MSS в SYN-пакетах до и после. Счётчик правила не растёт — правило не срабатывает: проверь интерфейс, цепочку, флаги. MSS изменился но всё равно не работает — проблема в ICMP Black Hole или где-то глубже. Описывай симптомы в комментариях — разберёмся.