GRE over IPsec: Why Tunnels and Encryption Belong Together

Configure GRE over IPsec on Cisco IOS XE with IKEv2 and IPsec profiles. Modern and legacy configs, MTU planning, OSPF over the tunnel, and gotchas.

GRE over IPsec: packet capture showing plaintext inner IPs and OSPF hellos, then ESP only

Every site-to-site VPN design runs into the same wall. You build a crypto map, the tunnel comes up, traffic between the two LANs is encrypted, and then someone asks the obvious question: "how do the sites learn each other's routes?" With a plain crypto map the answer is "they don't, you type them in by hand." A crypto ACL matches unicast flows. OSPF hellos go to 224.0.0.5. Those two facts never meet.

GRE solves exactly that problem and nothing else. It gives you a real routed interface that carries multicast, so a routing protocol runs across it. What it does not do is protect a single byte. Put the two together and you get what you actually wanted: a routed, encrypted WAN. This article is part of the IPsec VPN cluster, and it proves both halves with a packet capture taken at the same point on the same link, before and after.

The Two Halves of the Problem

GRE and IPsec are not competing technologies and they are not redundant. Each one does something the other structurally cannot.

What GRE gives you
Real interface: Tunnel0 with an IP address, a line protocol, and an MTU
Multicast: yes, so OSPF and EIGRP run across it
Any protocol: IPv4, IPv6, and legacy payloads all ride inside
Routing table entry: the tunnel is a next hop like any other
Confidentiality: none at all
Overhead: 24 bytes (20 byte outer IP + 4 byte GRE)
What IPsec gives you
Confidentiality: ESP encrypts the whole inner packet
Integrity and authentication: HMAC on every packet, peers proven by PSK or certs
Anti-replay: sequence numbers inside the SA
Multicast: no, a crypto ACL matches unicast flows
Interface: none, a crypto map is a filter bolted to a physical port
Routing protocols: cannot carry them

Read those two cards side by side and the design writes itself. GRE builds the pipe, IPsec protects it. Every gap in one column is filled by the other.

Half One: GRE Alone Carries Routing and Protects Nothing

The lab is a pair of cat8000v routers (EDGE1 and EDGE2) with an ISP router in the middle. EDGE1 sits on 203.0.113.1, EDGE2 on 198.51.100.2, and a GRE tunnel runs between those two public addresses with OSPF enabled on Tunnel0. First, what GRE claims to be:

EDGE1#show interface Tunnel0
Tunnel0 is up, line protocol is up
  Tunnel source 203.0.113.1 (GigabitEthernet2), destination 198.51.100.2
  Tunnel protocol/transport GRE/IP
  Tunnel transport MTU 1476 bytes

Tunnel protocol/transport GRE/IP, transport MTU 1476 (1500 on the wire, minus a 20 byte outer IP header, minus the 4 byte GRE header). That is a real interface, and a real interface can do the one thing a crypto map cannot:

EDGE1#show ip ospf neighbor
Neighbor ID     Pri   State           Dead Time   Address         Interface
10.255.0.2        0   FULL/  -        00:00:35    10.0.0.2        Tunnel0

FULL adjacency, across the public internet, through a tunnel. Add a subnet at either end and it appears at the other with no human intervention. That is the whole reason GRE exists, and why the GRE cluster is worth understanding on its own terms. Now the other half of the ledger:

EDGE1#show crypto ipsec sa
   (empty - NOTHING is encrypted)

Nothing. No SAs, no SPIs, no encaps counters. GRE has a header that looks technical and a name that sounds like infrastructure. Neither of those is encryption.

The Packet Capture That Ends the Argument

Here is a capture taken on the EDGE1 to ISP1 link, exactly where a hostile transit provider or anyone with a tap would sit. Plain GRE, carrying a ping from a real Debian host (192.168.99.100) to a loopback behind the far router (10.30.10.1):

No.  Time      Source           Destination      Proto  Info
1    0.000000  10.0.0.2         224.0.0.5        OSPF   LS Acknowledge
2    1.461513  192.168.99.100   10.30.10.1       ICMP   Echo (ping) request  id=0x004e, seq=1/256, ttl=63
3    1.462810  10.30.10.1       192.168.99.100   ICMP   Echo (ping) reply    id=0x004e, seq=1/256, ttl=255
4    2.463253  192.168.99.100   10.30.10.1       ICMP   Echo (ping) request  id=0x004e, seq=2/512, ttl=63
5    2.464559  10.30.10.1       192.168.99.100   ICMP   Echo (ping) reply    id=0x004e, seq=2/512, ttl=255
8    4.100454  10.0.0.1         224.0.0.5        OSPF   Hello Packet
15   7.206880  10.0.0.2         224.0.0.5        OSPF   Hello Packet

Look at what the capture tool did without being asked. It dissected straight through the GRE header and printed the inner conversation. The ISP can read:

  • Your private host addressing. 192.168.99.100 talking to 10.30.10.1. Your internal IP plan is on the wire.
  • Your application traffic. This happens to be ICMP. If it were HTTP or SNMP or a database session, the payload would be sitting there in full.
  • Your routing protocol. OSPF hellos and LS acknowledgements from 10.0.0.1 and 10.0.0.2 to 224.0.0.5. An attacker on this link now knows your tunnel subnet, your router IDs, your timers, and with a little work could inject LSAs.

GRE is encapsulation. Encapsulation is not encryption. If you take one thing from this article, make it that packet list.

The fix is four lines. Build an IPsec profile (the same transform set you would use with a crypto map, minus the crypto ACL) and bolt it to the tunnel interface:

crypto ipsec profile PLZ-IPSEC-PROF
 set transform-set PLZ-TS-AES256
 set pfs group14
interface Tunnel0
 tunnel protection ipsec profile PLZ-IPSEC-PROF

Note what is not there. There is no ip access-list extended PLZ-CRYPTO-ACL. There is no match address. There is no set peer. The tunnel already knows its peer (that is the tunnel destination) and it already knows what to encrypt (everything that enters the tunnel interface). The interface has replaced the ACL as the traffic selector, which is why this is dramatically simpler than the crypto map approach and dramatically harder to get wrong.

The Same Capture Point, The Same Ping, After

No.  Time      Source         Destination    Proto   Info
3    5.153552  203.0.113.1    198.51.100.2   ISAKMP  Identity Protection (Main Mode)
6    5.617148  198.51.100.2   203.0.113.1    ISAKMP  Identity Protection (Main Mode)
9    5.861495  203.0.113.1    198.51.100.2   ISAKMP  Quick Mode
11   6.425161  203.0.113.1    198.51.100.2   ISAKMP  Quick Mode
12   7.026032  203.0.113.1    198.51.100.2   ESP     ESP (SPI=0x6d4428aa)
13   8.939238  198.51.100.2   203.0.113.1    ESP     ESP (SPI=0x94cd6141)
14  12.002692  203.0.113.1    198.51.100.2   ESP     ESP (SPI=0x6d4428aa)
15  12.003690  198.51.100.2   203.0.113.1    ESP     ESP (SPI=0x94cd6141)
16  13.004286  203.0.113.1    198.51.100.2   ESP     ESP (SPI=0x6d4428aa)
17  13.005508  198.51.100.2   203.0.113.1    ESP     ESP (SPI=0x94cd6141)

Same link. Same ping. Same OSPF adjacency still running underneath. And the ISP now sees precisely two IP addresses (203.0.113.1 and 198.51.100.2, both of which are public and both of which it was routing anyway) plus an opaque stream of ESP. No 192.168.99.100. No 10.30.10.1. No 224.0.0.5. The routing protocol is still converging, it is just doing it inside the ciphertext.

Reading the Main Mode, Quick Mode, ESP Sequence

That capture is a complete IKEv1 lifecycle in ten packets, and it is worth walking slowly because this is the exact sequence you will be staring at in a troubleshooting session.

  • Packets 3 and 6, Identity Protection (Main Mode). This is IKE Phase 1, six messages in three exchanges. The peers negotiate the ISAKMP policy (encryption, hash, DH group, lifetime), perform the Diffie-Hellman key exchange, and then authenticate each other with the pre-shared key. The dissector calls it "Identity Protection" because Main Mode's whole selling point over Aggressive Mode is that the identity exchange happens after the DH shared secret exists, so the identities are already encrypted. The output of Phase 1 is a bidirectional ISAKMP SA: a secure management channel, carrying no user data.
  • Packets 9 and 11, Quick Mode. This is IKE Phase 2, and it runs entirely inside the Phase 1 SA (which is why the capture can name it but not read it). Here the peers negotiate the IPsec transform set, agree the proxy identities, and with PFS enabled they run a fresh Diffie-Hellman exchange so the Phase 2 keys are not derived from the Phase 1 material. The output is a pair of unidirectional IPsec SAs, one per direction.
  • Packets 12 onward, ESP. The two SPIs (0x6d4428aa outbound from EDGE1, 0x94cd6141 inbound from EDGE2) are the SA identifiers. Every subsequent data packet is ESP: encrypted GRE, encapsulating IP, encapsulating your ping. The capture tool can see the SPI and the sequence number and nothing else, because that is all that is in the clear.

This sequence also explains why the first ping across a freshly configured tunnel often fails: the packets that trigger IKE are consumed building the SA. Phase 1 and Phase 2 take real time, and IOS drops what it cannot yet encrypt. Ping twice before declaring a tunnel broken.

Why Tunnel Protection Beat the Old Crypto Map Approach

The old way to do this was to apply a crypto map to the tunnel interface and to the physical interface, with a crypto ACL that read something like permit gre host 203.0.113.1 host 198.51.100.2. It worked, mostly, and it was miserable:

  • Two places to apply the same crypto map, and forgetting the physical interface produced a tunnel that came up and dropped everything.
  • The crypto ACL matched the GRE flow, so the encryption decision was effectively made twice. Debugging a mismatch meant reasoning about both.
  • IOS XE refuses to edit a crypto ACL that is in use, so every change meant pulling the map off the interface first.

