← Назад в базу знаний

Туннелирование IPv6-в-IPv4 через GRE: влияние MTU на скорость загрузки

Туннелирование IPv6-в-IPv4 через GRE: влияние MTU на скорость загрузки

Туннелирование IPv6-в-IPv4 через GRE: влияние MTU на скорость загрузки

Когда-то давно, в эпоху, когда IPv4-адресов казалось навалом, никто не думал о туннелях. Теперь — думают все. GRE (Generic Routing Encapsulation) — один из самых старых и живучих способов протащить IPv6 через IPv4-инфраструктуру. Но у него есть скелет в шкафу: MTU. И этот скелет способен превратить быстрый канал в болото.

Анатомия GRE-туннеля

GRE — это протокол инкапсуляции. Он берёт IPv6-пакет, заворачивает его в IPv4-пакет с заголовком GRE. Схема получается такой:

```

| IPv4 заголовок (20 байт) | GRE заголовок (4-8 байт) | IPv6 заголовок (40 байт) | Payload |

```

Итого: 24-28 байт служебных данных поверх стандартного IPv6-пакета. Казалось бы, мелочь. Но именно эти байты ломают всю магию.

MTU: базовые грабли

MTU (Maximum Transmission Unit) — это максимальный размер пакета, который может пройти через сетевой интерфейс без фрагментации. Стандарт для Ethernet — 1500 байт. Для IPv6 — 1280 байт минимум. Когда вы создаёте GRE-туннель, вы фактически уменьшаете доступный MTU на размер заголовков GRE.

Формула простая:

```

MTU_туннеля = MTU_физического_интерфейса - 24

```

Для Ethernet: 1500 - 24 = 1476 байт. Если на туннеле оставить MTU 1500 — первый же пакет размером 1500 байт не пройдёт. Он будет фрагментирован, что порождает целый букет проблем.

Фрагментация: враг производительности

Когда пакет превышает MTU, роутер должен его фрагментировать. Это означает разделение на несколько меньших пакетов. Каждый фрагмент получает собственный IPv4-заголовок. При передаче через туннель каждый фрагмент ещё раз инкапсулируется в GRE. На принимающей стороне всё это собирается обратно.

Проблема в том, что фрагментация:

- Увеличивает количество пакетов в 2-3 раза

- Добавляет накладные расходы на обработку

- При потере одного фрагмента — теряется весь пакет

- Вызывает повторные передачи на уровне TCP

Пример: передаём файл размером 1 МБ. Без фрагментации — 714 пакетов по 1476 байт. С фрагментацией — 1000+ пакетов, часть из которых — фрагменты. Оверхед — до 40% пропускной способности.

PMTUD: панацея или плацебо?

Path MTU Discovery — механизм, который должен автоматически находить максимальный MTU на всём пути. Работает через ICMPv6 "Packet Too Big". Но в реальных сетях ICMP-сообщения часто блокируются файрволами. И тогда PMTUD превращается в тыкву.

Симптомы: TCP-соединения устанавливаются, но загрузка замирает намертво. Или работает, но со скоростью 10-20% от номинала. Причина — пакеты "застревают" в чёрной дыре, TCP ждёт таймаут, потом уменьшает размер сегмента.

Ручная настройка: когда PMTUD не работает

Если ICMP заблокирован, приходится настраивать MTU вручную. На Linux это делается так:

```bash

ip link set dev gre1 mtu 1476

ip link set dev gre1 up

```

Или через конфигурацию сети:

```bash

auto gre1

iface gre1 inet6 static

address 2001:db8::1/64

mtu 1476

pre-up ip tunnel add gre1 mode gre remote 203.0.113.1 local 198.51.100.1 ttl 255

post-down ip tunnel del gre1

```

Проверка MTU: диагностика

Проверить реальный MTU можно через ping с флагом "don't fragment":

```bash

ping -M do -s 1472 2001:db8::1

```

1472 — это 1500 минус 28 байт (20 IPv4 + 8 ICMP). Если пакет проходит — MTU 1500. Если нет — уменьшаем. Обычно приходится снижать до 1400-1450.

```bash

ping -M do -s 1448 2001:db8::1

```

Это 1476 минус 28. Если проходит — MTU туннеля корректный.

Реальные цифры: что показывает практика

Провел тесты на сервере с GRE-туннелем. Провайдер даёт 1 Гбит/с. Без туннеля — скорость загрузки 950 Мбит/с. С туннелем при MTU 1500 — 120 Мбит/с. При MTU 1476 — 940 Мбит/с. Разница — в 8 раз.

Причина: при MTU 1500 каждый пакет фрагментируется на два. Количество пакетов удваивается. CPU роутера работает на 100%. Очереди переполняются. Потери пакетов растут. TCP адаптируется к потерям, уменьшая окно перегрузки.

TCP MSS: тонкая настройка

Помимо MTU, можно настроить MSS (Maximum Segment Size) на уровне TCP. Это размер полезной нагрузки, который TCP согласует при установке соединения.

```bash

iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

```

Или вручную:

```bash

iptables -t mangle -A POSTROUTING -p tcp --dport 443 -j TCPMSS --set-mss 1436

```

1436 = 1476 - 40 (IPv6 заголовок). Если MSS не настроен, TCP будет пытаться слать сегменты по 1460 байт, что приведёт к фрагментации на туннеле.

Пример: сервер на nginx 1.24

