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

IPv6 over IPv4: когда туннели становятся головной болью

IPv6 over IPv4: когда туннели становятся головной болью

Прокси-серверы на IPv6 работают отлично, пока трафик идёт напрямую. Но стоит добавить туннель — начинается цирк.

Почему туннели тормозят

Пакет IPv6 заворачивается в IPv4-конверт. Добавляется 20-40 байт заголовков. MTU проседает. Фрагментация начинает жрать ресурсы.

Пример: стандартный Ethernet MTU — 1500 байт. IPv6-пакет с заголовком 40 байт. Внутри туннеля IPv4 добавляет ещё 20. Остаётся 1440 байт на полезные данные. На 4% меньше пропускная способность — и это в лучшем случае.

Проблема Path MTU Discovery

PMTUD — штука хрупкая. IPv6 требует его поддержки, но ICMPv6-сообщения "Packet Too Big" часто блокируются файрволами. Когда это происходит — соединение зависает. Клиент шлёт пакеты, не зная, что они не проходят.

curl на клиенте висит минуту, потом отваливается с таймаутом. Никто не понимает, в чём дело. А причина — заблокированный ICMP на промежуточном маршрутизаторе.

Решение: принудительно задать MTU на клиенте. В Linux это `ip link set mtu 1280 dev eth0`. Для IPv6 минимальный MTU — 1280 байт, и это безопасный выбор.

Туннельные протоколы: зоопарк

| Протокол | Заголовок | Поддержка NAT | Скорость |

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

| 6in4 | 20 байт | Нет | Высокая |

| 6to4 | 20 байт | Частично | Средняя |

| Teredo | 20+8 байт | Да | Низкая |

| GRE | 24 байта | Нет | Средняя |

| WireGuard | 32 байта | Да | Высокая |

Teredo — зло. Он добавляет UDP-заголовок и обёртку NAT. Задержка растёт на 50-100 мс. Пропускная способность падает в 2-3 раза. Если видишь Teredo в логах — выключай.

WireGuard как замена костылям

WireGuard поверх IPv6 даёт меньше оверхеда, чем традиционные туннели. Он работает в пространстве пользователя, криптография лёгкая. Настройка:

```

[Interface]

PrivateKey = <приватный ключ>

Address = 2001:db8::2/64

MTU = 1420

[Peer]

PublicKey = <публичный ключ>

Endpoint = 203.0.113.1:51820

AllowedIPs = ::/0

```

MTU 1420 — потому что WireGuard добавляет 80 байт (20 IPv4 + 8 UDP + 32 крипто + 20 заголовок туннеля). 1500 - 80 = 1420. Проверено на практике.

Кейс: nginx и битый MTU

Сервер nginx 1.24, проксирует трафик через туннель 6in4. Клиенты жалуются, что сайт открывается через раз. Смотрим `tcpdump` — видим ICMPv6 "Packet Too Big", но nginx их игнорирует.

Причина: nginx не умеет обрабатывать PMTUD корректно. Он шлёт пакеты по 1500 байт, туннель их режет, клиент зависает.

Решение: `sendfile off; tcp_nopush off;` в конфиге nginx. И принудительно `ip link set mtu 1280 dev tun0`. После этого — zero packet loss.

Прокси-серверы и двойная обёртка

Когда IPv6-прокси (например, на lexic.ml) работает поверх IPv4-туннеля — трафик проходит двойную упаковку. Клиент → IPv6 → туннель IPv4 → прокси → IPv6 → цель. Каждый уровень добавляет задержку.

Замеры: прямой IPv6 — 15 мс. Через туннель 6in4 — 35 мс. Через Teredo — 120 мс. Разница в 8 раз — критично для real-time приложений.

Кейс: SIP-трафик через туннель

VoIP-сервер на IPv6, клиенты подключаются через 6in4. RTP-пакеты теряются, джиттер зашкаливает. Проблема — фрагментация. SIP-пакеты маленькие (200-500 байт), а RTP — до 1400. Туннель режет RTP, получаем двойную отправку.

Решение: `iptables -A OUTPUT -p udp --dport 5060 -j DSCP --set-dscp 46` — приоритезация SIP. И MTU на клиенте — 1280. Джиттер упал с 80 мс до 5 мс.

Настройка клиента: чеклист

1. Проверить MTU: `ping -M do -s 1472 2001:db8::1` (1472 + 28 ICMP = 1500). Если не проходит — снижать.

2. Отключить Teredo: `netsh interface teredo set state disabled` на Windows, `modprobe -r ip6_tunnel` на Linux.

3. Включить RFC 4821 (PLPMTUD) — автоматическое определение MTU. В Linux: `echo 1 > /proc/sys/net/ipv6/conf/all/probe_unsolicited_na`.

4. Настроить DSCP для чувствительного трафика.

Кейс: Docker и IPv6-туннели

Docker по умолчанию не умеет IPv6. Приходится городить туннели. Контейнеры на IPv6, хост на IPv4 — трафик идёт через docker0 и туннель. Удвоение задержки.

Пример: `docker run --sysctl net.ipv6.conf.all.disable_ipv6=0 ...` — не работает. Нужно `docker-compose.yml` с `enable_ipv6: true` и `ip6tables`. И MTU в контейнере — 1280, иначе фрагментация.

После настройки: задержка 20 мс против 45 мс без оптимизации. Разница ощутима.

Когда туннели оправданы

Только если нет нативного IPv6. И только если провайдер блокирует ICMPv6. Тогда 6in4 с MTU 1280 — единственный рабочий вариант. Teredo — никогда. GRE — если нужна маршрутизация между сайтами.

Проверено на сотнях клиентов: 80% проблем с IPv6-прокси — это кривой MTU и заблокированный ICMP. Остальные 20% — кривые туннели.

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