Routing
Routing is where Linux decides where an IP packet should go next. An interface can be up and have a perfectly valid IP address, but that still doesn’t tell Linux how to reach every other network. The routing table provides that missing information.
In this lesson, you’ll use ip route to inspect routing decisions and then build a simple Linux router between two networks. The goal isn’t to turn Linux into a production router; it is to make the routing model concrete enough that you can reason about it when administering or debugging a real system.
What Is Routing?
Imagine a Linux machine with this configuration:
IP address: 192.168.1.20/24
Default gateway: 192.168.1.1It can communicate directly with machines on its local network, such as 192.168.1.50. But what happens when an application wants to send a packet to 8.8.8.8?
Linux needs to determine where that packet should go. It looks at the destination IP address and consults its routing table. The selected route tells the kernel which interface to use and, when necessary, which next-hop router should receive the packet.
The simplified decision is:
Destination IP
│
▼
Routing table
│
├── Local network?
│ │
│ └── Send directly
│
└── Other network?
│
└── Send to next-hop routerRouting therefore answers a very specific question:
Given this destination IP, where should Linux send the packet next?
The Routing Table
You can inspect the routing table with:
ip routeA typical machine might show:
default via 192.168.1.1 dev enp3s0
192.168.1.0/24 dev enp3s0 proto kernel scope link src 192.168.1.20Don’t treat this as a collection of fields to memorize. Read it as two routing rules.
The first says:
default via 192.168.1.1 dev enp3s0For destinations that don’t match a more specific route, send the packet to 192.168.1.1 through enp3s0.
The second says:
192.168.1.0/24 dev enp3s0Destinations belonging to the local 192.168.1.0/24 network are directly reachable through enp3s0; there is no router required for the first hop.
This gives us a useful mental model:
192.168.1.50
│
│ matches 192.168.1.0/24
▼
enp3s0
│
direct
8.8.8.8
│
│ does not match local route
▼
default route
│
▼
192.168.1.1
│
routerWhat Is A Default Route?
A default route is the route Linux uses when no more specific route matches the destination.
It is commonly written as:
default via 192.168.1.1 dev enp3s0The equivalent network notation is:
0.0.0.0/0The /0 means that no destination bits are fixed, so every IPv4 destination can potentially match it. Because more specific routes take precedence, the default route is effectively the fallback.
For example, suppose the table contains:
10.10.0.0/16 dev enp2s0
192.168.1.0/24 dev enp3s0
default via 192.168.1.1 dev enp3s0Then:
10.10.5.20
→ 10.10.0.0/16
→ enp2s0
192.168.1.50
→ 192.168.1.0/24
→ enp3s0
8.8.8.8
→ no more-specific match
→ default route
→ 192.168.1.1This is the basic mechanism behind routing on a Linux host.
More Specific Routes Win
A machine can have several routes that technically match the same destination. Linux therefore needs a way to decide which one is the better match.
The important rule is:
The most specific matching route wins.
Consider:
10.0.0.0/8
10.10.0.0/16
10.10.20.0/24
defaultAll four can potentially match some destination beginning with 10.10.20, but they represent different levels of specificity.
For:
10.10.20.50the /24 route is more specific than /16, which is more specific than /8, while the default route is the least specific possible route.
You can visualize it as:
default /0
│
└── 10.0.0.0/8
│
└── 10.10.0.0/16
│
└── 10.10.20.0/24This principle becomes very important when a machine has multiple networks, VPNs, containers, or other virtual networking components.
Ask Linux Which Route It Would Use
You don’t always have to inspect the entire routing table manually.
Linux can tell you which route it would select for a destination:
ip route get 8.8.8.8You might see something similar to:
8.8.8.8 via 192.168.1.1 dev enp3s0 src 192.168.1.20This is extremely useful when troubleshooting because it answers a practical question:
“If this machine sends a packet to that destination right now, what path will Linux choose?”
For example:
ip route get 192.168.1.50might return:
192.168.1.50 dev enp3s0 src 192.168.1.20Notice that there is no gateway. Linux considers the destination directly reachable on the local network.
Compare that with:
ip route get 8.8.8.8which might use:
via 192.168.1.1The difference between these two outputs is routing in action.
Directly Connected Networks
When you assign:
192.168.1.20/24to an interface, Linux knows that the 192.168.1.0/24 network is directly connected to that interface.
That is why a route similar to this normally appears:
192.168.1.0/24 dev enp3s0 proto kernel scope link src 192.168.1.20The proto kernel part indicates that this route was automatically created from the interface’s addressing information.
You didn’t have to manually type:
ip route add 192.168.1.0/24 dev enp3s0Linux already knew about the directly connected network because you configured the address and prefix on the interface.
This gives us an important relationship:
IP address + prefix
│
▼
directly connected network
│
▼
routing tableWhat Is A Next Hop?
Suppose your machine is:
192.168.1.20and the destination is:
8.8.8.8Your machine cannot normally place an Internet-bound packet directly onto the local Ethernet network and expect 8.8.8.8 to receive it. Instead, it sends the packet to a router on its local network, commonly called the default gateway.
For example:
Linux host
192.168.1.20
│
│ packet for 8.8.8.8
▼
192.168.1.1
gateway/router
│
▼
Internet
│
▼
8.8.8.8The router at 192.168.1.1 is the next hop from the Linux machine’s point of view.
The Linux host doesn’t need to know the entire path to 8.8.8.8. It only needs to know where to send the packet next.
The router then makes its own routing decision.
Routing Happens At Every Router
This is an important distinction.
Suppose a packet travels:
Host A
│
▼
Router 1
│
▼
Router 2
│
▼
Router 3
│
▼
Host BHost A does not normally calculate the entire path itself.
It makes a routing decision for the next hop.
Router 1 receives the packet and makes another routing decision.
Router 2 makes another.
Eventually, one of those routing decisions leads the packet to the destination network.
So routing is not one giant decision made by the original machine. It is a sequence of local forwarding decisions.
Source
│
│ routing decision
▼
Next hop
│
│ routing decision
▼
Next hop
│
│ routing decision
▼
DestinationLinux Can Be A Router Too
Linux isn’t limited to being an endpoint.
A Linux machine can have interfaces connected to different networks and forward packets between them.
Consider:
Network A Network B
10.10.1.0/24 10.10.2.0/24
Host A Host B
10.10.1.10 10.10.2.10
│ │
│ │
10.10.1.1 10.10.2.1
│ │
└──────── Linux Router ───────────┘The Linux router has two interfaces:
enp1s0 → 10.10.1.1/24
enp2s0 → 10.10.2.1/24From the router’s perspective, both networks are directly connected:
10.10.1.0/24 dev enp1s0
10.10.2.0/24 dev enp2s0If a packet arrives from Host A destined for 10.10.2.10, Linux can determine that the destination belongs to the second network and forward the packet through enp2s0.
But there is one additional requirement.
What Is IP Forwarding?
Normally, a Linux host is an endpoint. It receives packets intended for itself and sends packets generated by itself.
A router has an additional job: it receives a packet that is not addressed to itself and forwards it toward another network.
Linux controls this behavior with IPv4 forwarding.
You can check the current setting with:
sysctl net.ipv4.ip_forwardA result of:
net.ipv4.ip_forward = 0means forwarding is disabled.
A result of:
net.ipv4.ip_forward = 1means IPv4 forwarding is enabled.
You can think of it as:
ip_forward = 0
packet arrives
↓
packet is not for this host
↓
do not forward it
ip_forward = 1
packet arrives
↓
packet is not for this host
↓
consult routing table
↓
forward through appropriate interfaceThis is the same Linux networking stack we’ve been discussing, but now the machine is participating as a router rather than only as an endpoint.
For this course, that’s enough to understand the mechanism. We won’t turn this into a router configuration guide.
A Simple Linux Router Example
Let’s make the concept concrete with three machines:
Linux Router
┌────────────────────┐
│ │
│ enp1s0 enp2s0 │
│ 10.10.1.1 │
│ 10.10.2.1 │
└──────┬───────┬─────┘
│ │
Network A Network B
10.10.1.0 10.10.2.0
│ │
Host A Host B
10.10.1.10 10.10.2.10Host A has:
IP: 10.10.1.10/24
Gateway: 10.10.1.1Host B has:
IP: 10.10.2.10/24
Gateway: 10.10.2.1The router has:
enp1s0 → 10.10.1.1/24
enp2s0 → 10.10.2.1/24The router’s routing table will contain directly connected routes similar to:
10.10.1.0/24 dev enp1s0
10.10.2.0/24 dev enp2s0Now Host A sends a packet to:
10.10.2.10Host A knows that 10.10.2.10 is not on its own 10.10.1.0/24 network, so it sends the packet to its gateway:
10.10.1.1The Linux router receives it.
Because forwarding is enabled, Linux examines the destination:
10.10.2.10The routing table says:
10.10.2.0/24 dev enp2s0so the packet is forwarded through enp2s0.
The path is therefore:
Host A
10.10.1.10
│
│ gateway 10.10.1.1
▼
Linux Router
│
│ route 10.10.2.0/24 → enp2s0
▼
Host B
10.10.2.10This is the basic behavior of a Linux router.
Why Does The Destination Network Matter?
A common beginner mistake is to think of routing as:
“Find the interface for this IP address.”
The real process is closer to:
“Find the best route that matches this destination.”
For example:
Destination: 10.10.2.10
Routing table:
10.10.1.0/24 → enp1s0
10.10.2.0/24 → enp2s0
default → enp1s0The destination matches:
10.10.2.0/24so Linux chooses enp2s0.
The default route is not used because a more specific route exists.
This is why understanding prefixes is important. Routing and IP addressing are tightly connected.
Looking At A Routing Table In Practice
On your own Debian system, start with:
ip routeThen ask Linux about a few destinations:
ip route get 127.0.0.1
ip route get 8.8.8.8If your machine has a normal network connection, the second command will usually show a route through your default gateway.
You can also inspect the route to a host on your local network if you know one:
ip route get 192.168.1.1Replace the example address with your own gateway if necessary.
The point of this exercise isn’t to produce identical output. Your routing table depends on your machine, network, VPNs, virtual interfaces, and configuration.
Instead, ask three questions:
- What is the default route?
- Which interface does it use?
- What happens when the destination is on a directly connected network?
Adding A Temporary Route
Linux can also add routes manually.
For example:
sudo ip route add 10.20.0.0/16 via 192.168.1.1This tells Linux:
To reach
10.20.0.0/16, send packets to the next-hop router192.168.1.1.
You can verify it with:
ip routeand:
ip route get 10.20.5.10You can remove the route with:
sudo ip route del 10.20.0.0/16 via 192.168.1.1Important
These changes are normally runtime configuration. They are not automatically a permanent network configuration for the next boot.
That’s an important operational distinction:
ip route add
↓
change the running system
Persistent network configuration
↓
depends on the system's network management/configuration methodFor now, we’re using ip to understand and manipulate the kernel’s current networking state. We don’t need to turn this into a persistent network configuration lesson.
Warning
Be careful when changing routes on a remote machine. Removing or replacing the route you are using for your own SSH or management connection can immediately make the machine unreachable from where you are.
Routing And The Default Gateway
At this point, the relationship between an IP address, interface, and gateway should be clear.
Consider:
Linux host
192.168.1.20/24
│
│ enp3s0
▼
Local network
192.168.1.0/24
│
▼
Gateway
192.168.1.1
│
▼
Other networksThe IP address and prefix tell Linux what is local.
The routing table tells Linux what to do with destinations beyond that local network.
The default gateway is simply the next-hop router used by the default route.
It is not a special kind of IP address. It is just the next-hop address selected by a route.
Routing And The Network Interface
We can now connect the previous lesson to this one (fairly simplified view):
flowchart LR
A["Application"] --> S["Socket"]
S --> K["Linux Kernel"]
K --> IP["Destination IP"]
IP --> R["Routing Table"]
R --> NH["Next Hop"]
NH --> I["Network Interface"]
I --> N["Network"]
The routing table sits between the destination and the interface.
That’s why having an interface with a valid IP address doesn’t guarantee connectivity to every destination.
You can have:
Interface: UP
IP address: correctwhile still having:
No route to destinationor:
Wrong route to destinationRouting is its own layer of configuration and troubleshooting.
A Useful Troubleshooting Pattern
When a machine cannot reach a destination, one of the first questions to ask is:
“What route does Linux think it should use?”
Run:
ip route get <destination>For example:
ip route get 8.8.8.8This can immediately reveal problems such as:
- no matching route
- an unexpected interface
- an unexpected gateway
- traffic being sent through a VPN
- traffic being sent through a different network interface than expected
That makes ip route get one of the most useful commands in this topic.
What You Should Remember
Routing is the process of selecting where an IP packet should go next.
The key pieces are:
IP address
↓
identifies the local endpoint and network
↓
Routing table
↓
selects the best matching route
↓
Next hop / interface
↓
packet leaves through the selected pathThe commands worth remembering from this lesson are:
ip routeto inspect the routing table,
ip route get <destination>to ask Linux which route it would actually choose, and:
sudo ip route add ...
sudo ip route del ...to make temporary runtime route changes.
The most important concept is not the syntax. It is the decision Linux is making:
For this destination IP, what is the most specific route I have, and where does that route send the packet?
What’s Next
A routing table can tell Linux where to send a packet once it knows the destination IP. But users and applications usually don’t start with an IP address—they start with a name such as example.com.
Next we’ll look at DNS Resolution: how Linux turns names into addresses, where /etc/hosts and resolver configuration fit, and why DNS problems can look like general network failures.