Linux Policy Routing — Introduction

Marthin Satrya Pasaribu
4 min readMar 18, 2020

--

Policy routing actually allows us a great deal of flexibility in how we direct traffic out of a Linux host. There are a couple of parts involved in policy routing:

  • Policy Routing Tables: Linux comes with three default:
    * Local (cannot be modified or default)
    * Main
    * Default
    Routes added to the system without a routing table specified to go to the main table, not the default table.
  • Policy routing rules
    Linux comes with three rules, one for each of the default routing tables.

When we’re trying to used policy routing for our purpose we need to do three things:

  • We need to create a custom policy routing table
  • We need to create one or more custom policy routing rules
  • We need to populate the custom policy routing table with routes

Now let’s try, I’m using Ubuntu on this sample:

Creating Custom Policy Routing Table

The first step is to create a custom policy routing table, each table is represented by an entry in the file /etc/iproute2/rt_tables. You can check using vim or nano or other tools in Linux.

We will try to create custom table in the policy routing table using this command.

echo 200 custom >> /etc/iproute2/rt_tables

And after you run that command, and check-in rt_tables, you will see this:

Creating Policy Routing Rules

The next step is to create policy routing rules that will tell the system which table to use to determine the correct route. In this example I will use the source address (i.e., the originating address for the traffic) as the determining factor in the rule.

To create the policy routing rule, use this command:

ip rule add from <source address> lookup <table name>

Before we already create custom routing table, and we will set source address 192.168.30.199. It means if request is coming from that IP it means system to use the `custom` table.

ip rule add from 192.168.39.199 lookup custom

We can see all the policy routing rules that are currently in effect using this command:

ip rule list

As earlier mention in this article, there are default rules that govern the use of local, main, and default. That’s why once you added the rule, you will see it listed there as well.

One important note and problem. It will disappear when your system is restarted (or when the networking is restarted). But the `custom` in table route will be still there, only in policy routing rules will be gone. To make rules persist, add this command:

post-up ip rule add from 192.168.39.199 lookup custom

It will be adding to /etc/network/interfaces. With this command, the rule should persist across reboots or across network restarts.

Populating the Routing Table

We already set the custom policy routing table and a rule defined that directs the system to use it. The last step is we need to populate the table with the correct routes. The generic command to do this is:

ip route add

But with a specific table parameter added. Using our previous example, let’s say we wanted to add a default route that was specific to traffic originating from 192.168.39.199. We’ve already created a custom policy routing table, and we have a rule that directs the system to use that table for traffic originating from that address. To add a new default route specifically for that interface, you’d use this command.

ip route add default via 192.168.30.2 dev eth1 table custom

Naturally, you’d want to substitute the correct default gateway for 192.168.30.2 and the correct interface for eth1 in the above command, but this should give you the right idea. Of course, you don’t have to use default routes; you could install specific routes into the custom policy routing table as well. This also works on VLAN sub-interfaces, so you could create per-VLAN routing tables. But you need to create vlan30 table on the first step:

ip route add default via 192.168.30.2 dev eth0.30 table vlan30

This command installs a default route for the 192.168.30.x interface on VLAN 30, using a table named “vlan30”

As with the policy routing tables, routes added this way are not persistent, so you’ll want to make them persistent by adding a line like this to your /etc/network/interfaces configuration file:

post-up ip route add default via 192.168.30.2 dev eth1 table custom

References:

--

--