Obtaining and interpreting routing tables on Linux

Posted on 2014-12-30

This post describes how to obtain and interpret the routing table of your system on Linux. A routing table is a set of rules that specify how network packets are routed based on their destination IP addresses.

To understand this post, you should be familiar with two concepts: the CIDR notation, which is used to specify IP subnetworks in the format <network-prefix>/<netmask-length>, and the longest prefix match algorithm. If you're not familiar with them, please take the time to read the linked articles before proceeding. While our examples will focus on IPv4 networks, all the concepts we go over apply to IPv6 networks as well.

On Linux, there are two commands that are typically used for obtaining routing table information: route and ip. This post will use the ip command because its output is easier to interpret than the output of route. To display the routing table of your system with the ip command, open a terminal and run:

ip route show

The output will depend on your network configuration. Here is an example that is very common for devices connected to a wireless router in home networks:

default via 192.168.1.1 dev wlan0
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.100

Let's interpret the output above, starting with the second line. This line states that packets sent to any IP address within the subnetwork 192.168.1.0/24 must be sent through the network interface wlan0 (a wireless network interface) with 192.168.1.100 as the source IP address, which in this case is the IP address assigned to wlan0 via DHCP. In addition, proto kernel shows that this entry in the routing table was created by the kernel during autoconfiguration, while scope link expresses that the destination IP addresses within 192.168.1.0/24 are valid only on the device wlan0.

The first line states that the default route for any packet (i.e., the route taken by a packet when no other route applies) is through the network device wlan0 via the default gateway (the router), which has the IP address 192.168.1.1. Figure 1 illustrates this network scheme.

Local network
Fig. 1:
A local network scheme. The IP addresses belonging to the local network fall within the range 192.168.1.0/24. The external IP address of the router (the one visible to the Internet) is omitted.

The ip command is highly flexible regarding its input parameters. You can enter them partially, and ip will autocomplete them internally. To clarify, all of the commands below are equivalent:

ip r s
ip r show
ip ro sh
ip route show

A complex example: VPN routing

When you connect to a virtual private network (VPN), your network traffic is routed through an encrypted tunnel to the VPN server. As an example, let's analyze how OpenVPN accomplishes this. Consider what happens when the user of the laptop shown in figure 1 connects to an OpenVPN server. First, a virtual network interface (usually named tun0) is created. Routes are then added to the routing table to direct all traffic through this virtual interface, where packets are encrypted and sent via the (physical) interface wlan0 to the OpenVPN server. Figure 2 illustrates a summary of this setup.

OpenVPN scheme
Fig. 2:
An OpenVPN network scheme. The arrow from the router to the OpenVPN server indicates that the encrypted packet may travel through the Internet before reaching the server, where it's decrypted and then sent to its final destination.

Below is a potential routing table for the OpenVPN client after it connects to the OpenVPN server:

0.0.0.0/1 via 192.168.254.9 dev tun0
default via 192.168.1.1 dev wlan0
95.91.22.94 via 192.168.1.1 dev wlan0
128.0.0.0/1 via 192.168.254.9 dev tun0
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.100
192.168.254.0/24 via 192.168.254.9 dev tun0
192.168.254.9 dev tun0  proto kernel  scope link  src 192.168.254.10

Covering all the details of this routing table would be tedious, so we will concentrate on the most relevant aspects. The second and fifth lines are identical to those in the routing table shown earlier, meaning the default route and the route for the local network remain unchanged. On the other hand, the first and fourth lines introduce two new routes that significantly alter the routing rules: packets with destination addresses matching either 0.0.0.0/1 or 128.0.0.0/1 are now routed through tun0, with 192.168.254.9 as the gateway IP address.

The catch here is that 0.0.0.0/1 and 128.0.0.0/1 match packets with destination IP addresses where the first bit equals 0 and 1 respectively. Combined, they match all packets not matched by other routes. The fifth line will still apply for all IP addresses within the range 192.168.1.0/24 (so communicating with devices in the local network will still be possible), but since the first bit of a packet will always be either 0 or 1, the default route will never be applied. In other words, OpenVPN creates two routes that collectively match every packet that is not addressed to a device in the local network; these packets are then routed to the interface tun0. From there, packets are encrypted and sent to 95.91.22.94 (the OpenVPN server). Finally, the route specified on the third line directs the packets to be sent out through the physical interface wlan0 via the gateway 192.168.1.1.

The last two lines are also important. They exist due to the fact that OpenVPN creates the virtual tun0 interface in point-to-point mode, meaning this interface functions as if directly connected to another endpoint: the OpenVPN server. The server establishes a virtual local network 192.168.254.0/24 and assigns IP addresses from this pool to each endpoint of the connection. As shown on the last line, the IP address assigned to the client is 192.168.254.10, with 192.168.254.9 being the IP address of the server endpoint. This can be seen more clearly by running:

ip addr show dev tun0

The output provides a clear demonstration of the point-to-point connection mentioned in the previous paragraph:

21: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/none
    inet 192.168.254.10 peer 192.168.254.9/32 scope global tun0
      valid_lft forever preferred_lft forever