Vai al contenuto
GLGiuseppe Lanza Scrivimi

GRE su IPsec tra Cisco e Ubuntu

Proteggere con IPsec IKEv2 in modalità trasporto il tunnel GRE tra un router Cisco e Ubuntu con strongSwan: configurazione dei due lati, calcolo di MTU e MSS, OSPF opzionale, verifiche e problemi comuni.

Sistemi: Cisco IOS XE 17 · Ubuntu 24.04 LTS · strongSwan 5.9Livello: AvanzatoTempo: 60 minutiAggiornata: novembre 2026

Perché GRE su IPsec

Nella guida Tunnel GRE tra un router Cisco e Ubuntu Linux abbiamo costruito un tunnel GRE funzionante, ma in chiaro. Qui lo proteggiamo con IPsec senza cambiare indirizzi, interfacce e rotte.

Perché non usare direttamente una VPN IPsec? Perché GRE porta vantaggi che IPsec da solo non offre:

  • Multicast: nel tunnel passano i protocolli di routing dinamico come OSPF ed EIGRP.
  • Più reti senza toccare le SA: IPsec protegge un solo flusso, il GRE tra i due IP pubblici. Le reti che ci passano dentro le decide il routing.
  • Interoperabilità: ogni apparato capisce GRE, e la parte IPsec si riduce a una sola Child SA semplice.

Oggi una VTI (vedi VPN IPsec tra Cisco e Ubuntu con strongSwan) copre molti di questi casi con meno overhead. GRE su IPsec resta la scelta giusta se ti serve multicast, se hai già un’infrastruttura GRE o se l’altro capo non supporta interfacce IPsec.

Lo scenario

Gli indirizzi sono quelli della guida GRE. Il tunnel GRE resta com’è; IPsec, in modalità trasporto, cifra i pacchetti GRE che viaggiano tra 198.51.100.1 e 203.0.113.10.

LAN sede A 192.168.10.0/24 Router Cisco Gi0/0 198.51.100.1 Internet UDP 500/4500 · ESP Ubuntu 24.04 ens18 203.0.113.10 LAN sede B 192.168.20.0/24 IPsec ESP, modalità trasporto · IKEv2 Tunnel GRE · 10.255.255.0/30 Tunnel0 .1 gre1 .2 Gi0/1 .1 (gateway) ens19 .1 (gateway)
Il tunnel GRE (tratteggiato) viaggia dentro la protezione IPsec (linea continua): su Internet si vedono solo pacchetti ESP.
ElementoSede A (Cisco)Sede B (Ubuntu)
IP pubblico e identità IKE198.51.100.1 su Gi0/0203.0.113.10 su ens18
LAN192.168.10.0/24, gateway .1 su Gi0/1192.168.20.0/24, gateway .1 su ens19
Interfaccia tunnelTunnel0 – 10.255.255.1/30gre1 – 10.255.255.2/30
Traffico protettoGRE (protocollo IP 47) tra 198.51.100.1 e 203.0.113.10, modalità trasporto

Gli algoritmi sono gli stessi della guida IPsec: IKE con aes256gcm16-prfsha256-ecp256 (AES-256-GCM, PRF SHA-256, gruppo DH 19), ESP con aes256gcm16-ecp256 (AES-256-GCM con PFS gruppo 19). Lì trovi anche la tabella di corrispondenza tra i nomi Cisco e strongSwan.

Overhead, MTU e MSS

In modalità tunnel IPsec aggiungerebbe una nuova intestazione IP davanti al pacchetto GRE, che ne ha già una. In modalità trasporto l’intestazione esterna del GRE viene riusata: ESP si inserisce tra questa e l’intestazione GRE. Risparmi 20 byte per pacchetto, e il traffico è comunque tutto cifrato.

aggiunto da GRE e IPsec pacchetto originale IP 20 ESP 8 IV 8 GRE 4 IP 20 TCP 20 Dati MSS Trailer 2–5 ICV 16 cifrato (AES-256-GCM) autenticato dall’ICV
GRE su IPsec in modalità trasporto con AES-GCM. I numeri sono byte. Con NAT-T si aggiungono 8 byte di intestazione UDP dopo l’IP esterno.

Facciamo i conti su un collegamento con MTU 1500:

