Che cos’è un tunnel GRE
GRE (Generic Routing Encapsulation, RFC 2784) incapsula un pacchetto IP dentro un altro pacchetto IP. Le due sedi si vedono come se fossero collegate da un cavo punto-punto: ognuna ha un indirizzo sul tunnel e le reti locali vengono instradate attraverso di esso.
GRE è semplice, supportato da quasi tutti i router e dal kernel Linux, e trasporta anche multicast: per questo ci passano bene i protocolli di routing dinamico come OSPF. Ha però un limite importante:
Il traffico nel tunnel viaggia in chiaro su Internet. Per un collegamento tra sedi vero usa GRE solo dentro IPsec: lo spiego nella guida GRE su IPsec tra Cisco e Ubuntu. Questa guida serve a costruire e capire il tunnel, che poi proteggerai.
Lo scenario
Due sedi: la sede A ha un router Cisco, la sede B un server Ubuntu che fa da router per la sua LAN. Entrambi hanno un indirizzo IP pubblico statico.
| Elemento | Sede A (Cisco) | Sede B (Ubuntu) |
|---|---|---|
| IP pubblico | 198.51.100.1 su Gi0/0 | 203.0.113.10 su ens18 |
| LAN | 192.168.10.0/24, gateway .1 su Gi0/1 | 192.168.20.0/24, gateway .1 su ens19 |
| Interfaccia tunnel | Tunnel0 – 10.255.255.1/30 | gre1 – 10.255.255.2/30 |
Gli indirizzi pubblici usati qui sono quelli riservati alla documentazione: sostituiscili con i tuoi. Le due LAN non devono sovrapporsi.
Prima di cominciare: MTU e MSS
GRE aggiunge 24 byte a ogni pacchetto (20 di nuova intestazione IP e 4 di intestazione GRE). Se il collegamento ha MTU 1500, dentro il tunnel restano 1476 byte. Per evitare frammentazione e connessioni TCP che “si bloccano” sulle pagine grandi:
- imposta l’MTU del tunnel a 1476 su entrambi i lati;
- riduci l’MSS TCP a 1436 (1476 − 40 byte di intestazioni IP e TCP).
Se la connessione è PPPoE (MTU 1492) togli altri 8 byte: tunnel a 1468, MSS a 1428.
Configurazione del router Cisco
configure terminal
!
interface Tunnel0
description GRE verso sede B (Ubuntu)
ip address 10.255.255.1 255.255.255.252
ip mtu 1476
ip tcp adjust-mss 1436
tunnel source GigabitEthernet0/0
tunnel destination 203.0.113.10
tunnel mode gre ip
!
ip route 192.168.20.0 255.255.255.0 10.255.255.2
!
end
write memorytunnel mode gre ip è il valore predefinito: lo scrivo per chiarezza. Se sull’interfaccia WAN hai una access list in ingresso, aggiungi una riga che accetti GRE (protocollo IP 47) dal server Ubuntu:
ip access-list extended WAN-IN
permit gre host 203.0.113.10 host 198.51.100.1Se il router fa NAT verso Internet (ip nat inside source … overload), escludi dalla traslazione il traffico tra le due LAN. Di solito basta che la access list usata dal NAT abbia in testa una riga deny ip 192.168.10.0 0.0.0.255 192.168.20.0 0.0.0.255. In realtà, poiché quel traffico esce dall’interfaccia Tunnel0 e non da quella esterna, il NAT spesso non lo tocca comunque: controlla con show ip nat translations.
Configurazione di Ubuntu
1. Abilitare l’instradamento
Ubuntu deve inoltrare i pacchetti tra la LAN e il tunnel:
net.ipv4.ip_forward = 1
# filtro sul percorso inverso in modalità "loose": evita scarti
# sul traffico che entra dal tunnel
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2sudo sysctl --system
2. Creare il tunnel con Netplan
Su Ubuntu Server la rete si configura con Netplan. Crea un file dedicato al tunnel:
network:
version: 2
tunnels:
gre1:
mode: gre
local: 203.0.113.10
remote: 198.51.100.1
addresses:
- 10.255.255.2/30
mtu: 1476
routes:
- to: 192.168.10.0/24
via: 10.255.255.1sudo chmod 600 /etc/netplan/60-gre.yaml
sudo netplan try # applica e torna indietro da solo se perdi la connessione
sudo netplan apply
Gli stessi passaggi a mano (si perdono al riavvio):
sudo ip tunnel add gre1 mode gre local 203.0.113.10 remote 198.51.100.1 ttl 255
sudo ip addr add 10.255.255.2/30 dev gre1
sudo ip link set gre1 mtu 1476 up
sudo ip route add 192.168.10.0/24 via 10.255.255.13. Aprire il firewall a GRE e correggere l’MSS
GRE non usa porte: è il protocollo IP numero 47. Con nftables (il firewall predefinito di Ubuntu, vedi la guida Firewall completo con nftables) aggiungi queste regole alle catene esistenti:
table inet filtro {
chain input {
# ... regole esistenti ...
ip saddr 198.51.100.1 ip protocol gre accept
}
chain forward {
# ... regole esistenti ...
# MSS clamping: adegua l'MSS dei SYN all'MTU del percorso
tcp flags syn tcp option maxseg size set rt mtu
iifname "ens19" oifname "gre1" accept
iifname "gre1" oifname "ens19" accept
}
}Se usi UFW invece di nftables diretto:
sudo ufw allow proto gre from 198.51.100.1
sudo ufw route allow in on ens19 out on gre1
sudo ufw route allow in on gre1 out on ens19
Ricorda che i client della LAN B devono avere il server Ubuntu (192.168.20.1) come gateway, oppure una rotta verso 192.168.10.0/24 che passi da lì.
Verifiche
Sul router Cisco
show interfaces Tunnel0 ! deve risultare "up, line protocol is up"
show ip route 192.168.20.0
ping 10.255.255.2 source Tunnel0
ping 192.168.20.1 source GigabitEthernet0/1
Su Ubuntu
ip -d link show gre1
ip route get 192.168.10.1
ping -c 3 10.255.255.1
ping -c 3 -I 192.168.20.1 192.168.10.1
# vedere i pacchetti GRE sulla WAN
sudo tcpdump -ni ens18 ip proto 47
Per controllare l’MTU senza frammentazione, da un client della LAN B:
ping -M do -s 1448 192.168.10.10 # 1448 + 28 = 1476: deve passare
ping -M do -s 1460 192.168.10.10 # deve fallire: "Frag needed and DF set (mtu = 1476)"
Il secondo comando non deve “appendersi” senza risposta: deve ricevere dal server Ubuntu il messaggio che indica l’MTU del tunnel. Se resta muto, da qualche parte un firewall sta bloccando i messaggi ICMP e la scoperta automatica dell’MTU non funziona.
Keepalive: sapere quando il tunnel è giù
Un’interfaccia GRE resta “up” anche se l’altro capo non risponde. Sul Cisco puoi attivare i keepalive GRE:
interface Tunnel0
keepalive 10 3
Il router invia ogni 10 secondi un pacchetto che l’altro capo deve rimandare indietro; dopo 3 risposte mancate il tunnel va giù e la rotta statica sparisce, così può subentrare una rotta di riserva. Linux rimanda indietro i keepalive solo se l’instradamento è attivo e il filtro rp_filter non li scarta (per questo l’abbiamo messo a 2). Se con il keepalive attivo il tunnel continua a cadere, toglilo e controlla la raggiungibilità con un monitoraggio esterno, oppure usa un protocollo di routing come OSPF, che ha i suoi messaggi di controllo.
Problemi comuni
| Sintomo | Causa probabile | Cosa fare |
|---|---|---|
| Tunnel0 “up/down” sul Cisco | Manca la rotta verso l’IP pubblico remoto, oppure keepalive senza risposta | Verifica show ip route 203.0.113.10; prova senza keepalive |
Nessun pacchetto GRE con tcpdump su Ubuntu | GRE bloccato da un firewall o dal provider | Controlla l’ACL sul Cisco e il firewall di Ubuntu; alcuni modem/router del provider bloccano il protocollo 47 |
| Ping tra i tunnel OK, tra le LAN no | Instradamento disattivato o gateway sbagliato sui client | sysctl net.ipv4.ip_forward deve valere 1; controlla le rotte dei client |
| Ping OK, ma siti e condivisioni si bloccano | MTU/MSS | Verifica ip tcp adjust-mss sul Cisco e la regola MSS su Ubuntu |
| Ubuntu dietro un router con NAT | GRE non attraversa bene il NAT | Inoltra il protocollo 47 verso Ubuntu, oppure usa IPsec con NAT-T o WireGuard |
Il passo successivo
Il tunnel funziona, ma è in chiaro. Il passo successivo è proteggerlo con IPsec: nella guida GRE su IPsec tra Cisco e Ubuntu cifriamo lo stesso tunnel senza cambiare indirizzi e rotte. Per un collegamento IPsec puro, senza GRE, vedi VPN IPsec tra Cisco e Ubuntu con strongSwan.
Prova sempre la configurazione in laboratorio, salva quella attuale prima di modificarla e tieni un accesso di emergenza (console o accesso fuori banda) quando lavori su firewall e VPN da remoto.