When developing network applications or testing interface drivers, we often need to simulate traffic between two interfaces on the same machine. The specific scenario involves:
- eth1 with IP 192.168.1.1
- eth2 with IP 192.168.2.2
- A crossover cable connecting eth1 and eth2
The goal is to force all traffic destined for 192.168.1.1 to physically traverse eth2, then return via eth1, rather than being handled internally by the loopback interface.
Standard Linux routing handles local traffic intelligently - when you access a local IP, the kernel shortcuts the network stack and processes it internally. Our challenge is to override this behavior.
# This doesn't solve our problem ip route add 192.168.1.1 dev eth2
We need a combination of routing rules and NAT to achieve our goal:
# First, add a special routing table echo "200 special" >> /etc/iproute2/rt_tables # Route traffic to our alternate IP via eth2 ip route add 192.168.1.100 dev eth2 table special ip rule add from all to 192.168.1.100 lookup special # Set up NAT to translate our alternate IP to the real one iptables -t nat -A PREROUTING -d 192.168.1.100 -j DNAT --to-destination 192.168.1.1 iptables -t nat -A POSTROUTING -s 192.168.1.1 -j SNAT --to-source 192.168.1.100 # Enable routing between interfaces sysctl -w net.ipv4.ip_forward=1
To test this setup with an HTTP server:
# On one terminal: python3 -m http.server 80 # On another terminal: curl http://192.168.1.100
Use tcpdump to verify the traffic path:
tcpdump -i eth2 -n host 192.168.1.100 tcpdump -i eth1 -n host 192.168.1.1
If you're specifically testing network drivers, consider creating virtual interfaces:
# Create virtual Ethernet pair ip link add veth0 type veth peer name veth1 # Assign IPs ip addr add 192.168.3.1/24 dev veth0 ip addr add 192.168.3.2/24 dev veth1 # Bring them up ip link set veth0 up ip link set veth1 up
For Windows users, you can achieve similar functionality using the routing table:
route add 192.168.1.100 mask 255.255.255.255 192.168.2.2 if
And using PowerShell for NAT:
Add-NetNatStaticMapping -NatName "LoopbackTest" -Protocol TCP -ExternalIPAddress 192.168.1.100 -InternalIPAddress 192.168.1.1 -InternalPort 80 -ExternalPort 80
When developing network drivers or testing interface behavior, we often need to route local traffic through physical interfaces instead of the loopback adapter. Here's a concrete scenario:
# Current interface configuration eth1: 192.168.1.1/24 eth2: 192.168.2.2/24
The Linux kernel automatically routes traffic destined for local addresses (like 192.168.1.1) through the loopback interface. Simple routing commands won't override this behavior:
# This won't work as expected for local addresses ip route change 192.168.1.1/24 dev eth2
We need to combine several techniques to achieve the desired traffic flow:
First, mark packets destined for our target IP:
iptables -t mangle -A OUTPUT -d 192.168.1.1 -j MARK --set-mark 1
Then create a custom routing table for marked packets:
echo "100 custom" >> /etc/iproute2/rt_tables ip rule add fwmark 1 table custom ip route add default via 192.168.2.1 dev eth2 table custom
Finally, configure NAT to handle the return traffic:
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
Here's a full script to implement this solution:
#!/bin/bash # Configure interfaces ip addr add 192.168.1.1/24 dev eth1 ip addr add 192.168.2.2/24 dev eth2 # Mark packets destined for 192.168.1.1 iptables -t mangle -A OUTPUT -d 192.168.1.1 -j MARK --set-mark 1 # Set up custom routing echo "100 custom" >> /etc/iproute2/rt_tables ip rule add fwmark 1 lookup custom ip route add default via 192.168.2.1 dev eth2 table custom # Enable NAT iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE # Verify with: # ip route show table custom # iptables -t mangle -L -n -v
To verify this works with actual services:
# Set up test HTTP server python3 -m http.server --bind 192.168.1.1 80 & # Make request through forced path curl --interface eth2 http://192.168.1.1 # For iperf testing: iperf3 -s -B 192.168.1.1 & iperf3 -c 192.168.1.1 --bind 192.168.2.2
If you're using a crossover cable between interfaces, you can simplify the setup:
# Assign addresses on different subnets ip addr add 192.168.1.1/24 dev eth1 ip addr add 192.168.1.2/24 dev eth2 # Add explicit route ip route add 192.168.1.1/32 dev eth2 # Disable reverse path filtering sysctl -w net.ipv4.conf.all.rp_filter=0 sysctl -w net.ipv4.conf.eth1.rp_filter=0 sysctl -w net.ipv4.conf.eth2.rp_filter=0
How to Force Local IP Traffic Through External Network Interface in Linux: A Complete iptables and Routing Guide
2 views