In this post we’ll use iproute2 to create tunnels between two unix hosts. This will be the simplest form of an IP-in-IP tunnel.
How the Tunnels will work
In this example we have two Unix hosts with IP addresses 10.255.254.96 and 10.255.254.196 on a 10.255.254.0/24 network and a gateway address of 10.255.254.2. These two hosts are on the same network. For this tunnel example we are going to add dummy interfaces to each of our hosts and assign addresses 192.168.2.111 and 192.168.2.222 addresses to each of them respectively. Once the tunnels are up we will be able to send a ping from the first tunnel to the second tunnel as if the hosts are on the same network. This is known as encapsulation, since inside an IPv4 packet with a source of 10.255.254.96 and destination of 10.255.254.196 we have another IPv4 packet encapsulated inside with a source of 192.168.2.111 and destination of 192.168.2.222.
iproute2 and the dummy kernel module
For this we’ll need iproute2. As long as your linux distribution is fairly modern you should have iproute2. Type ip and you should see something like the following.
Check out iproute2, it is the new way of doing things. The net-tools are being phased out. The net-tools that are ifconfig, route, arp, netstat, iptunnel, nameif, and ipmaddr are all old school and replaced by iproute2.
Now ensure you have the dummy module loaded into the kernel. This is probably the largest source of frustration if not found by lsmod.
Checking if the dummy network kernel module is loaded
The grep found it. That’s good. Now if you don’t have it see the following section.
To insert the module do the following. Note, you could have the module but the uname -r output and the directory in /lib/modules don’t match. Perhaps you need to restart the box after the kernel has been compiled/upgraded? Anyways, here is how to find and load the dummy network module into the kernel.
Inserting the dummy network kernel module if not loaded
The Network Before Tunnels
Here is a picture of the network before the tunnels are added. It’s really simple it shows eth0 on a 10.255.254.0/24 network with an address of 10.255.254.96 and the gateway being the default route with address of 10.25.254.2.
Routing table before tunnels are added
Creating a Tunnel on the First Host
Here we will create a dummy interface, add an address to that interface, create a tunnel from the dummy interface to our network’s gateway. We’ll then put the tunnel up, and add a route from it to our eth0 interface. Then we’ll show the addresses on the box and the new routing table.
Above, you can see for some reason the tunnels have UNKNOWN state. I am not sure why. Also, note that the dummy0 interface has 2 addresses. Yes, interfaces can have multiple addresses. We just don’t use the random address it gives us. It’s also important to know the type of tunnel is ipip which is the most simple form. Later, I hope to get into the more modern and flexible types of tunnels for various use cases. It’s also important to see the mtu is 1480 rather than 1500 as the IP-in-IP protocol takes off 20 bits.
Creating the tunnel on the Second Host
Now we’ll do nearly the same thing on the second host with slight variations on ip addresses. Hopefully it’s obvious most of the needs to be done on both hosts for bi-directional communication.
Note on the Dummy Interfaces
Firstly, note that the dummy network device in Unix “A dummy device drops all packets sent to it.”. So this shouldn’t be used for anything useful. It is truly for example purposes.
When we ran the command ip link add dummy0 type dummy dummy ip addresses were assigned to the dummy0 interface. Namely, 169.254.230.254 and 169.254.178.151 respectively. Instead of the 192.168.2.111 and 192.168.2.222 addresses we used we could have used these addresses. This in fact would have made things more simply because routes were also added. However, by creating the addresses 192.168.2.111 and 192.168.2.222 don’t rely on the randomness. This can be advantageous in a number of scenarios.
Let’s do some pinging!
Ok now we need to ping and traceroute to make sure what we have is working:
Ping/Traceroute from Unix Host 1 to Unix Host 2
I’ll spare you from the opposite side of the tunnel, but it’s the same.
The New Neighbor List
We can see from the neighbor list (arp table) that mac addresses from our hosts are seen. Look closely as they match the mac address in each of the links on the interfaces. Note, if we had not ping from each host there would be no arp entries since there would be no reason to find the mac address of each host.
Neighbors on Host 1
Neighbors on Host 2
Note, the address 10.255.254.91 is the host that I’m ssh’d in from.
Where to go from here?
Wow! There is a lot to these tunnels and this is just scratching the surface. Next, we’ll look at different types of tunnels (gre, sit, l2tp, vxlan), and IPSec VPN.