Build and Check Linux Policy Routing Rules with ip rule

ip rule lets you send some traffic down a different routing table based on where it came from, not just where it is going. You will inspect Linux's routing policy database (RPDB), add one source-based rule, check its priority, and remove it again. The commands use the installed iproute2 6.1.0 on this machine. Allow about 10 minutes if you already know which source prefix and table you need; designing the routes in that table is a separate task.

Before you start

Checkpoint: Keep the source prefix, table ID and priority you choose in one place. In the examples below they are 192.0.2.0/24, table 100, and priority 1000. The addresses are documentation values, so replace them before using the command on a real network.

1. Inspect the current policy database

Start with a read-only listing:

ip rule show

A new installation commonly begins with three rules like these:

0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

The first rule checks the special local table. The main table is the normal route set, and the default table is reserved for later processing and is normally empty. The number at the left is the rule's priority: the kernel processes rules in increasing numerical order, so 0 is higher priority than 32766.

Use the listing to find an unused priority and to check whether another rule already handles your source or destination. A rule that matches first can prevent a later rule from being reached.

2. Save a recovery copy

Before changing a busy host, save the RPDB in the format accepted by ip rule restore:

ip rule save > /tmp/ip-rule-before.txt
sed -n '1,40p' /tmp/ip-rule-before.txt

The file is plain command input rather than a general configuration file. Keep it private if your host's rule selectors reveal network design or firewall marks. Restore is additive: existing rules are left unchanged, and duplicate rules are not ignored. It is therefore not a general-purpose rollback command. For a small change, explicit deletion is easier to reason about.

3. Add a source-based lookup rule

Warning: This changes the live RPDB. A rule pointing at an empty or incomplete table can make matching traffic fail, and an overly broad rule can bypass expected routes. Confirm the table's routes and test during a maintenance window if the source is production traffic.

First inspect the table you intend to use. Table 100 is only an example:

sudo ip route show table 100

Then add a rule with an explicit, unique priority:

sudo ip rule add pref 1000 from 192.0.2.0/24 table 100

from is the selector. table (also accepted as lookup) is the action taken when that selector matches. The routing table must contain a suitable route; the rule does not create one.

Verify the exact entry and its position:

ip rule list pref 1000

Expected output is similar to:

1000:   from 192.0.2.0/24 lookup 100

The output may include additional attributes on a host with a different iproute2 build. If the command reports that the priority already exists, return to step 1 and choose another unused value. Avoid silently changing an existing rule.

4. Test the boundary conditions

Check the rules around the new priority, then check the table itself:

ip rule show
ip route show table 100

Look for three common mistakes:

Selectors can also match destination prefixes, incoming interfaces, firewall marks, user ID ranges, IP protocol and source or destination ports. For example, the installed syntax supports a destination-specific rule such as to 198.51.100.0/24, but combine selectors only when each one is needed. Every extra condition is another reason a rule may appear correct while matching nothing.

5. Remove the test rule

Delete the same selector and action, including the priority:

sudo ip rule del pref 1000 from 192.0.2.0/24 table 100
ip rule list pref 1000

The second command should produce no rule. If you changed a different rule by mistake, stop and compare ip rule show with the saved file. Do not use ip rule flush as a shortcut: it removes rules and prints the deleted entries, which can disrupt every policy-routed flow on the machine.

Useful selectors and safety boundaries

The local manpage for this installation accepts selectors including not, from, to, tos, fwmark with an optional mask, iif, oif, pref, l3mdev, uidrange, ipproto, sport, dport and tun_id. Actions include table lookup, a protocol label, realms, NAT, goto and suppressors. Use ip rule help on the target host rather than copying an option from a different release.

Policy rules are not the same as routes. A rule chooses when to consult a table; ip route populates that table. Also, a rule added interactively is not persistent across reboot unless your distribution's network configuration recreates it. Put the rule in the network manager or boot configuration used by that host only after the live command has been tested.

The installed manpage mentions flushing the routing cache after a batch of changes. Modern kernels and iproute2 releases do not always expose a separate cache in the same way, so check the target system's ip route behaviour before adding cache-flush commands to automation. Do not add an unverified command merely because an older procedure contains it.

Done means