The ip route command is your primary tool for interacting with the Linux kernel’s routing tables, the intricate maps that direct network traffic from your machine to its destination.

Let’s see it in action. Imagine you have a server with two network interfaces, eth0 connected to your local network (192.168.1.0/24) and eth1 connected to a separate subnet (10.0.0.0/24).

# Display the main routing table
ip route show

# Expected output might look something like this:
# default via 192.168.1.1 dev eth0
# 10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.10
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

In this output:

  • default via 192.168.1.1 dev eth0: This is the default route. If the kernel doesn’t find a more specific route for a destination, it sends the traffic to 192.168.1.1 (your router) via the eth0 interface.
  • 10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.10: This route says that for any destination within the 10.0.0.0/24 network, the traffic should go directly out the eth1 interface. The src 10.0.0.10 indicates the source IP address that will be used for packets destined for this network.
  • 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10: Similarly, this route handles traffic for your local 192.168.1.0/24 network, using eth0.

The system uses these routes to make forwarding decisions. When a packet arrives or is about to be sent, the kernel looks at the destination IP address and performs a "longest prefix match" against the entries in the routing table. The entry with the most specific matching network mask wins.

You can add, delete, or modify routes. For example, to add a route for a new subnet 172.16.0.0/16 that should be reached via a gateway 192.168.1.254 on eth0:

sudo ip route add 172.16.0.0/16 via 192.168.1.254 dev eth0

To delete that route:

sudo ip route del 172.16.0.0/16 via 192.168.1.254 dev eth0

You can also add "blackhole" routes, which silently discard packets, useful for blocking traffic:

sudo ip route add unreachable 1.2.3.4/32

This adds a route for the specific IP 1.2.3.4 and marks it as unreachable, meaning packets to that IP will be dropped without any ICMP error being sent back.

Linux systems can have multiple routing tables, often used for policy-based routing. The ip route show table 100 command, for instance, would display the contents of routing table number 100. Rules, managed by ip rule, determine which routing table is consulted for a given packet. A common use case is directing traffic from a specific source IP address to a different routing table.

The scope field in ip route show is critical. scope link means the destination is directly reachable on the local network segment attached to the specified interface. scope global (often implied for default routes) means the route is available for all routing decisions. scope host typically applies to loopback addresses.

When you configure network interfaces with tools like systemd-networkd or NetworkManager, they often manage these ip route commands for you by reading configuration files. For example, a systemd-networkd .network file might contain an [Route] section that translates into ip route commands upon activation.

The output of ip route show might also include proto information, like proto kernel for routes automatically added by the kernel when an interface comes up with an IP address, or proto static for routes added manually or by configuration tools.

Understanding how ip route interacts with ip rule and the kernel’s forwarding logic is key to complex network setups, including VPNs, multi-homed servers, and advanced firewalling.

The ip route command uses a specific internal representation of routes that can sometimes be less intuitive than the high-level commands suggest; for instance, routes with scope link are not strictly "routes" in the sense of needing a gateway, but rather assertions that a network is directly attached to an interface.

Want structured learning?

Take the full Computer Networking course →