VoceAES-256-GCMAES-256-CBC + SHA-256
GRE (IP esterno + GRE)2424
Intestazione ESP (SPI + sequenza)88
IV816
Trailer (padding + 2 byte)2–52–17
ICV1616
NAT-T (se presente)88
Totale, caso peggiore6989

Il caso peggiore lascia circa 1431 byte con GCM e 1411 con CBC. Su PPPoE (MTU 1492) togli altri 8 byte. Per questo il valore consigliato è un MTU del tunnel di 1400: copre tutti i casi con un piccolo margine, ed è lo stesso che usa Cisco nei suoi esempi. L’MSS è l’MTU meno 40 byte di intestazioni IP e TCP: 1360.

Perché non sfruttare ogni byte?

Guadagnare 30 byte su 1400 vale il 2% di banda, ma un MTU troppo alto provoca frammentazione dopo la cifratura, che costa molto di più in CPU e in pacchetti persi. Usa 1400 su entrambi i lati: con OSPF è anche obbligatorio che i due MTU coincidano.

Configurazione del router Cisco

La parte IKEv2 è identica a quella della guida IPsec: proposta, policy, keyring e profilo. Se l’hai già configurata, riusala.

Cisco IOS XE – IKEv2
configure terminal
!
crypto ikev2 proposal PROP-GCM256
 encryption aes-gcm-256
 prf sha256
 group 19
!
crypto ikev2 policy POL-GCM256
 match address local 198.51.100.1
 proposal PROP-GCM256
!
crypto ikev2 keyring KR-SEDE-B
 peer UBUNTU-SEDE-B
  address 203.0.113.10
  pre-shared-key Cambia-Questa-Chiave-Esempio-0000
!
crypto ikev2 profile IKEV2-SEDE-B
 match identity remote address 203.0.113.10 255.255.255.255
 identity local address 198.51.100.1
 authentication remote pre-share
 authentication local pre-share
 keyring local KR-SEDE-B
 dpd 10 3 periodic

Cambia la parte IPsec: il transform-set è in modalità trasporto e il profilo si applica al tunnel GRE esistente.

Cisco IOS XE – protezione del tunnel GRE
crypto ipsec transform-set TS-GCM256-TR esp-gcm 256
 mode transport
!
crypto ipsec profile IPSEC-GRE-SEDE-B
 set transform-set TS-GCM256-TR
 set pfs group19
 set ikev2-profile IKEV2-SEDE-B
!
interface Tunnel0
 ip mtu 1400
 ip tcp adjust-mss 1360
 tunnel mode gre ip
 tunnel protection ipsec profile IPSEC-GRE-SEDE-B
!
end
write memory

Indirizzo, sorgente, destinazione e rotta statica di Tunnel0 restano quelli della guida GRE. Con tunnel protection il Cisco propone come selettori di traffico il solo GRE tra i due IP pubblici: 198.51.100.1/32 protocollo 47 verso 203.0.113.10/32 protocollo 47.

Prima di applicare, pensa all’accesso remoto

Appena applichi tunnel protection, il tunnel GRE resta giù finché anche Ubuntu non è pronto. Se gestisci uno dei due capi passando dal tunnel, perderai la connessione: lavora dalla rete locale o da un accesso alternativo. Vale anche per la PSK: Cambia-Questa-Chiave-Esempio-0000 è un segnaposto; genera la tua con openssl rand -base64 32 e usala identica sui due lati.

Aggiorna l’access list in ingresso sulla WAN: da ora accetta IKE ed ESP, e non più GRE in chiaro.

Cisco IOS XE – access list WAN
ip access-list extended WAN-IN
 permit udp host 203.0.113.10 host 198.51.100.1 eq isakmp
 permit udp host 203.0.113.10 host 198.51.100.1 eq non500-isakmp
 permit esp host 203.0.113.10 host 198.51.100.1
 no permit gre host 203.0.113.10 host 198.51.100.1

Configurazione di Ubuntu

1. Adeguare l’MTU del tunnel GRE

Nel file Netplan della guida GRE porta l’MTU da 1476 a 1400:

/etc/netplan/60-gre.yaml
network:
  version: 2
  tunnels:
    gre1:
      mode: gre
      local: 203.0.113.10
      remote: 198.51.100.1
      addresses:
        - 10.255.255.2/30
      mtu: 1400
      routes:
        - to: 192.168.10.0/24
          via: 10.255.255.1
