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.
| IPIP | GRE | |
|---|---|---|
| Specification | RFC 2003 | RFC 2784; key and sequence number in RFC 2890 |
| IP protocol number | 4 | 47 |
| Overhead on an IPv4 path | 20 bytes | 24 bytes; +4 each for key, checksum and sequence number |
| Tunnel MTU on a 1,500-byte path | 1,480 | 1,476 (1,472 with a key) |
| TCP MSS, IPv4 inside | 1,440 | 1,436 (1,432 with a key) |
| Payloads | IPv4 only | IPv4, IPv6, MPLS, Ethernet frames, others by EtherType |
| Several tunnels between the same two addresses | Not distinguishable | Yes, with different keys |
| Keepalives | None | Vendor feature, not in the RFC |
| Encryption | None | None |
| Linux link types | ipip | gre, 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.
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 tunnel03What 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: 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=206How 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
| Symptom | Likely cause | Fix |
|---|---|---|
| Ping works; large transfers and TLS handshakes stall | MTU too high, or MSS not clamped | Set the tunnel MTU and clamp the MSS |
| Tunnel interface up, nothing arrives | Protocol 47 or 4 blocked, or wrong remote address | Allow the protocol from the far endpoint; capture on the uplink |
| Packets arrive, replies never leave | Strict reverse-path filtering, or no route back | rp_filter=2, or policy routing through the tunnel |
| Fails behind NAT | GRE and IPIP have no ports for NAT to track | Use a public address on the endpoint |
| Keyed tunnel drops everything | Key mismatch | Match key, or ikey and okey, on both ends |
| Tunnel stays up while traffic vanishes | Nothing monitors the far end | Run BGP or BFD over it, or probe the far end |
# 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-pmtu08GRE 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
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.
- 01RFC 2784: Generic Routing Encapsulation (GRE) · RFC Editor
- 02RFC 2890: Key and Sequence Number Extensions to GRE · RFC Editor
- 03RFC 2003: IP Encapsulation within IP · RFC Editor
- 04Assigned Internet Protocol Numbers · IANA
- 05RFC 4459: MTU and Fragmentation Issues with In-the-Network Tunneling · RFC Editor
- 06How GRE keepalives work · Cisco
- 07Magic Transit: MTU and MSS · Cloudflare docs
- 08ip-link(8) manual page · man7.org
- 09IP sysctl: rp_filter · Linux kernel documentation
- 10Mangling packet headers (MSS clamping) · nftables wiki
Last updated