Introduction
GRE (Generic Routing Encapsulation, RFC 2784) is the standard transport for delivering BGP transit at a distance. It's a simple L3 tunnel, no encryption, adding only 24 bytes of header (4 GRE + 20 IPv4) or 44 bytes (4 GRE + 40 IPv6). Light, natively supported by Linux, Cisco, Arista, OPNsense, Mikrotik.
Main limit: GRE uses IP protocol 47, often filtered by residential boxes (notably Bouygues Bbox in France). If that's your case, see the WireGuard or VXLAN tutorial.
Prerequisites
- A Linux server with a fixed public IP (
PUB_CLIENT) - VeryCloud's technical email with your addressing plan:
PUB_VC(VeryCloud endpoint),169.254.X.1/30(VeryCloud tunnel IP),169.254.X.2/30(your tunnel IP),2a0e:XXXX:XXXX::/127v6 - Root / sudo
- Kernel module
ip_gre(present in 100% of recent distros)
Step 1: Verify GRE support
sudo modprobe ip_gre
sudo modprobe ip6_gre
lsmod | grep gre
You should see ip_gre and ip6_gre loaded.
Step 2: Create the GRE tunnel (IPv4)
For a standard tunnel (IPv4-in-IPv4):
sudo ip tunnel add gre-vc mode gre \
remote PUB_VC \
local PUB_CLIENT \
ttl 255
sudo ip link set gre-vc up
sudo ip addr add 169.254.X.2/30 dev gre-vc
For a dual-stack tunnel (carry v4 AND v6 in the same GRE tunnel):
sudo ip link add gre-vc type gretap \
remote PUB_VC \
local PUB_CLIENT \
ttl 255
sudo ip link set gre-vc up
sudo ip addr add 169.254.X.2/30 dev gre-vc
sudo ip -6 addr add 2a0e:XXXX:XXXX::1/127 dev gre-vc
💡
gretapis L2 mode. For simple IP transit,mode greis enough — you address v4+v6 on top.
Step 3: MTU and fragmentation
GRE adds 24 bytes of IPv4 header. On standard Ethernet MTU=1500, your in-tunnel effective MTU is 1476.
sudo ip link set gre-vc mtu 1476
TCP-MSS clamping to avoid TCP sessions breaking:
sudo iptables -t mangle -A FORWARD -o gre-vc -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
sudo ip6tables -t mangle -A FORWARD -o gre-vc -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
⚠️ Clamping is mandatory in practice. Without it, some sites/services load partially.
Step 4: Test connectivity
ping 169.254.X.1
ping6 2a0e:XXXX:XXXX::0
Step 5: Persistence with systemd-networkd
/etc/systemd/network/10-gre-vc.netdev:
[NetDev]
Name=gre-vc
Kind=gre
[Tunnel]
Local=PUB_CLIENT
Remote=PUB_VC
TTL=255
/etc/systemd/network/10-gre-vc.network:
[Match]
Name=gre-vc
[Network]
Address=169.254.X.2/30
Address=2a0e:XXXX:XXXX::1/127
LinkLocalAddressing=no
[Link]
MTUBytes=1476
sudo systemctl enable --now systemd-networkd
sudo systemctl restart systemd-networkd
networkctl status gre-vc
Step 6: Persistence with Netplan (Ubuntu)
network:
version: 2
tunnels:
gre-vc:
mode: gre
local: PUB_CLIENT
remote: PUB_VC
mtu: 1476
addresses:
- 169.254.X.2/30
- 2a0e:XXXX:XXXX::1/127
sudo netplan apply.
Step 7: Tunnel routes
ip route show dev gre-vc
ip -6 route show dev gre-vc
Step 8: Prepare for BGP
Authorize TCP/179 between tunnel IPs:
sudo iptables -A INPUT -p tcp --dport 179 -s 169.254.X.1 -j ACCEPT
sudo iptables -A INPUT -p tcp --sport 179 -s 169.254.X.1 -j ACCEPT
sudo ip6tables -A INPUT -p tcp --dport 179 -s 2a0e:XXXX:XXXX::0 -j ACCEPT
sudo ip6tables -A INPUT -p tcp --sport 179 -s 2a0e:XXXX:XXXX::0 -j ACCEPT
Troubleshooting
Ping on tunnel IP doesn't respond
- Check VeryCloud side that the tunnel is provisioned (technical email received)
- Your side:
ip tunnel showshould listgre-vc,ip link show gre-vcshould be UP tcpdump -i any proto greto see if GRE packets arrive
IP proto 47 blocked (residential ISP case)
- Classic symptom: no GRE packets leave your box, or none come back
- Bouygues Bbox actively filters proto 47 on consumer plans
- Solution: switch to WireGuard or VXLAN (dedicated tutorials)
- Or: host behind a public VPS that relays the GRE
Tunnel up but losing packets
- MTU wrong: retry lower MTU (
1400then increase) - TCP-MSS clamping missing
- NAT issue in path
Operation not supported when creating the tunnel
- Module
ip_grenot loaded:sudo modprobe ip_gre - LXC/Docker: need host kernel with GRE support and
NET_ADMINcapability
Tunnel recreated at each reboot
- Forgot systemd-networkd or Netplan persistence (step 5 or 6)
Useful commands
# List all GRE tunnels
ip -d link show type gre
ip tunnel show
# Stats
ip -s link show gre-vc
# Tcpdump on the tunnel
sudo tcpdump -i gre-vc -nn
# Tcpdump on encapsulated GRE packets
sudo tcpdump -i eth0 proto gre -nn
# Delete a tunnel
sudo ip tunnel del gre-vc
Conclusion
GRE on Linux = 3 commands to create, once forever for persistence. The canonical transport for Remote Transit IP when your ISP doesn't filter proto 47. Combined with a clean firewall, MSS clamping, you have a solid base for your BGP session.
Going further: VXLAN if proto 47 blocked, WireGuard for encryption, BIRD 2 / FRR for the BGP session on top.


















