Network & delivery

7 min readUpdated

GRE vs IPIP: which tunnel should you use?

Quick answer

GRE and IPIP are both stateless tunnels that wrap a packet inside a new IPv4 header. IPIP (IP protocol 4) carries only IPv4 and adds 20 bytes. GRE (IP protocol 47) adds a 4-byte GRE header on top, 24 bytes in total, but can carry IPv6, MPLS and Ethernet frames, and several keyed tunnels can share the same endpoints. Neither encrypts. For DDoS-protected transit GRE is the usual choice; IPIP suits simple IPv4-only links.

01What is the difference between GRE and IPIP?

Both are point-to-point tunnels without handshakes, sessions or encryption. The sender adds an outer IPv4 header addressed to the far end, routers in between forward it like any other packet, and the receiver strips the outer header and routes the original packet onwards.

IPIP, specified in RFC 2003, puts an IPv4 packet directly behind a new IPv4 header and marks it with IP protocol number 4. GRE, specified in RFC 2784, inserts a small GRE header between the two and uses protocol 47. That header's Protocol Type field names the payload with an EtherType value, which is what lets GRE carry much more than IPv4. For how tunnels deliver filtered traffic in general, see GRE tunnelling explained.

IPIPGRE
SpecificationRFC 2003RFC 2784; key and sequence number in RFC 2890
IP protocol number447
Overhead on an IPv4 path20 bytes24 bytes; +4 each for key, checksum and sequence number
Tunnel MTU on a 1,500-byte path1,4801,476 (1,472 with a key)
TCP MSS, IPv4 inside1,4401,436 (1,432 with a key)
PayloadsIPv4 onlyIPv4, IPv6, MPLS, Ethernet frames, others by EtherType
Several tunnels between the same two addressesNot distinguishableYes, with different keys
KeepalivesNoneVendor feature, not in the RFC
EncryptionNoneNone
Linux link typesipipgre, gretap, ip6gre

02Header overhead, MTU and MSS: the arithmetic

Encapsulation takes bytes from every packet. On a path with a 1,500-byte MTU, the inner packet must be smaller by everything the tunnel adds, and TCP's maximum segment size (MSS) must be smaller again by the inner IPv4 and TCP headers, 40 bytes without options. The tunnel MTU and MSS calculator does the same sums for stacked tunnels.

Cloudflare's tunnel documentation gives the same GRE figures, 1,476 and 1,436, a useful cross-check that these are arithmetic rather than vendor preference. If the physical path is smaller than 1,500 bytes, for example 1,492 on PPPoE, subtract from that instead.

Getting it wrong produces a distinctive failure. Pings and TCP handshakes pass, so the tunnel looks up, but full-size packets are dropped and large downloads, TLS handshakes with big certificate chains or busy SSH sessions stall. Path MTU discovery should fix it, but it relies on ICMP Fragmentation Needed messages that many networks filter, a problem RFC 4459 describes for tunnels. Clamping the MSS on TCP SYN packets removes the dependency.

Worked calculation for a 1,500-byte path
IPIP          1500 - 20 (outer IPv4)            = 1480 MTU   1480 - 40 = 1440 MSS
GRE           1500 - 20 - 4 (GRE header)        = 1476 MTU   1476 - 40 = 1436 MSS
GRE + key     1500 - 20 - 4 - 4 (key)           = 1472 MTU   1472 - 40 = 1432 MSS
GRE over IPv6 1500 - 40 (outer IPv6) - 4        = 1456 MTU   1456 - 40 = 1416 MSS

IPv6 inside the tunnel: subtract 60 instead of 40 (40-byte IPv6 + 20-byte TCP header)
GRE           1476 - 60 = 1416 MSS for IPv6 traffic through an IPv4 GRE tunnel

03What can each tunnel carry?

GRE's Protocol Type field uses EtherType values from the IANA registry: 0x0800 for IPv4, 0x86DD for IPv6, 0x8847 for MPLS and 0x6558 for Transparent Ethernet Bridging, which Linux exposes as gretap. One GRE tunnel can therefore carry IPv4 and IPv6 together, or bridge two layer-2 segments.

IPIP carries IPv4 and nothing else. IPv6 inside IPv4 uses a different protocol number, 41 (SIT on Linux), so a dual-stack service needs a second tunnel where one GRE tunnel would do. Routing protocols follow the same split: BGP and OSPFv2 run over either, while OSPFv3 needs IPv6 and IS-IS is not IP at all.

GRE's optional key, defined in RFC 2890, is a 32-bit value carried in every packet. It lets two endpoints run several independent tunnels between the same pair of addresses, which is why some providers ask for one.

04Keepalives: how do you know a tunnel is down?

Neither RFC 2784 nor RFC 2003 defines a keepalive. Both tunnels are stateless, so an interface can stay up for days while the far end is unreachable and traffic quietly disappears into it.

Cisco's GRE keepalive is the best-known workaround. The router builds a GRE packet whose inner header is addressed back to itself; the far end decapsulates it and routes it home as ordinary traffic, so it works even when the remote end has no keepalive support. Cisco's default is one every 10 seconds, with the tunnel declared down after 3 are missed. IPIP has no equivalent, and iproute2 offers no keepalive option for either type.

On transit tunnels, liveness usually comes from the routing layer instead:

  • A BGP session over the tunnel, which drops and withdraws routes when the tunnel stops passing traffic
  • BFD for sub-second failure detection, where both ends support it
  • A monitoring probe that pings the far tunnel address and alerts on loss
  • Cisco-style keepalives, between devices that send or reflect them

05How to set up GRE and IPIP tunnels on Linux

The GRE, routing and sysctl commands were run inside an isolated network namespace, not on a live host, and the IPIP lines follow iproute2's own help output. Addresses are documentation examples: 198.51.100.2 is your server, 203.0.113.1 the far tunnel endpoint and 192.0.2.64/29 a protected range.

The last block matters when inbound traffic arrives through the tunnel but replies leave through the normal uplink. Linux applies the higher of the all and per-interface rp_filter values, and 2 (loose) is higher than 1 (strict), so loose mode on all is enough to stop the kernel discarding tunnelled packets as spoofed.

GRE and IPIP with iproute2 (syntax per iproute2 6.1)
# GRE: 24 bytes of overhead on an IPv4 path
ip link add gre1 type gre local 198.51.100.2 remote 203.0.113.1 ttl 255
ip link set gre1 mtu 1476 up
ip addr add 10.10.10.2/30 dev gre1

# keyed GRE, if the far end assigns a key
ip link add gre2 type gre local 198.51.100.2 remote 203.0.113.1 ttl 255 key 1001

# IPIP: 20 bytes of overhead, IPv4 payload only
ip link add ipip1 type ipip local 198.51.100.2 remote 203.0.113.1 ttl 255
ip link set ipip1 mtu 1480 up

# send replies from the protected range back through the tunnel
ip rule add from 192.0.2.64/29 table 100
ip route add default dev gre1 table 100

# or keep replies on the uplink and use loose reverse-path filtering
sysctl -w net.ipv4.conf.all.rp_filter=2

06How DDoS protection providers deliver clean traffic over GRE

For services that are not websites, such as game servers, mail or whole networks, DDoS protection works at the routing layer. The provider announces the protected prefix, at least a /24, with BGP, so traffic for it reaches the provider's network, attack traffic is filtered there, and the clean remainder is encapsulated and sent to the customer through a tunnel. Replies either return through the tunnel or leave directly through the customer's own uplink.

GRE is the usual choice because one tunnel carries IPv4 and IPv6, keys let several tunnels share endpoints, and almost every router and operating system supports it. IPIP works for an IPv4-only server where both ends are Linux.

Two prerequisites are easy to miss. If you bring your own prefix and it has ROAs, one of them must also authorise whichever AS originates it during mitigation, or networks that validate routes will drop the announcement as invalid: see what RPKI is. And the server's real address must not be reachable by attackers, as covered in how to hide your origin IP. For game hosting, see DDoS protection for game servers.

07Troubleshooting a GRE or IPIP tunnel

SymptomLikely causeFix
Ping works; large transfers and TLS handshakes stallMTU too high, or MSS not clampedSet the tunnel MTU and clamp the MSS
Tunnel interface up, nothing arrivesProtocol 47 or 4 blocked, or wrong remote addressAllow the protocol from the far endpoint; capture on the uplink
Packets arrive, replies never leaveStrict reverse-path filtering, or no route backrp_filter=2, or policy routing through the tunnel
Fails behind NATGRE and IPIP have no ports for NAT to trackUse a public address on the endpoint
Keyed tunnel drops everythingKey mismatchMatch key, or ikey and okey, on both ends
Tunnel stays up while traffic vanishesNothing monitors the far endRun BGP or BFD over it, or probe the far end
Capture filter and MSS clamping (tcpdump 4.99 filter compiled; rules checked with nft 1.0.6 and iptables 1.8.9)
# see tunnel packets on the physical interface
tcpdump -ni eth0 'ip proto 47 or ip proto 4'