sudo netplan try
sudo netplan apply

2. Installare strongSwan

sudo apt update
sudo apt install strongswan-swanctl charon-systemd

3. Configurare la connessione in modalità trasporto

/etc/swanctl/conf.d/sede-a-gre.conf
connections {
  sede-a-gre {
    version = 2
    local_addrs = 203.0.113.10
    remote_addrs = 198.51.100.1
    proposals = aes256gcm16-prfsha256-ecp256
    rekey_time = 24h
    dpd_delay = 10s

    local {
      auth = psk
      id = 203.0.113.10
    }
    remote {
      auth = psk
      id = 198.51.100.1
    }

    children {
      gre {
        mode = transport
        # solo GRE (protocollo 47) tra i due IP pubblici
        local_ts = 203.0.113.10[gre]
        remote_ts = 198.51.100.1[gre]
        esp_proposals = aes256gcm16-ecp256
        rekey_time = 1h
        start_action = start
        dpd_action = restart
      }
    }
  }
}

secrets {
  ike-sede-a {
    id = 198.51.100.1
    secret = "Cambia-Questa-Chiave-Esempio-0000"
  }
}

[gre] limita i selettori al protocollo GRE: strongSwan accetta il nome del protocollo o il numero, quindi [47] è equivalente. Il resto del traffico tra i due server (SSH, monitoraggio) resta fuori da IPsec.

sudo chmod 600 /etc/swanctl/conf.d/sede-a-gre.conf
sudo systemctl enable --now strongswan
sudo swanctl --load-all

4. Firewall e MSS

Nel firewall sostituisci la regola che accettava GRE dal Cisco: ora entrano IKE ed ESP, e GRE è accettato solo se è arrivato cifrato.

/etc/nftables.conf – estratto
table inet filtro {
  chain input {
    # ... regole esistenti ...
    ip saddr 198.51.100.1 udp dport { 500, 4500 } accept
    ip saddr 198.51.100.1 meta l4proto esp accept
    # GRE solo se decifrato da IPsec
    ip saddr 198.51.100.1 ip protocol gre meta ipsec exists accept
    iifname "gre1" ip saddr 10.255.255.0/30 accept
  }
  chain forward {
    # ... regole esistenti ...
    tcp flags syn tcp option maxseg size set rt mtu
    iifname "ens19" oifname "gre1" accept
    iifname "gre1" oifname "ens19" accept
  }
}

Anche senza la regola nftables, il kernel scarta il GRE in chiaro dal Cisco: la policy IPsec in ingresso, installata da strongSwan, lo richiede cifrato. La regola esplicita rende la scelta visibile a chi legge il firewall.

Verifiche

Sul router Cisco

show crypto ikev2 sa                     ! Status READY
show crypto ipsec sa peer 203.0.113.10   ! "in use settings ={Transport, }"
show crypto session detail
show interfaces Tunnel0                  ! "Tunnel protection via IPSec"
ping 10.255.255.2 source Tunnel0
ping 192.168.20.1 source GigabitEthernet0/1

In show crypto ipsec sa controlla le righe local ident e remote ident: devono riportare /47/0, cioè il protocollo GRE. I contatori #pkts encaps e #pkts decaps devono crescere mentre fai ping.

Su Ubuntu

sudo swanctl --list-sas        # ESTABLISHED, e la Child SA "INSTALLED, TRANSPORT"
sudo ip xfrm policy            # policy con "proto gre"
ping -c 3 10.255.255.1
ping -c 3 -I 192.168.20.1 192.168.10.1
sudo journalctl -u strongswan -f

La prova decisiva è guardare la WAN:

sudo tcpdump -ni ens18 'esp or udp port 4500'   # qui deve passare il traffico
sudo tcpdump -ni ens18 'ip proto 47'            # qui non deve comparire nulla

Se con il secondo comando vedi pacchetti GRE, il tunnel sta viaggiando in chiaro: la Child SA non è attiva o i selettori non corrispondono. Infine controlla l’MTU da un client della LAN B:

ping -M do -s 1372 192.168.10.10   # 1372 + 28 = 1400: deve passare
ping -M do -s 1400 192.168.10.10   # deve fallire con "mtu = 1400"

Opzionale: OSPF sopra il tunnel

Con GRE su IPsec puoi sostituire le rotte statiche con OSPF: ogni nuova rete in una sede viene annunciata all’altra senza toccare la VPN. Ecco una configurazione minima, tutta in area 0.

Sul router Cisco

Cisco IOS XE – OSPF
interface Tunnel0
 ip ospf network point-to-point
!
router ospf 1
 router-id 10.255.255.1
 passive-interface GigabitEthernet0/1
 network 10.255.255.0 0.0.0.3 area 0
 network 192.168.10.0 0.0.0.255 area 0
!
no ip route 192.168.20.0 255.255.255.0 10.255.255.2

Su Ubuntu con FRRouting

sudo apt install frr
sudo sed -i 's/^ospfd=no/ospfd=yes/' /etc/frr/daemons
sudo systemctl restart frr
/etc/frr/frr.conf – estratto
interface gre1
 ip ospf network point-to-point
!
interface ens19
 ip ospf passive
!
router ospf
 ospf router-id 10.255.255.2
 network 10.255.255.0/30 area 0
 network 192.168.20.0/24 area 0
sudo systemctl reload frr
sudo vtysh -c "show ip ospf neighbor"

Togli poi il blocco routes: dal file Netplan di gre1, altrimenti la rotta statica resta e prevale su quella OSPF. Nel firewall di Ubuntu accetta OSPF (protocollo 89) dal tunnel:

iifname "gre1" ip protocol 89 accept
Adiacenza bloccata in EXSTART

OSPF confronta l’MTU delle interfacce: se Tunnel0 e gre1 non sono entrambe a 1400, l’adiacenza non arriva mai a FULL. Allinea gli MTU invece di usare ip ospf mtu-ignore.

Problemi comuni

SintomoCausa probabileCosa fare
NO_PROPOSAL_CHOSENAlgoritmi IKE o ESP diversiConfronta le proposte con la tabella della guida IPsec; il log di strongSwan elenca quelle ricevute
AUTHENTICATION_FAILEDPSK o identità diverseAllinea id in swanctl con identity local e match identity remote sul Cisco; ricopia la chiave
TS_UNACCEPTABLESelettori diversi: per esempio il Cisco usa un IP sorgente diverso da 198.51.100.1Verifica tunnel source e tunnel destination; local_ts e remote_ts devono essere i due IP pubblici con [gre]
Child SA in modalità TUNNEL invece di TRANSPORTUn lato non chiede la modalità trasportoControlla mode transport nel transform-set e mode = transport nella child; funziona lo stesso, ma con 20 byte in più
SA attive, ma Tunnel0 non passa trafficoNetplan o firewall: GRE scartato dopo la decifraturaip -d link show gre1; controlla la regola meta ipsec exists e rp_filter
Il tunnel cade dopo circa un’oraPFS configurato da una sola parte, fallisce il rekeyAllinea set pfs group19 e ecp256 in esp_proposals
Dopo il riavvio di un capo il tunnel resta giùDPD assenteVerifica dpd sul Cisco e dpd_action = restart su strongSwan
Ubuntu dietro un router con NATIn trasporto i selettori contengono l’IP pubblico, che Ubuntu non haPreferisci IP pubblici diretti; in alternativa usa la modalità tunnel o una VTI con NAT-T
Ping OK, ma siti e condivisioni si bloccanoMTU/MSSMTU 1400 su Tunnel0 e gre1, MSS 1360 sul Cisco, regola MSS su Ubuntu

In produzione e passi successivi

La chiave condivisa va bene per due sedi. In produzione preferisci i certificati: ogni capo ha la propria chiave privata e puoi revocarne uno senza toccare gli altri (sul Cisco authentication local rsa-sig con un trustpoint PKI, su strongSwan auth = pubkey).

Se non ti servono multicast né routing dinamico, una VPN IPsec con VTI è più semplice e ha meno overhead: la trovi nella guida VPN IPsec tra Cisco e Ubuntu con strongSwan. Per ripassare il tunnel di partenza, vedi Tunnel GRE tra un router Cisco e Ubuntu Linux.

Prima di andare in produzione

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.