tunnel protection ipsec profile collapses all of that into one statement on one interface. The tunnel endpoints are the crypto peers. The tunnel interface is the traffic selector. There is nothing to mismatch, which is the biggest single source of IPsec outages eliminated by configuration syntax. It is also the only approach that scales to mGRE, which is what DMVPN is built on: a hub cannot hold a static crypto map per spoke, but it can hold one IPsec profile that every dynamic tunnel inherits.

MTU: The 1476 Number and the 1438 Number

GRE reported a transport MTU of 1476: 1500 minus the 20 byte outer IP header minus the 4 byte GRE header, before any encryption at all.

Now add ESP in tunnel mode with AES-256 and SHA-256. That means another outer IP header, the ESP header with its SPI and sequence number, an initialisation vector, block-cipher padding, the ESP trailer, and the authentication data. With this exact transform set the crypto SA reports what is left:

     local crypto endpt.: 203.0.113.1, remote crypto endpt.: 198.51.100.2
     plaintext mtu 1438, path mtu 1500, ip mtu 1500, ip mtu idb GigabitEthernet2

1438 against a path MTU of 1500. That is roughly 62 bytes of IPsec overhead, and it lands on top of the GRE overhead you already paid. The practical consequence: a 1500 byte packet entering Tunnel0 will not fit, and something has to give. You have three options, in order of how much you will regret them.

  1. Lower the tunnel IP MTU. ip mtu 1400 on Tunnel0 makes the router fragment before encryption rather than after, which is the cheaper of the two fragmentation points.
  2. Clamp TCP. ip tcp adjust-mss 1360 on the tunnel rewrites the MSS in the TCP handshake so hosts never generate an oversized segment in the first place. This is the single highest-value line of config in most GRE over IPsec deployments and it fixes the classic "ping works, big file transfers hang" complaint.
  3. Rely on path MTU discovery. Which works right up until a firewall somewhere in the middle drops ICMP unreachables, and then it fails silently and intermittently. Do not rely on it.

The pings in our captures were 100 bytes and never came close to the limit. MTU problems do not show up in your smoke test. They show up three weeks later in a ticket about one application.

Transport Mode vs Tunnel Mode for GRE Over IPsec

The transform set in this lab uses mode tunnel, the default and what the capture shows. ESP in tunnel mode adds a fresh outer IP header, so the packet on the wire is: outer IP, ESP, inner IP, GRE, original IP, payload.

You can also run mode transport. Because the GRE tunnel's source and destination are already the same addresses as the crypto endpoints, that tunnel-mode outer header is a byte-for-byte duplicate of the header GRE already built. Transport mode skips it and reuses the GRE outer header, saving 20 bytes per packet. On a WAN carrying small packets (voice, for example) that is a real saving.

The catch is NAT. Transport mode leaves the original IP header intact and integrity-protected, so a NAT device that rewrites addresses in the path will break the authentication check. Tunnel mode, combined with NAT-T's UDP 4500 encapsulation, survives it. That is why tunnel mode stays the safe default, and why transport mode is an optimisation you apply only when both endpoints are public and nothing between them is translating.

Where This Goes Next

An obvious question follows from all of this: if the GRE header is only there to give us an interface, and IPsec can now attach directly to an interface, do we still need GRE at all? For a straightforward IPv4 site-to-site link the answer is no, and that is the static VTI, which drops the GRE header entirely and reports Tunnel protocol/transport IPSEC/IP with a transport MTU of 1438 instead of 1476. Same routing protocol support, four fewer bytes, same profile.

Crypto maps vs VTI puts the older design and the newer one head to head. And when you need this for dozens of spokes rather than one peer, GRE stops being point-to-point and becomes mGRE, which is where DMVPN takes over. The IPsec profile you built here is the same object DMVPN uses, so nothing you learned in this article gets thrown away.

Key Takeaways

  • GRE carries routing protocols and encrypts nothing. The capture on the transit link showed inner host IPs (192.168.99.100 to 10.30.10.1) and OSPF hellos to 224.0.0.5 in the clear. Encapsulation is not encryption.
  • A crypto map encrypts and cannot carry routing. A crypto ACL matches unicast flows. OSPF's multicast hellos never match one, so a plain crypto map VPN needs static routes forever.
  • Together they are a routed, encrypted WAN. After tunnel protection ipsec profile, the same capture point showed ISAKMP Main Mode, then Quick Mode, then nothing but ESP between the two public endpoints. The OSPF adjacency never dropped, it just became invisible.
  • Tunnel protection is far simpler than a crypto map. No crypto ACL, no set peer, no double application to tunnel and physical. The tunnel interface is the traffic selector.
  • Budget for MTU. GRE gives you 1476, and this AES-256 / SHA-256 transform set leaves a plaintext MTU of 1438. Set ip tcp adjust-mss on the tunnel before your users find the problem for you.
  • Tunnel mode is the safe default. Transport mode saves 20 bytes by reusing the GRE outer header, but any NAT in the path will break it.
  • The first ping often fails. IKE is built on demand and the triggering packets are consumed doing it. Ping twice.

For the rest of the series, including IKEv1 versus IKEv2, NAT traversal, and a systematic approach to debugging a tunnel that will not come up, start at the IPsec VPN pillar.

Read next