table inet mssclamp {
    chain forward {
        type filter hook forward priority mangle; policy accept;
        oifname "gre1" tcp flags syn tcp option maxseg size set rt mtu
        iifname "gre1" tcp flags syn tcp option maxseg size set rt mtu
    }
    chain output {
        type filter hook output priority mangle; policy accept;
        ip saddr 192.0.2.64/29 tcp flags & (syn | ack) == syn | ack tcp option maxseg size > 1436 tcp option maxseg size set 1436
    }
}

# iptables equivalent of the forward rule
iptables -t mangle -A FORWARD -o gre1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

08GRE or IPIP: which should you choose?

The four-byte difference is about 0.27% of a 1,500-byte packet (4 / 1,500), rarely the deciding factor. What the tunnel must carry, and what the far end supports, usually decides.

  • GRE for IPv6, several tunnels between the same endpoints, Ethernet bridging, or routing protocols beyond BGP and OSPFv2
  • GRE when the provider or appliance at the other end expects it, the common case for DDoS-protected transit
  • IPIP for a simple IPv4-only link between two Linux hosts
  • Neither if you need confidentiality: add IPsec or use an encrypted tunnel, accepting more overhead

Questions

Frequently asked questions

Only marginally. IPIP adds 20 bytes per packet and GRE 24, a difference of about 0.27% of a full 1,500-byte packet, and both are simple enough for routers and the Linux kernel to handle at line rate. The choice is usually driven by what the tunnel must carry and what the far end supports, not by throughput. GRE's optional key and checksum add four bytes each.

GRE uses IP protocol 47, as registered with IANA and specified in RFC 2784. IPIP uses protocol 4, and IPv6 encapsulated in IPv4 uses 41. Firewalls must allow the specific protocol number between the two tunnel endpoints; opening TCP or UDP ports does nothing, because these tunnels have no ports at all.

Generally not reliably. NAT devices track flows by port number, and neither GRE nor IPIP has ports, so most home routers and carrier-grade NAT cannot map tunnel packets back to the right inside host. Some routers have a helper for the GRE used by old VPN protocols, but for an endpoint behind NAT a UDP-based tunnel is the practical choice.

No. Both only encapsulate. Anyone on the path between the endpoints can read the packets and, without further protection, inject packets that look like tunnel traffic. For delivering public internet traffic that was never private, that is usually acceptable. Where the payload is sensitive, run IPsec over the tunnel, and in every case accept tunnel packets only from the far endpoint's address.

A standard Ethernet path carries 1,500-byte IP packets, and GRE over IPv4 adds a 20-byte outer IPv4 header plus a 4-byte GRE header, leaving 1,476 bytes for the inner packet. Subtracting another 40 bytes for the inner IPv4 and TCP headers gives the usual MSS of 1,436. With a GRE key enabled, both values drop by four.

Sources

Sources and verification

GRE and keyed GRE interfaces, the policy routing, the rp_filter sysctl, the nftables (nft 1.0.6) ruleset and the iptables (1.8.9) rule were created inside an isolated network namespace with iproute2 6.1.0; the IPIP lines were checked against iproute2's help output only; the tcpdump 4.99.3 filter was compiled with tcpdump -d; Debian 12, October 2026.

  1. 01RFC 2784: Generic Routing Encapsulation (GRE) · RFC Editor
  2. 02RFC 2890: Key and Sequence Number Extensions to GRE · RFC Editor
  3. 03RFC 2003: IP Encapsulation within IP · RFC Editor
  4. 04Assigned Internet Protocol Numbers · IANA
  5. 05RFC 4459: MTU and Fragmentation Issues with In-the-Network Tunneling · RFC Editor
  6. 06How GRE keepalives work · Cisco
  7. 07Magic Transit: MTU and MSS · Cloudflare docs
  8. 08ip-link(8) manual page · man7.org
  9. 09IP sysctl: rp_filter · Linux kernel documentation
  10. 10Mangling packet headers (MSS clamping) · nftables wiki

Last updated