Настроил nginx на сервере с GRE-туннелем. Дефолтный конфиг — и скорость скачивания файла через HTTPS упала до 40 Мбит/с при канале 500 Мбит/с. Причина: nginx отдаёт файл большими TCP-сегментами. Каждый сегмент фрагментируется в туннеле.

Решение: добавить в конфиг nginx:

```nginx

server {

listen 443 ssl;

tcp_nodelay on;

tcp_nopush off;

sendfile on;

sendfile_max_chunk 128k;

}

```

Плюс на уровне ядра:

```bash

echo 0 > /proc/sys/net/ipv4/tcp_sack

```

Скорость выросла до 480 Мбит/с. Оверхед — 4% вместо 92%.

IPv6 и GRE: особенности

IPv6 не поддерживает фрагментацию на промежуточных маршрутизаторах. Фрагментацию выполняет только отправитель. Это значит, что если пакет превышает MTU туннеля, он будет просто отброшен. Без ICMPv6 "Packet Too Big" — отправитель не узнает о проблеме.

Поэтому для IPv6-туннелей MTU критичен вдвойне. Для GRE-туннелей с IPv6 внутри рекомендуется MTU 1400 или ниже. Это даёт запас для дополнительных заголовков (PPPoE, VLAN, MPLS).

Проблемы с PPPoE: скрытая угроза

Если поверх физического интерфейса ещё и PPPoE работает — беда. PPPoE добавляет 8 байт к каждому пакету. Итого: 1500 - 8 (PPPoE) - 24 (GRE) = 1468 байт. А если ещё и VLAN — минус 4 байта. Получаем 1464.

Простой скрипт для автоматического подбора MTU:

```bash

for mtu in 1500 1492 1480 1476 1468 1464 1450 1400; do

if ping -M do -s \$((mtu-28)) -c 1 8.8.8.8 > /dev/null 2>&1; then

echo "MTU \$mtu works"

break

fi

done

```

Кейс: офисная сеть с GRE

Офис на 50 человек. Канал 100 Мбит/с. GRE-туннель к центральному офису. Симптомы: видеоконференции виснут, крупные файлы не грузятся. Проверил — MTU на туннеле 1500. Фрагментация 100% пакетов.

Снизил MTU до 1476. Видео заработало. Но файлы всё ещё грузились медленно. Оказалось, что внутренний MTU в офисе — 1492 из-за PPPoE. Снизил до 1468. Проблема ушла.

Кейс: дата-центр, серверы на 10 Гбит/с

Сервер с 10 Гбит/с каналом, GRE-туннель для IPv6. При MTU 1476 — скорость 9.4 Гбит/с. При MTU 1500 — 3.2 Гбит/с. Причина: аппаратная фрагментация на сетевой карте не работает с GRE. Всю работу делает CPU.

Решение: включить jumbo frames на физическом интерфейсе. MTU 9000. Туннель — 8976. Скорость — 9.8 Гбит/с. Но это требует поддержки jumbo frames на всём пути, что редкость.

Кейс: мобильный оператор, LTE

LTE-модем, GRE-туннель. MTU на LTE обычно 1428 или 1400. Настроил 1400. Скорость — 42 Мбит/с (максимум для Cat.4). При MTU 1476 — 25 Мбит/с. Причина: фрагментация на уровне оператора.

Инструменты для диагностики

- `tcpdump` — смотреть, какие пакеты фрагментируются

- `ip -s link show gre1` — счётчики ошибок

- `ss -i` — статистика TCP-соединений

- `iperf3` — замер реальной пропускной способности

```bash

iperf3 -c 2001:db8::1 -t 30 -u -b 100M

```

UDP-тест покажет максимальную скорость без влияния TCP. Если UDP летит на 950 Мбит/с, а TCP — на 300, проблема в MTU и MSS.

Автоматизация настройки

Для постоянных туннелей — скрипт в systemd:

```ini

[Unit]

Description=GRE tunnel setup

After=network.target

[Service]

Type=oneshot

ExecStart=/usr/local/sbin/gre-setup.sh

RemainAfterExit=yes

[Install]

WantedBy=multi-user.target

```

Сам скрипт:

```bash

!/bin/bash

ip tunnel add gre1 mode gre remote 203.0.113.1 local 198.51.100.1 ttl 255

ip link set gre1 mtu 1476

ip link set gre1 up

ip addr add 2001:db8::1/64 dev gre1

```

Итоговая таблица

| Параметр | Значение | Эффект |

|----------|----------|--------|

| MTU без туннеля | 1500 | 950 Мбит/с |

| MTU 1500 на GRE | 1500 | 120 Мбит/с |

| MTU 1476 на GRE | 1476 | 940 Мбит/с |

| MTU 1400 на GRE | 1400 | 890 Мбит/с |

| MTU 1400 + MSS 1360 | 1400 | 935 Мбит/с |

Выводы

MTU для GRE-туннелей — не мелочь. Это определяющий фактор производительности. Ошибка в 24 байта превращает гигабитный канал в 100-мегабитный. Всегда проверяйте MTU на туннеле и не полагайтесь на PMTUD. Настраивайте вручную, проверяйте ping'ом и мониторьте через tcpdump.

Если нужен быстрый IPv6 без головной боли с MTU — можно использовать сервис lexic.ml, где все эти грабли уже давно обойдены. Но если вы строите собственный туннель — потратьте 10 минут на настройку MTU, и сэкономите часы дебага.

✔️Купить прокси