Routing traffic based on specific source or destination addresses on Ubuntu requires policy routing, which standard default routes cannot handle. You must configure separate routing tables and use ip rule commands to direct packets through distinct network interfaces. This approach ensures that traffic from a specific IP uses the correct gateway without disrupting general connectivity.
Understanding Policy Routing Concepts
Before applying changes, it is essential to understand how Linux handles packet forwarding. By default, all traffic uses the main routing table. Policy routing allows you to create additional tables and assign rules to them. These rules check the source address of incoming packets and decide which table to consult for the next hop. This mechanism is critical when you have multiple internet connections or need to isolate specific services to different networks. For more details on how network interfaces interact with these rules, see our guide on Ubuntu server network interfaces. Understanding the underlying interface configuration helps prevent conflicts when assigning static IPs to specific sources.Configuring Static IP Addresses
Policy routing typically relies on static IP assignments for the source interfaces. Dynamic addressing via DHCP can complicate rule matching because IP addresses may change. First, identify the network interfaces involved in your setup. You can list them using theip link show command.
Next, assign static IP addresses to these interfaces. In modern Ubuntu versions, Netplan is the default configuration tool. However, Netplan does not natively support complex policy routing rules like ip rule directly in its YAML schema. Therefore, you often need to combine Netplan for basic interface configuration with systemd-networkd or manual scripts for the routing policies.
If you are dealing with persistent connectivity issues after changing network settings, refer to our article on fixing Raspberry Pi internet issues after VPN changes, as similar principles apply to maintaining stable routes during configuration shifts.
Creating Custom Routing Tables
Linux supports up to 255 custom routing tables, indexed by ID. You need to define these IDs in the/etc/iproute2/rt_tables file. Open this file with a text editor and add new entries. For example, you might add:
# /etc/iproute2/rt_tables
#
# reserved values
255 local
254 main
253 default
0 unspec
# local routing tables
100 special_source
200 special_dest
Here, we created two tables: special_source (ID 100) and special_dest (ID 200). The numbers must be unique and not conflict with reserved IDs like 254 (main) or 255 (local). Once defined, the kernel recognizes these tables and can route packets to them based on rules.
Defining Rules and Routes
The core of policy routing lies in theip rule and ip route commands. Rules determine which packets go to which table, while routes define how to reach destinations within that table.
First, add a rule that matches your specific source IP address. Replace 192.168.1.100 with your actual source IP and eth0 with the appropriate interface name.
sudo ip rule add from 192.168.1.100 table special_source
This command tells the kernel: "If a packet originates from 192.168.1.100, look up the route in the 'special_source' table." Next, populate that table with the necessary routes. You need at least a default route pointing to the gateway for that specific connection.
sudo ip route add default via 10.0.0.1 dev eth0 table special_source
sudo ip route add 192.168.1.0/24 dev eth0 src 192.168.1.100 table special_source
The first line sets the default gateway for this table. The second line ensures that local subnet traffic remains on the interface. If you need to route based on destination rather than source, you would use ip rule add to <dest_ip> table ... instead.
Making Configuration Persistent
Commands executed viaip are lost upon reboot. To make them persistent, you should integrate them into your system's initialization process. On Ubuntu, creating a systemd service is the most reliable method. Create a file named /etc/systemd/system/policy-routing.service:
[Unit]
Description=Policy Routing Configuration
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/setup-policy-routing.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Then, create the script /usr/local/bin/setup-policy-routing.sh containing all your ip rule and ip route commands. Ensure the script is executable with chmod +x. Finally, enable the service:
sudo systemctl enable policy-routing.service
sudo systemctl start policy-routing.service
This ensures that every time the network comes online, your custom routing policies are applied automatically.
Troubleshooting Common Issues
If your routed traffic does not work, verify the rules are active usingip rule show. Check if the source IP matches exactly. Also, ensure that the gateway specified in the custom table is reachable from the interface assigned to that table. Asymmetrical routing can cause problems where return traffic ignores your custom rules. To test connectivity, use ping -I <source_ip> <destination> to force the source address.
For deeper diagnostics on why a device might not be reachable, consult our guide on troubleshooting Linux device not reachable during ping. This covers common firewall and routing blockers that affect policy-based setups.
Frequently Asked Questions
Can I use Netplan for all policy routing configurations?
No, standard Netplan YAML does not supportip rule directives directly. You should use Netplan for basic interface and IP assignment, then use systemd services or NetworkManager dispatcher scripts for the actual policy routing rules.
How do I verify which routing table a packet is using?
You can useip rule show to see active rules. To trace a specific packet, use tcpdump or ss to monitor connections. Additionally, checking cat /proc/net/fib_trie can provide insights into how the kernel resolves addresses.
What happens if the primary interface goes down?
If the interface associated with your custom routing table fails, packets destined for that table will drop unless you have backup routes defined. It is good practice to include failover routes in your custom tables to maintain connectivity.Is policy routing safe for production servers?
Yes, it is safe and widely used. However, incorrect configurations can lead to blackholes or asymmetric routing. Always test changes in a staging environment first and ensure you have console access to revert mistakes if network connectivity is lost.Can I route traffic based on port numbers?
Standard Linux routing tables operate at Layer 3 (IP), not Layer 4 (ports). To route based on ports, you need to use iptables or nftables with mangle table rules to mark packets, and then use those marks in yourip rule statements.