GRE e unul dintre cele mai vechi protocoale de tunelare încă folosite zilnic în producție și refuză să moară dintr-un motiv bun: e simplu, e peste tot și transportă orice. E și sursa unei clase foarte specifice de outage — cea în care ping-ul merge, cererile mici merg, iar orice implică un pachet de dimensiune completă rămâne agățat la nesfârșit.
Acest articol e lista de verificare pe care ne-ar fi plăcut să ne-o dea cineva prima dată când am ridicat un tunel GRE care „mergea” și apoi, în liniște, nu mai mergea.
Unde GRE își merită încă locul
GRE (Generic Routing Encapsulation, protocolul 47) învelește un pachet într-un header IP nou plus un header GRE mic și îl trimite punct-la-punct. Fără criptare, fără autentificare, fără stare de sesiune. Simplitatea asta e exact motivul pentru care supraviețuiește:
- Căi de retur pentru scrubbing DDoS. Acesta e cazul de utilizare modern canonic. Un furnizor de scrubbing îți anunță prefixul, absoarbe atacul și îți returnează traficul curat — printr-un tunel GRE, pentru că adevărata ta cale de upstream e anunțată în altă parte. Am acoperit arhitectura din jur în articolul nostru despre mitigarea DDoS.
- Conectarea insulelor de rețea. Două site-uri, fără L2 comun, fără buget de MPLS — un tunel GRE peste internetul public îți dă o interfață peste care poți ruta.
- Transportul protocoalelor de rutare acolo unde politica le blochează. Adiacențele OSPF și sesiunile BGP rulează fericite într-un tunel, peste un underlay care nu ți-ar forwarda niciodată hello-urile multicast și nici nu ți-ar accepta prefixele nativ.
Aritmetica MTU pe care trebuie să o faci
Aici merg prost majoritatea deployment-urilor GRE, așa că hai să facem calculul explicit.
O cale Ethernet standard îți dă un MTU IP de 1500 de octeți. Încapsularea GRE adaugă:
20 bytes outer IPv4 header
+ 4 bytes GRE header
= 24 bytes overhead
Deci cel mai mare pachet interior care încape fără fragmentare este:
1500 − 24 = 1476 bytes → your tunnel MTU
Pentru TCP, scazi headerele IP și TCP interioare ca să obții MSS-ul:
1476 − 20 (IP) − 20 (TCP) = 1436 bytes → your TCP MSS
Două precizări care schimbă aceste cifre: dacă folosești o cheie GRE (obișnuit când multiplexezi tuneluri între aceleași capete), adaugă încă 4 octeți de overhead — 1472/1432. Dacă transportul exterior e IPv6, headerul exterior are 40 de octeți, deci overhead-ul e 44 și cifrele scad la 1456/1416.
Ridicarea tunelului pe Linux cu MTU-ul setat corect de la început:
ip tunnel add gre1 mode gre local 198.51.100.2 remote 203.0.113.1 ttl 255
ip link set gre1 up mtu 1476
ip addr add 10.0.0.1/30 dev gre1
Dacă lași MTU-ul la ce alege kernelul și acesta nu se potrivește cu capătul celălalt, ai construit o fabrică de pachete fragmentate.
Blackhole-uri PMTUD: de ce „aproape” funcționează
În teorie nu trebuie să-ți pese de nimic din toate astea, pentru că Path MTU Discovery se ocupă: un host trimite un pachet de dimensiune completă cu DF setat, routerul din fața tunelului nu-l poate încadra și răspunde cu ICMP Fragmentation Needed, spunându-i expeditorului să folosească 1476. Expeditorul își micșorează pachetele. Toată lumea e fericită.
În practică, mesajul ICMP trebuie să călătorească înapoi prin internet până la expeditor — și undeva pe calea aceea există un firewall configurat de cineva care a citit că „ICMP e un risc de securitate” și l-a blocat în întregime. Acum expeditorul nu află niciodată despre MTU-ul mai mic. Continuă să retransmită pachete de dimensiune completă cu DF setat, routerul tunelului continuă să le arunce în tăcere, iar conexiunea rămâne agățată.
Simptomul e inconfundabil odată ce l-ai văzut: ping-ul merge, handshake-ul TCP merge, transferurile mici merg, iar primul pachet de dimensiune completă — un certificat TLS, un body de răspuns HTTP, un scp al oricărui lucru real — se blochează la nesfârșit. Pachetele de handshake sunt mici; pachetele de date nu sunt.
Nu poți repara filtrarea ICMP a tuturor celorlalți. Așa că nu depinde de ea.
MSS clamping: fix-ul care chiar ține
Pentru că TCP își negociază dimensiunea maximă a segmentului în pachetele SYN, iar acele pachete SYN trec prin routerul tău, poți rescrie MSS-ul anunțat din mers, astfel încât niciunul dintre capete să nu încerce vreodată un pachet care nu încape. Asta e MSS clamping și nu e opțional pentru un tunel GRE de producție — face parte din ridicarea tunelului.
Cu nftables:
nft add rule inet filter forward oifname "gre1" \
tcp flags syn tcp option maxseg size set rt mtu
rt mtu limitează automat la MTU-ul rutei, ceea ce supraviețuiește unei schimbări ulterioare a MTU-ului tunelului. Echivalentul iptables:
iptables -t mangle -A FORWARD -o gre1 -p tcp \
--tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Fă clamping în ambele direcții (traficul care intră în tunel și traficul care iese din el) și ține minte că ajută doar TCP. Protocoalele bazate pe UDP — QUIC, VPN-uri, DNS cu răspunsuri mari — depind în continuare de o configurare corectă a MTU-ului și de un PMTUD funcțional, ceea ce e încă un motiv să setezi MTU-ul tunelului onest în loc să speri.
Keepalive-uri: Linux nu le are
GRE-ul din lumea Cisco are un mecanism de keepalive (un pachet auto-adresat inteligent, pe care capătul celălalt îl trimite înapoi). GRE-ul din Linux nu-l implementează. Un tunel GRE pe Linux e stateless: interfața rămâne „up” chiar dacă endpoint-ul de la distanță e oprit de o săptămână, iar rutele tale peste el continuă să trimită traficul în gaură neagră în consecință.
Deci starea de viață trebuie să vină de la un strat de deasupra tunelului:
- rulează un protocol de rutare peste el (hello-urile OSPF sau BGP servesc și ca verificare de liveness),
- adaugă BFD dacă stiva ta de rutare îl suportă, sau
- cel puțin, un monitor bazat pe ping care retrage ruta când partea cealaltă nu mai răspunde.
Rutele statice îndreptate într-un tunel GRE nemonitorizat sunt un eșec silențios care își așteaptă momentul.
Când să nu folosești GRE
- Când traficul are nevoie de confidențialitate. GRE e în clar — fiecare octet de payload e lizibil pe fir. Fie rulezi IPsec peste tunel, fie sari peste stratificare și folosești WireGuard, care îți dă criptare, keepalive-uri și NAT traversal într-o singură unealtă. Pentru link-uri site-to-site noi, fără constrângeri legacy, WireGuard e de obicei alegerea implicită mai bună.
- Când ai nevoie de L2. GRE transportă L3. Dacă trebuie să întinzi un domeniu de broadcast, asta e treaba VXLAN (deși gândește-te bine înainte să întinzi L2 în general).
- Când există NAT pe cale. GRE e protocolul IP 47 — fără porturi — și majoritatea dispozitivelor NAT îl gestionează undeva între prost și deloc.
Lecții
- Fă aritmetica MTU înainte ca tunelul să transporte trafic — MTU 1476 și MSS 1436 pe IPv4, mai puțin cu chei sau cu headere exterioare IPv6.
- Nu depinde niciodată doar de PMTUD — cineva de pe cale aruncă ICMP-ul de care ai nevoie.
- Fă MSS clamping pe routerul tunelului, în ambele direcții — face parte din configurația tunelului, nu e o optimizare.
- Monitorizează liveness-ul deasupra tunelului — GRE-ul din Linux va rămâne fericit „up” către un endpoint mort.
- Alege WireGuard când ai nevoie de confidențialitate, VXLAN când ai nevoie de L2 — nișa GRE e simplitatea L3 în clar.
Tunelurile GRE fac parte din felul în care traficul curățat ajunge înapoi în rețele ca a noastră — dacă te lupți cu tuneluri, mistere de MTU sau cu networking-ul de edge în general, noi facem asta zi de zi.
Ai ceva asemănător de construit?
Proiectăm, construim și operăm software la comandă — platforme web, unelte interne, software care comunică cu hardware-ul — deseori cu agenți AI sub review uman. O singură echipă, de la specificație la producție și mai departe, oriunde ai fi.


