Зачем GRE и IPIP
Иногда нужен point-to-point туннель между двумя точками через обычный интернет: site-to-site VPN, точка-в-точку BGP-сессия, multicast-через-unicast (IGMP внутри туннеля). [[vxlan-overlay|VXLAN]] для этого слишком тяжёлый (ему нужен L2-сегмент); IPsec - готовая VPN но сложная.
GRE (Generic Routing Encapsulation, RFC 2784) - простейший universal туннель. Берёт IP-пакет (или Ethernet, IPv6, MPLS - что угодно), оборачивает в IP-пакет с GRE-header'ом, шлёт на другую сторону. Там распаковывается.
IPIP - частный случай: только IPv4-в-IPv4, без GRE-header'а. Overhead на пакет: IPIP добавляет только 20-байтный outer IP; GRE - 20 (IP) + 4 (минимальный GRE-header) = 24 байта.
Структура GRE-пакета
┌──────────────────────────────────────┐
│ outer IPv4 header (20 байт) │ proto = 47 (GRE)
├──────────────────────────────────────┤
│ GRE header (4-16 байт) │ optional checksum, key, sequence
├──────────────────────────────────────┤
│ payload protocol (что обернули) │ IPv4 / IPv6 / Ethernet / MPLS
├──────────────────────────────────────┤
│ payload data │
└──────────────────────────────────────┘
GRE header базовый:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|C| |K|S| Reserved0 | Ver | Protocol Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- C - присутствует ли checksum
- K - GRE Key (4 байта, после header'а если K=1)
- S - sequence number
- Protocol Type - что внутри (0x0800 = IPv4, 0x86DD = IPv6, 0x6558 = Ethernet)
Минимум - 4 байта. С checksum + key + sequence - до 16 байт.
IP outer header: protocol number = 47 (GRE) или 4 (IPIP).
GRE Key - multiplexing
Если между двумя хостами нужно несколько раздельных GRE-туннелей (один для prod-сети, другой для dev) - помогает GRE Key, 32-битный идентификатор туннеля. На приёме разбираешь по ключу.
Key - не для безопасности (передаётся в clear), просто способ логически разделить туннели в одной IP-паре.
Linux GRE
Создать GRE-туннель IPv4-в-IPv4:
ip tunnel add gre1 mode gre \
local 203.0.113.1 \
remote 198.51.100.1 \
ttl 64 \
key 1234
ip link set gre1 up
ip addr add 10.99.99.1/30 dev gre1
ip route add 192.168.20.0/24 dev gre1
IPIP:
ip tunnel add ipip1 mode ipip local 203.0.113.1 remote 198.51.100.1
ip link set ipip1 up
ip addr add 10.99.99.1/30 dev ipip1
Тип туннеля выбирается через mode:
| Mode | Encapsulation | Когда |
|---|---|---|
ipip | IPv4 в IPv4 | минимум overhead, только v4 |
gre | IPv4 в IPv4 (с GRE) | + key, + multicast support |
gretap | Ethernet в IP (через GRE) | L2 туннель (как VXLAN, но GRE) |
sit | IPv6 в IPv4 | переход на IPv6 поверх IPv4-сети |
ip6gre | IPv4/v6 в IPv6 | то же поверх IPv6 |
ip6tnl | IPv6 в IPv6 | плотный v6-туннель |
mGRE - multipoint GRE
Обычный GRE - точка-точка. Если у hub-and-spoke топологии 50 spoke'ов, на hub'е надо 50 туннелей. mGRE (multipoint GRE) решает: один интерфейс - множество удалённых endpoint'ов.
Cisco DMVPN использует mGRE + NHRP (Next Hop Resolution Protocol)
для поиска remote IP. На Linux mGRE поддерживается через gre
без remote параметра:
ip tunnel add mgre1 mode gre local 203.0.113.1 ttl 64 key 100
Но без NHRP нужно вручную добавлять neighbor:
ip neigh add 10.99.99.2 lladdr 198.51.100.2 dev mgre1
ip neigh add 10.99.99.3 lladdr 198.51.100.3 dev mgre1
GRE vs VXLAN vs IPsec
| Свойство | GRE | VXLAN | IPsec |
|---|---|---|---|
| OSI | L3 (или L2 в gretap) | L2 over L3 | L3 |
| Header overhead | 24 байта | 50 байт | 50-80 байт |
| Шифрование | нет | нет | да (AES-GCM) |
| Multitenant | через GRE key (32 бит) | VNI 24 бит | через SA |
| Multicast inside | да | да (через multicast/HER) | сложно |
| Через NAT | плохо (нет L4-портов) | хорошо (UDP) | требует NAT-T |
| Underlay | IP unicast | IP unicast | IP unicast |
| Use case | site-to-site VPN, lab | DC overlay, k8s CNI | secure VPN |
Главное: GRE не шифрует. Для безопасности обычно делают GRE-over-IPsec - сначала GRE-туннель (для multicast/L3-routing features), потом весь GRE-трафик в IPsec transport-mode для encryption.
NAT и GRE - почему не дружат
GRE - L3-протокол (proto 47), у него нет L4-портов. NAT-роутер делает NAPT по портам, GRE подменять не умеет.
Решения:
- PPTP-style ALG в роутере (старо, often broken)
- GRE через IPsec NAT-T (UDP encapsulation)
- VXLAN вместо GRE - UDP-based, NAT-friendly out of the box
В современной инфраструктуре GRE стараются не пускать через NAT - либо public IP с обеих сторон, либо переходи на VXLAN.
MTU - неизбежная боль
Total overhead GRE поверх IPv4 = 20 (outer IP) + 4 (минимальный GRE-header) = 24 байта. С key - 28, с checksum+key+sequence - до 36. Если underlay MTU 1500 - tunnel MTU = 1476 (без опций).
ip link set gre1 mtu 1476
Если полезная нагрузка не лезет в 1476 - либо фрагментация (плохо), либо PMTUD (часто blackhole). См. [[mtu-and-pmtud|MTU и PMTUD]]. MSS clamping в iptables - стандартный фикс на gre0:
iptables -t mangle -A FORWARD -o gre1 -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Где это применяется
- Site-to-site VPN без шифрования (внутренние линки между офисами через MPLS-провайдера, который уже secure)
- OSPF/BGP над интернетом - GRE-туннель + IGP внутри (multicast OSPF Hello требует подходящий link)
- IPv6 поверх IPv4 интернета -
sitтуннели (исторически 6to4) - Cisco DMVPN - hub-and-spoke с mGRE + NHRP + IPsec
- Calico CNI в IPIP-mode - когда underlay не BGP-friendly (см. [[cni-plugins|CNI plugins]])
Когда что-то пошло не так
- Туннель не работает после старта - проверь IP-связность
underlay (
ping <remote>), потом firewall (proto 47 для GRE, proto 4 для IPIP). На AWS/GCP proto 47 часто блокирован - используй VXLAN. - Ассиметричный traffic - туннель up в одну сторону, down в другую. Проверь, что на обеих сторонах настроен match local/remote.
- MTU blackhole - те же симптомы что у [[mtu-and-pmtud|VXLAN]].
ip link set gre1 mtu 1400+ MSS clamping. ip tunnel showпустой, ноip linkпоказывает туннель - intermixing старогоip tunnelAPI и нового черезip link. Используй один из них (ip link add ... type gre- современный).- GRE через NAT не работает - смотри секцию выше, GRE и NAT не дружат.
- Multicast inside tunnel не идёт - убедись
ttlподнят на обеих сторонах, IGMP snooping не режет.
Полезные настройки sysctl
net.ipv4.conf.all.rp_filter=0для GRE-интерфейса (асимметричный routing нормален)net.ipv4.ip_forward=1- туннель почти всегда на роутереnet.ipv4.conf.gre1.accept_redirects=0- параноидально