When working with multi-homed Linux systems, it's crucial to understand which network interface and source IP will be used for outbound connections. The routing decision is made based on the kernel's routing table, which can be complex to interpret manually.
The most efficient way to check the route for a specific destination is using the ip route get
command:
ip route get 8.8.8.8
8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.100
cache
This output shows:
- Destination: 8.8.8.8
- Gateway: 192.168.1.1
- Interface: eth0
- Source IP: 192.168.1.100
For understanding the complete path including interface selection:
traceroute -i any example.com
The first hop will reveal the outgoing interface.
To verify the source IP that will be used:
ip route get to 8.8.8.8 | grep -oP 'src \K[^ ]+'
Consider a server with two interfaces:
ip addr show
1: lo: ...
2: eth0: inet 192.168.1.100/24
3: eth1: inet 10.0.0.2/24
For a destination in 192.168.1.0/24:
ip route get 192.168.1.50
192.168.1.50 dev eth0 src 192.168.1.100
cache
For an external destination:
ip route get 1.1.1.1
1.1.1.1 via 192.168.1.1 dev eth0 src 192.168.1.100
When using multiple routing tables (policy routing), you might need to specify the table:
ip route get 8.8.8.8 table 100
For automated checks, use this bash function:
get_route_info() {
dest=$1
echo "Route information for $dest:"
ip route get "$dest" | awk -F'[ ]' '/src/ {print "Interface:",$3,"\nSource IP:",$5}'
}
When dealing with multi-homed Linux systems, identifying the exact network path for specific destinations becomes critical for network debugging and configuration. The standard routing table output can be overwhelming when you just need to know:
- Which physical interface handles traffic for a specific host
- What source IP address will be used
- Whether multiple paths exist
The most precise tool for this task is ip route get
, which performs a route lookup simulation:
ip route get 8.8.8.8
# Output example:
# 8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.100 uid 1000
For DNS-based destinations, combine with dig
for complete analysis:
destination="example.com"
ip route get $(dig +short $destination | head -1) | \
awk '{print "Interface: " $3 "\nSource IP: " $5}'
Using tracepath:
tracepath -n example.com | head -2
Network Namespace Variation:
ip netns exec namespace_name ip route get 10.0.0.5
Case 1: Multiple default routes
# With routing table:
# default via 192.168.1.1 dev eth0
# default via 10.0.0.1 dev eth1
ip route get 1.1.1.1 | grep -oP 'dev \K\S+' # Shows active interface
Case 2: Policy-based routing
ip rule list
ip route get 8.8.8.8 from 10.0.0.5
Create a reusable bash function for your shell:
routeinfo() {
local dest=$(dig +short $1 | head -1)
[ -z "$dest" ] && dest=$1
echo "Route analysis for $1 ($dest):"
ip route get $dest | awk '{print "Interface:",$3,"| Source IP:",$5}'
}
- If encountering "RTNETLINK answers: Invalid argument", try using the numeric IP
- For containers/VMs, check both host and guest routing tables
- Remember that iptables/nftables might affect source address selection