When dealing with multiple network interfaces on a Linux system, we often need to route traffic from specific applications through designated interfaces. In this case, we want to:
- Route traffic from UID 1002 through tun0 (OpenVPN tunnel)
- Send all other traffic through eth1 (default internet)
Before implementing any changes, let's examine the existing network configuration:
# Current routing table
ip route show
default via 192.168.1.254 dev eth1 metric 203
10.32.0.49 dev tun0 proto kernel scope link src 10.32.0.50
85.17.27.71 via 192.168.1.254 dev eth1
192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.73 metric 203
Here's the complete solution that actually works:
1. Packet Marking in Mangle Table
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
2. Create Custom Routing Table
echo "11 vpn_route" >> /etc/iproute2/rt_tables
3. Configure Routing Rules
# Add route for VPN traffic
ip route add default via 10.32.0.49 dev tun0 table vpn_route
# Add policy routing rule
ip rule add fwmark 11 lookup vpn_route
4. NAT Configuration (Essential for VPN)
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
To ensure everything works as expected:
# Check marked packets
iptables -t mangle -L -v -n
# Verify routing rules
ip rule show
# Test with specific user
sudo -u user1002 curl ifconfig.me
If traffic still goes through the wrong interface:
- Verify the VPN tunnel is active (ip addr show tun0)
- Check packet counters in iptables
- Test routing with: ip route get to 8.8.8.8 mark 11
- Ensure reverse path filtering is disabled: sysctl -w net.ipv4.conf.all.rp_filter=2
For persistence across reboots, add these commands to your network initialization scripts (e.g., /etc/rc.local or network manager hooks). The exact method depends on your Linux distribution.
# For Debian/Ubuntu systems, consider adding to /etc/network/interfaces
post-up ip route add default via 10.32.0.49 dev tun0 table vpn_route
post-up ip rule add fwmark 11 lookup vpn_route
When dealing with multiple network interfaces on Linux systems, proper traffic routing becomes crucial. In this scenario, we have:
eth1 - Primary internet interface (192.168.1.73/24)
tun0 - OpenVPN tunnel interface (10.32.0.50)
We need to ensure:
- Processes owned by UID 1002 route through tun0
- All other traffic uses eth1
- Must maintain existing default routes
Step 1: Marking Packets
First, we mark packets from UID 1002 in the OUTPUT chain:
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
Step 2: Policy Routing Setup
Create a new routing table and add rules:
# Create new routing table
echo "11 vpntable" >> /etc/iproute2/rt_tables
# Add route to VPN interface
ip route add default via 10.32.0.49 dev tun0 table vpntable
# Add policy rule for marked packets
ip rule add fwmark 11 table vpntable priority 1000
Step 3: NAT Configuration
For proper masquerading through the VPN:
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
To test the configuration:
# As normal user
sudo -u user1000 wget -qO- ifconfig.me
# Should show eth1 IP
# As VPN user
sudo -u user1002 wget -qO- ifconfig.me
# Should show VPN endpoint IP
If traffic isn't routing correctly:
- Check packet marking:
iptables -t mangle -vL
- Verify routing rules:
ip rule list
- Inspect routing tables:
ip route show table vpntable
- Enable logging for debugging:
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j LOG --log-prefix "VPN-ROUTE: "
For a complete solution, you might want to:
- Add persistent configuration in /etc/network/interfaces or equivalent
- Consider DNS routing through the VPN
- Implement connection state tracking for established sessions