gretun: GRE Tunnel Management CLI
Simple CLI for creating and managing GRE tunnels on Linux. Built for cloud VPC interconnection.

What It Does
GRE (Generic Routing Encapsulation) tunnels connect networks over the internet. You have two sites with private IP ranges. GRE wraps their traffic in IP packets, routes it across the public internet, and unwraps it at the destination.
gretun is a CLI for managing these tunnels on Linux. Create, list, probe, delete—without remembering ip tunnel syntax or netlink flags.
Why did I pick GRE over others? It’s simple, widely supported, and kernel-native. No userspace daemon, no key exchange, no handshake latency. For trusted networks (VPCs you control), the simplicity is a big factor.
How GRE Works
GRE encapsulates packets:
Original: [Inner IP Header] [Payload]
Tunneled: [Outer IP Header] [GRE Header] [Inner IP Header] [Payload]
The outer IP header routes the packet across the internet using public IPs. The GRE header marks it as encapsulated (IP protocol 47). The inner packet travels unchanged.
At the remote endpoint, the kernel strips outer headers and delivers the inner packet to the tunnel interface. Applications see a normal network interface with private IPs.
CLI Design
Four commands cover the lifecycle:
create: Set up a tunnel. Specify local/remote endpoints (public IPs), tunnel IP (private), optional GRE key.
gretun create --name tun0 --local 10.0.0.1 --remote 10.0.0.2 \
--tunnel-ip 192.168.1.1/30
list: Show all GRE tunnels with their configuration. JSON output for scripting.
probe: ICMP health check to the remote tunnel IP. Configurable thresholds for alerting.
delete: Tear down the tunnel and clean up routes.
The commands mirror the mental model: create a tunnel, verify it works, delete when done.
Netlink Integration
Linux network configuration happens through netlink sockets. The vishvananda/netlink library provides a Go interface.
Creating a tunnel:
- Create a GRE link with local/remote addresses
- Add the tunnel IP address to the interface
- Bring the interface up
- (Optional) Add routes for remote subnets
The library handles netlink message serialization. Error handling required care—partial failures can leave interfaces in broken states. The CLI rolls back on errors.
Challenges & Lessons
Testing without multiple machines was the main hurdle. Network namespaces simulate separate hosts on one box. Two namespaces with veth pairs can test the full tunnel flow locally.
Privilege management: netlink requires CAP_NET_ADMIN. The CLI checks permissions early and fails with a clear message rather than cryptic netlink errors.
MTU issues surprised me. GRE adds 24 bytes of overhead. If the outer path has 1500 MTU, inner packets larger than 1476 bytes get fragmented or dropped. The CLI sets tunnel MTU automatically. This took me awhile to figure out. I learned that MTU is a common source of network issues.
Use Cases
Site-to-site VPN: Connect on-prem to cloud VPC. GRE tunnels are simpler than IPsec for trusted networks.
Multi-cloud networking: Link AWS VPC to GCP VPC. Each cloud has public IPs; GRE bridges the private ranges.
Lab environments: Create isolated networks for testing. Spin up tunnels, run experiments, tear down.
What I’d Do Differently
IPv6 support is the gap here, I was fine with skipping it for the current iteration. Go-Hunter is IPv4-only. Adding IPv6 outer headers and inner addresses would double the use cases so it will be added next.
Health checks could be smarter. Current probe is ICMP-based. Checking actual application connectivity (TCP handshake, HTTP request) would catch more failure modes.