Getting and interpreting routing table information


Posted by Diego Assencio on 2014.12.30 under Linux (Networking)

This post will describe how you can obtain and interpret the routing table of your Linux device. A routing table is a list containing the routes which network packets take based on their destination IP addresses.

To understand this post, you must understanding two things first: the CIDR notation, which is used for specifying IP subnetworks in the format <network-prefix>/<netmask-length>, and the of longest prefix match algorithm. If you don't understand them, take the time to read the linked articles before proceeding. As a side note, our examples will study IPv4 networks, but all concepts we go over apply to IPv6 networks as well.

On Linux, there are two commands which are typically used for obtaining routing table information: route and ip. This post will use the ip command because its output is much easier to interpret than the output of route. To show 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 which 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 by starting with the second line. This line says 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 ínterface) with 192.168.1.100 as the source IP address, which in this case is the IP address assigned to wlan0 via DHCP. The other parts are not so interesting: proto kernel means this entry in the routing table was created by the kernel during autoconfiguration, while scope link means the destination IP addresses within 192.168.1.0/24 are valid only on the device wlan0.

The first line says that the default route for any packet (i.e., the route which is 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 shows this network scheme.

Fig. 1: A local network scheme. The IP addresses belonging to the local network are in 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 very flexible in terms of its input parameters. You can write them only partially and ip will autocomplete them internally. To clarify, all 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 sent through an encrypted tunnel to the VPN server. As an example, let's analyze how OpenVPN does this. Consider what happens if the user of the laptop shown on 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 have all traffic be sent through this virtual interface, where packets are encrypted and sent through the (physical) interface wlan0 to the OpenVPN server. Figure 2 shows a summary of this setup.

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

Below is a possible 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

Going over all the details of this routing table would be tedious, so we will focus on what matters here. Notice the second line: the default route has not changed. However, the first and fourth lines introduce two new routes which completely change the rules of the game: packets with destination addresses matching either 0.0.0.0/1 or 128.0.0.0/1 are now sent through the device tun0 with 192.168.254.9 as the gateway IP address.

The catch here is the fact that 0.0.0.0/1 and 128.0.0.0/1 match packets with destination IP addresses having the first bit equal to 0 and 1 respectively. Together, they match all packets which are not matched by other routes and effectively make the original default route have no effect because of the longest prefix matching rule: the first bit of a packet will always be either 0 or 1, so the default route will never be applied. In other words, OpenVPN creates two routes which together swallow each packet by matching its first bit (except for packets matching other more specific routes, of course); the packet is then sent on the interface tun0. From there, packets are encrypted and then sent to 95.91.22.94 (the OpenVPN server). Not surprisingly, the route specified on the third line causes those packets to be sent through the physical interface wlan0 via the gateway 192.168.1.1.

For the more curious reader, the IP address 192.168.254.9 comes from the fact that in the example above, OpenVPN creates the tun0 interface in point-to-point mode, meaning this interface works as if directly connected to another endpoint: the OpenVPN server. The server creates 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

In our example, this gives us a clear indication 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

Comments

Ram Viswanathan on Jun 07, 2017:
Excellent post! Thanks for sharing. There's so much to learn from your website. Keep up the great work!
Alp on Nov 27, 2018:
Thank you for the post. It helped me understand openvpn routing table. Is the 6th entry in the table necessary because there is only 1 destination address, 192.168.254.9, created by openvpn and it already has a route defined with last entry?
Diego Assencio on Nov 28, 2018:
@Alp: Keep in mind that the routing table does not change the destination IP address of a network packet; it simply defines how the packet must be routed based on the packet's destination IP address (e.g. 1.2.3.4).

Typically, when a device connects to an OpenVPN server, the server assigns it an IP address from a predefined range (192.168.254.0/24 in my case). Other clients connected to the same VPN will also be assigned IP addresses from this same range, so you can access them directly. As an example, 192.168.254.13 may the IP address assigned to another device connected to my VPN, so I can ping it directly. This predefined IP range forms a virtual subnetwork containing the server and all clients connected to it.

The 6th line on the routing table above specifies the route for this virtual subnetwork in my setup: any network packet sent to an IP address within 192.168.254.0/24 must go through the tun0 interface with 192.168.254.9 as the gateway.
Matko Kubko on May 26, 2019:
Diego you are the best! With your unique article I managed to correct ip route table for softether client on android - it was messy. Now it works like charm! I needed to add route direct to server. No idea how openvpn oe android vpn work as they do not have this single route to server??
Diego Assencio on May 26, 2019:
@Matko: Thank you for your comment. I am happy to know that this post was useful to you!

I never used SoftEther VPN, but I find it odd that you had to correct your routing table manually to get your VPN connection working. Could this be due to an error on the server configuration, or perhaps due to a bug on the software itself?
ChihYu on Jun 26, 2019:
Thank you so much for giving such detailed and nice information! I would like to ask how to change routing table so that device connected to OpenVPN can still connect to other devices in LAN? Thanks!
Diego Assencio on Jun 26, 2019:
@ChihYu: By default, OpenVPN will not prevent you from accessing devices in your local network even with a connection to an OpenVPN server established.

Your OpenVPN server may be pushing a DNS server to your device, though, so if you try to access another device in your LAN through its hostname, the hostname-to-IP resolution will fail and your device will seem to be unreachable. If this is what you are doing, try accessing the local device through its IP address instead.
DocWeirdo on Dec 15, 2020:
Hey, thanks for the detailed explanation!

What is the benefit of the last line, except for changing the source address to 192.168.254.10?

In every routing entry, it was specified that packages to 192.168.254.9 should be sent over interface tun0.

What would happen if you left out the last entry?
Diego Assencio on Dec 27, 2020:
@DocWeirdo: OpenVPN requires both endpoints of the connection to have IP addresses assigned to them, but it seems their values have no special purpose except for ICMP errors (and only for the client):

https://unix.stackexchange.com/q/198501

I unfortunately can no longer reproduce the same routes above with OpenVPN (probably because some of the information in the article about the way OpenVPN works is outdated), but my guess is that removing the last entry in the routing table would not break the client-server tunnel.