LFCE 15 ๐ง Static Routes โ Configuration
Configuration is where static routing theory becomes kernel state. The previous chapter established why static routes exist and how the kernel selects them by longest prefix match. This chapter is the operational counterpart: the exact commands to add, verify, replace, and remove routes, the flags that handle gateways outside connected subnets, and the persistence mechanisms that survive a reboot. Every command here modifies the running kernel immediately, but none of them persist by default. The gap between a route that works in a lab session and a route that works after a production restart is the central concern of this chapter.
Key point: ip route add creates a route in the running kernel only. Reboot removes it. Persistence requires the distribution’s network managerโNetplan on Ubuntu, nmcli on RHEL and NetworkManager-managed systems, or systemd-networkdโand the persistent configuration must be verified separately from the running configuration.
Why configuration is a separate discipline from concepts
The immediate-versus-persistent problem.
The ip route add command is satisfying because it works instantly. The route appears in ip route show, and ip route get confirms the kernel selects it. This immediate feedback creates a false sense of completion. The route exists in volatile kernel memory, not in any configuration file. A reboot, a network service restart, or a systemctl restart NetworkManager can erase it without warning. Production configuration requires two separate operations: add the route to the running kernel for immediate effect, and write it to the persistent configuration for survival. The two must produce the same result, and the persistent configuration must be tested by rebooting or restarting the network service, not by inspecting the file.
The gateway reachability problem.
The kernel validates that a gateway is reachable before accepting a route through it. If the gateway address does not fall within a directly connected subnet, ip route add fails with “Nexthop has invalid gateway” or “Network is unreachable.” This validation prevents routes that point to nonexistent gateways, but it blocks legitimate configurations: VPN tunnels where the gateway is inside the tunnel, dummy interfaces used for testing, and point-to-point links where the neighbor address is outside the configured subnet. The onlink flag overrides the validation, telling the kernel to trust the administrator’s assertion that the gateway is reachable through the specified interface .
The verification problem.
A route in the table is not proof that traffic flows. The kernel might select a different route due to a longer prefix, the gateway might be unreachable at layer 2, or a firewall might drop the forwarded packets. Configuration is complete only when ip route get shows the intended route and an actual packetโa ping or tracerouteโconfirms delivery. The commands in this chapter modify state; the verification commands confirm that the modification achieved its purpose.
a. Adding and verifying routes
The ip route add command is the primary tool for creating static routes. It accepts a destination prefix, a gateway (via), an outgoing interface (dev), or both .
# Add a route to a remote network through a gateway
ip route add 192.168.2.0/24 via 10.0.0.1
# Add a route through an interface without a gateway
ip route add 192.168.2.0/24 dev eth0
# Add a route specifying both gateway and interface
ip route add 192.168.2.0/24 via 10.0.0.1 dev eth0
# Add a host route for a single destination
ip route add 10.10.10.1/32 via 192.168.1.1
The via keyword is used when the destination is not directly connected and must be reached through a next-hop router. The dev keyword specifies the interface. When both are present, the kernel sends the packet out the named interface to the gateway’s MAC address. When only dev is specified, the kernel treats the destination as directly reachable on that link, which is appropriate for point-to-point links .
# Verify the route was added
ip route show 192.168.2.0/24
# Output: 192.168.2.0/24 via 10.0.0.1 dev eth0
# Ask the kernel which route it will use for a specific destination
ip route get 192.168.2.100
# Output: 192.168.2.100 via 10.0.0.1 dev eth0 src 10.0.0.2 uid 0
ip route get is the definitive verification. It shows the selected route, the outgoing interface, and the source address the kernel will use. A route that exists in the table but is not selected for the intended destination is not functioning as configured .
b. Replacing, deleting, and handling special cases
The add command fails if an identical route already exists. The replace command creates the route if absent and overwrites it if present, avoiding the “File exists” error .
# Replace an existing route without deleting it first
ip route replace 192.168.2.0/24 via 10.0.0.2
# Delete a route
ip route del 192.168.2.0/24
# Delete a route with a specific gateway when multiple routes share the prefix
ip route del 192.168.2.0/24 via 10.0.0.1
The onlink flag is required when the gateway is not reachable through a connected route. Without it, the kernel rejects the route .
# Add a route where the gateway is only reachable through the interface
# The onlink flag bypasses the gateway reachability check
ip route add 203.0.113.0/24 via 198.51.100.254 dev lfcsroute0 onlink
This configuration is common in lab environments using dummy interfaces, in VPN scenarios where the gateway is inside the tunnel, and in point-to-point links where the neighbor address does not fall within the configured subnet. The kernel normally validates that the gateway is on a directly connected subnet; onlink tells it to accept the administrator’s assertion that the gateway is reachable through the interface.
The metric field influences route selection when multiple routes match the same prefix. A lower metric is preferred. NetworkManager assigns default metrics based on connection type: Ethernet is preferred over Wi-Fi, which is preferred over WWAN .
c. Persistence across reboots
Routes added with ip route are lost on reboot. Persistence depends on the distribution’s network management system. The three most common mechanisms are Netplan on Ubuntu, nmcli on RHEL and NetworkManager-managed systems, and systemd-networkd.
# Ubuntu / Netplan: edit or create a YAML file under /etc/netplan/
# network:
# version: 2
# ethernets:
# eth0:
# routes:
# - to: 192.168.2.0/24
# via: 10.0.0.1
# Apply with:
netplan apply
The Netplan configuration nests the route under the interface definition. The to field is the destination prefix, and via is the gateway. The netplan apply command applies the configuration to the running system; the configuration is automatically applied at boot by the backend network manager .
# RHEL / NetworkManager: add the route to the connection profile
nmcli connection modify "eth0" +ipv4.routes "192.168.2.0/24 10.0.0.1"
# Reactivate the connection to apply the change
nmcli connection up "eth0"
The + modifier appends the route to the existing list. Without it, ipv4.routes replaces the entire route list . The connection must be reactivated for the change to take effect on the running interface. The connection profile IDโnot necessarily the interface nameโis the target of the modify command .
# systemd-networkd: add a [Route] section to the .network file
# [Route]
# Destination=192.168.2.0/24
# Gateway=10.0.0.1
# Restart the service to apply
systemctl restart systemd-networkd
For any persistence method, the running configuration and the persistent configuration must be verified independently. ip route show confirms the running state. The persistent state is verified by rebooting or restarting the network service and checking that the route reappears.
Complete Example Session
# ============================================
# PART 1: INSPECT THE CURRENT ROUTING TABLE
# ============================================
# Before adding a route, understand the existing paths
ip route show
# Output shows the default route and connected networks
# ============================================
# PART 2: CHECK THE CURRENT PATH FOR A DESTINATION
# ============================================
ip route get 203.0.113.10
# Before the static route, this follows the default route
# ============================================
# PART 3: CREATE A DUMMY INTERFACE FOR TESTING
# ============================================
# A dummy interface provides a safe local interface without altering the real network path
ip link add lfcsroute0 type dummy
ip addr add 198.51.100.1/24 dev lfcsroute0
ip link set lfcsroute0 up
ip -brief address show lfcsroute0
# Output: lfcsroute0 UP 198.51.100.1/24
# ============================================
# PART 4: ADD THE STATIC ROUTE WITH ONLINK
# ============================================
# The gateway is in the dummy interface's subnet but no real neighbor exists
# The onlink flag tells the kernel to accept the gateway anyway
ip route add 203.0.113.0/24 via 198.51.100.254 dev lfcsroute0 onlink
# ============================================
# PART 5: VERIFY THE ROUTE EXISTS
# ============================================
ip route show 203.0.113.0/24
# Output: 203.0.113.0/24 via 198.51.100.254 dev lfcsroute0
# ============================================
# PART 6: VERIFY THE KERNEL SELECTS THE ROUTE
# ============================================
ip route get 203.0.113.10
# Output: 203.0.113.10 via 198.51.100.254 dev lfcsroute0
# The static route is selected instead of the default route
# ============================================
# PART 7: TEST A DESTINATION OUTSIDE THE ROUTE
# ============================================
ip route get 8.8.8.8
# Output: 8.8.8.8 via <default-gateway> dev eth0
# The default route is still used for other destinations
# ============================================
# PART 8: REPLACE THE ROUTE
# ============================================
# Change the gateway without deleting and re-adding
ip route replace 203.0.113.0/24 via 198.51.100.253 dev lfcsroute0 onlink
ip route get 203.0.113.10
# Output confirms the new gateway is selected
# ============================================
# PART 9: DELETE THE ROUTE
# ============================================
ip route del 203.0.113.0/24
ip route get 203.0.113.10
# Output reverts to the default route
# ============================================
# PART 10: PERSIST THE CONFIGURATION
# ============================================
# On a NetworkManager system, add the route to the connection profile
nmcli connection modify "eth0" +ipv4.routes "192.168.2.0/24 10.0.0.1"
nmcli connection up "eth0"
# Verify the route survives a connection restart
ip route show 192.168.2.0/24
The ten parts demonstrate the complete lifecycle: inspect, test, add with onlink, verify selection, replace, delete, and persist. The critical verification steps are Part 6 (ip route get confirms selection) and Part 10 (the persistent configuration produces the same running state after reactivation).
Quick Reference
Route Configuration Commands
| Task | Command |
|---|---|
| Add route via gateway | ip route add <net>/<prefix> via <gw> |
| Add route via interface | ip route add <net>/<prefix> dev <if> |
| Add route with both | ip route add <net>/<prefix> via <gw> dev <if> |
| Add with onlink | ... dev <if> onlink |
| Replace route | ip route replace <net>/<prefix> via <gw> |
| Delete route | ip route del <net>/<prefix> |
| Show routes | ip route show |
| Verify selection | ip route get <dest> |
Persistence Methods
| System | Configuration Method | Apply Command |
|---|---|---|
| Ubuntu/Netplan | YAML routes: under interface | netplan apply |
| RHEL/NM | nmcli connection modify +ipv4.routes | nmcli connection up |
| systemd-networkd | [Route] in .network file | systemctl restart systemd-networkd |
Key Flags
| Flag | Purpose |
|---|---|
via | Gateway for the route |
dev | Outgoing interface |
onlink | Accept gateway outside connected subnet |
metric | Route preference; lower wins |
Best Practices
โ Do This:
# Verify the current path before adding a route
ip route get <dest> # โ
# Use onlink when the gateway is not on a connected subnet
ip route add <net> via <gw> dev <if> onlink # โ
# Use replace when the route may already exist
ip route replace <net> via <gw> # โ
# Persist through the distribution's network manager
nmcli connection modify "eth0" +ipv4.routes "..." # โ
# Reactivate the connection after nmcli changes
nmcli connection up "eth0" # โ
# Verify both running state and persistent state
ip route show; reboot; ip route show # โ
โ Don’t Do This:
# Assume a route works because it appears in ip route show
# Verify with ip route get and a ping # โ
# Use ip route add when the route might exist
# add fails with "File exists"; use replace # โ
# Omit onlink when the gateway is unreachable
# The kernel rejects the route # โ
# Expect ip route add to survive reboot
# It modifies volatile kernel state only # โ
# Forget to reactivate the connection after nmcli modify
# The change is saved but not applied to the running interface # โ
# Overwrite existing routes without the + modifier in nmcli
# ipv4.routes without + replaces the entire route list # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| “Nexthop has invalid gateway” | Gateway not on connected subnet | Add onlink flag |
| Route lost after reboot | ip route add is not persistent | Configure through network manager |
| “File exists” error | Route already present | Use ip route replace |
| nmcli change not applied | Connection not reactivated | nmcli connection up |
| nmcli replaced all routes | Used ipv4.routes without + | Use +ipv4.routes to append |
| Route selected but no traffic | Firewall or gateway issue | Check ip6tables/iptables and gateway reachability |
| Persistent config not loaded | Service not restarted after edit | netplan apply or restart service |
Real-World Examples
1. Basic route via gateway
ip route add 192.168.2.0/24 via 10.0.0.1
2. Route via interface only
ip route add 192.168.2.0/24 dev eth0
3. Onlink route for dummy interface
ip route add 203.0.113.0/24 via 198.51.100.254 dev lfcsroute0 onlink
4. Host route
ip route add 10.10.10.1/32 via 192.168.1.1
5. Replace an existing route
ip route replace 192.168.2.0/24 via 10.0.0.2
6. Delete a route
ip route del 192.168.2.0/24
7. Verify selection
ip route get 192.168.2.100
8. Persist with nmcli
nmcli connection modify "eth0" +ipv4.routes "192.168.2.0/24 10.0.0.1"
nmcli connection up "eth0"
9. Persist with Netplan
# /etc/netplan/01-routes.yaml
network:
version: 2
ethernets:
eth0:
routes:
- to: 192.168.2.0/24
via: 10.0.0.1
10. Verify persistent route after reboot
ip route show 192.168.2.0/24
# Route should reappear after reboot if persistence is configured correctly
Visual
The Two-Layer Configuration Model
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ RUNNING CONFIGURATION vs PERSISTENT CONFIGURATION โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ RUNNING KERNEL STATE โ โ
โ โ โ โ
โ โ ip route add 192.168.2.0/24 via 10.0.0.1 โ โ
โ โ โ โ โ
โ โ โผ โ โ
โ โ ip route show โ route appears immediately โ โ
โ โ ip route get 192.168.2.5 โ route is selected โ โ
โ โ โ โ
โ โ โ LOST ON REBOOT โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โ Must match โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ PERSISTENT CONFIGURATION โ โ
โ โ โ โ
โ โ Netplan YAML OR nmcli connection profile โ โ
โ โ โ โ โ โ
โ โ โผ โผ โ โ
โ โ netplan apply nmcli connection up โ โ
โ โ โ โ โ โ
โ โ โผ โผ โ โ
โ โ Route applied at boot Route applied on reactivation โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Verification: reboot, then ip route show. โ
โ If the route is absent, persistence failed. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The onlink Flag Decision
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ WHEN IS onlink REQUIRED? โ
โ โ
โ Question: Is the gateway address within a directly โ
โ connected subnet? โ
โ โ
โ โ โ
โ โโโ YES โ No onlink needed โ
โ โ ip route add <net> via <gw> โ
โ โ โ
โ โโโ NO โ onlink required โ
โ ip route add <net> via <gw> dev <if> onlink โ
โ โ
โ Examples where onlink is needed: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Dummy interface: gateway address is fictional โ โ
โ โ VPN tunnel: gateway is inside the tunnel โ โ
โ โ Point-to-point: neighbor is outside configured subnet โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Without onlink, the kernel rejects the route: โ
โ "Nexthop has invalid gateway" โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
nmcli Route Persistence Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ nmcli CONNECTION MODIFY AND REACTIVATION โ
โ โ
โ Step 1: Add route to connection profile โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ nmcli connection modify "eth0" โ โ
โ โ +ipv4.routes "192.168.2.0/24 10.0.0.1" โ โ
โ โ โ โ
โ โ The + modifier APPENDS. โ โ
โ โ Without +, ipv4.routes REPLACES all existing routes. โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ Step 2: The profile is saved but NOT yet applied โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ip route show โ route may NOT appear yet โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ Step 3: Reactivate the connection โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ nmcli connection up "eth0" โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ Step 4: Verify โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ip route show 192.168.2.0/24 โ route appears โ โ
โ โ Route is now persistent across reboots โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Primary command | ip route (iproute2) |
| Add route | ip route add <net>/<prefix> via <gw> |
| Replace route | ip route replace |
| Delete route | ip route del |
| Verify selection | ip route get <dest> |
| onlink flag | For gateways outside connected subnets |
| Default metric rule | Lower metric preferred |
| Ubuntu persistence | Netplan YAML + netplan apply |
| RHEL persistence | nmcli connection modify +ipv4.routes + connection up |
| systemd-networkd | [Route] in .network file |
| Volatility | ip route add does not persist |
Key takeaways:
ip route addmodifies the running kernel, not the configuration. The route works immediately and disappears on reboot. Persistence is a separate operation through the network manager .onlinkis required when the gateway is not on a connected subnet. Without it, the kernel rejects the route with “Nexthop has invalid gateway.” Use it for dummy interfaces, VPN tunnels, and point-to-point links .replaceavoids the “File exists” error. When a route might already be present,replacecreates it if absent and overwrites it if present.addfails in both cases.ip route getis the verification tool. A route in the table is not necessarily the route selected.ip route getshows the kernel’s actual decision for a specific destination .- nmcli requires reactivation. The
connection modifycommand saves the route to the profile but does not apply it to the running interface.connection upapplies it . - The
+modifier in nmcli appends. Without it,ipv4.routesreplaces the entire route list, potentially removing routes that were already configured . - Persistence must be tested by reboot. A configuration file that looks correct but is not applied at boot is not persistence. The only verification is a reboot followed by
ip route show.
Remember: Static route configuration is two operations that must produce one result. The first operation modifies the running kernel: ip route add, ip route replace, or ip route del. The second operation writes the same intent to the persistent configuration: a Netplan YAML file, an nmcli connection profile, or a systemd-networkd .network file. The running operation is verified with ip route get. The persistent operation is verified with a reboot. A route that works in one layer but not the other is half-configured, and the half that disappears on restart is the one that matters least in a lab and most in production.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!