Tunneling: IPIP and GRE Encapsulation

If you have never worked with IP tunneling before, you might want to take a look at the Advanced Router HOWTO before continuing. Essentially, an IP tunnel is much like a VPN, except that not every IP tunnel involves encryption. A machine that is "tunneled" into another network has a virtual interface configured with an IP address that isn't local, but exists on a remote network. Usually, all (or most) network traffic is routed down this tunnel, so remote clients appear to exist on the network services, or more generally, to connect to any two private networks together using the Internet to carry the tunnel traffic.

If you want to perform simple IP-within-IP tunneling between two machines, you might want to try IPIP. It is probably the simplest tunnel protocol available and will also work with *BSD, Solaris, and even Windows. Note that IPIP is simply a tunneling protocol and does not involve any sort of encryption. It is also only capable of tunneling unicast packets;

Before we rush right into our first tunnel, you'll need a copy of the advanced routing tools (specifically the ip utility). You can get the latest authoritative copy at ftp://ftp.inr.ac.ru/ip-routing/. Be warned, the advanced routing tools aren't especially friendly, but they allow you to manipulate nearly any facet of the Linux networking engine.

Assume that you have two private networks ( and and that these networks both have direct Internet connectively via a Linux router at each network. The "real" IP address of the first network router is, and the "real" IP of the second router is This isn't very difficult, so let's jump right in.

First, load the kernel module on both routers:

Next, on the first network's router (on the network), do the following:

And on the second network's router (on the, reciprocate:

Naturally, you can give the interface a more meaningful name than mytun if you like. From the first network's router, you should be able to ping, and from the second network router, you should be able to ping Likewise, every machine on the network should be able to route to every machine on the network, just as if the Interent weren't even there.

If you're running a Linux 2.2x kernel, you're in luck: here's a shortcut that you can use to avoid having to use the Advanced Router tools package at all. After loading the module, try these commands instead:

And on the second network's router (on the

That's all there is to it.
If you can ping the opposite router but other machines on the network don't seem to be able to pass traffic beyond the router, make sure that both routers are configured to forward packets between interfaces:

If you need to reach networks beyond and, simply add additional route add -net... lines. There is no configuration needed on any of your network hosts, as long as they have a default route to their respective router (which they definitely should, since it is their router, after all).

To bring the tunnel down: On both routers, bring down the interface and delete it, if you like:

The kernel will very politely clean up your routing table for you when the interface goes away.

GRE stands for Generic Routing Encapsulation. Like IPIP tunneling, GRE is an unencrypted encapsulation protocol. The main advantage of using GRE instead of IPIP are that it supports multicast packets and that it will also inter operate with Cisco routers.

Just as with the IPIP tunneling hack, we'll assume that you have two private networks ( and and that these networks both have direct Internet connectivity via a Linux router at each network. The "real" IP address of the first network router is, and the "real" IP of the second router is

Again, as with IPIP tunneling, you will need a copy of the advanced routing tools package (there is no shortcut for GRE tunnels in Linux 2.2 that I've been able to find). Once you have the iproute2 package installed, we'll begin by loading the GRE kernel module on both routers:

On the first network's router, set up a new tunnel device:

Note that you can call the device anything you like; gre0 is just an example. Also, that address can be any available address on the first network, but shouldn't be (the IP already bound to its internal interface). Now, add your network routes via the new tunnel interface:

The first network is finished. Now for the second:

Again, the address can be any available address on the second network. Feel free to add as many ip route add . . . dev gre0 commands as you need.

That's it! You should now be able to pass packets between the two networks as if the Internet didn't exist. A tracroute from the first network should show just a couple of hops to any host in the second network (although you'll probably notice a fair bit of latency when crossing the hop, unless you're really well connected). If you're having trouble, check the notes in the IPIP example and don't panic. Your best friend when debugging new network configurations is probably a packet sniffer like tcpdump or ethereal. Running a tcpdump 'proto \icmp' on both routers while pinging will give you a very detailed overview of what's going on.

To bring the tunnel down, run this on both routers:


  1. how configure these tunnels UP on boot time.

  2. how do u make it persisitanat after reboot ?

    1. That would depend on your Linux distribution, but don't be afraid to script it and run it from SystemD earlier in the boot process. Adding it in rc.local might not be ideal considering that it will run last after other services that might depend on the networking.

  3. Thanks man, very well written article !

  4. Thanks for this post! Clearly explained and easy to follow.

  5. Thanks for the post. So if I want to configure GRE between 4 Linux hosts, how can I do this? I see samples of 2 hosts only. Trying to stand up Oracle RAC on AWS. AWS does not support multicast unfortunately. Thanks in advance.