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 (10.42.1.0/24 and 10.42.2.0/24) 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 240.101.83.2, and the "real" IP of the second router is 251.4.92.217. This isn't very difficult, so let's jump right in.

First, load the kernel module on both routers:

[root@host]# modprobe ipip 

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

[root@host]# ip tunnel add mytun mode ipip remote 251.4.92.217 local 240.101.83.2 ttl 255
[root@host]# ifconfig mytun 10.42.1.1
[root@host]# route add -net 10.42.2.0/24 dev mytun

And on the second network's router (on the 10.42.2.0/24), reciprocate:

[root@host]# ip tunnel add mytun mode ipip remote 240.101.83.2 local 251.4.92.217 ttl 255
[root@host]# ifconfig tun10 10.42.2.1
[root@host]# route add -net 10.42.1.0/24 dev mytun 

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 10.42.2.1, and from the second network router, you should be able to ping 10.42.1.1. Likewise, every machine on the 10.42.1.0/24 network should be able to route to every machine on the 10.42.2.0/24 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:

[root@host]# ifconfig tun10 10.42.1.1 pointopoint 251.4.92.217
[root@host]# route add -net 10.42.2.0/24 dev tun10 

And on the second network's router (on the 10.42.2.0/24):

[root@host]# ifconfig tun10 10.42.2.1 pointopoint 240.101.83.2
[root@host]# route add -net 10.42.1.0/24 dev tun10 

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:

[root@host]# echo "1" > /proc/sys/net/ipv4/ip_forward 

If you need to reach networks beyond 10.42.1.0 and 10.42.2.0, 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:

[root@host]# ifconfig mytun down
[root@host]# ip tunnel del mytun

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 (10.42.1.0/24 and 10.42.2.0/24) 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 240.101.83.2, and the "real" IP of the second router is 251.4.92.217.

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:

[root@host]# modprobe ip_gre

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

[root@host]# ip tunnel add gre0 mode gre remote 251.4.92.217 local 240.101.83.2 ttl 255
[root@host]# ip addr add 10.42.1.254 dev gre0
[root@host]# ip link set gre0 up 

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

[root@host]# ip route add 10.42.2.0/24 dev gre0 

The first network is finished. Now for the second:

[root@host]# ip tunnel add gre0 mode gre remote 240.101.83.2 local 251.4.92.217 ttl 255
[root@host]# ip addr add 10.42.2.254 dev gre0
[root@host]# ip link set gre0 up
[root@host]# ip route add 10.42.1.0/24 dev gre0 

Again, the 10.42.2.254 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 10.42.2.254 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:

[root@host]# ip link set gre0 down
[root@host]# ip tunnel del gre0

1 comment: