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 184.108.40.206 via 192.168.1.1 dev wlan0 220.127.116.11/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 18.104.22.168/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 22.214.171.124/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 126.96.36.199 (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