Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Linux Policy Routing with iprule and iproute2: Managing Rules and Routing Tables

Tech 3

Linux policy routing is implemented with iproute2. Use ip to inspect, create, and delete rules and routes; legacy tools like ifconfig/route cannot express policy decisions.

Verify iproute2

# ip -V
ip utility, iproute2-5.15.0

Policy Routing Rule Database (RPDB)

Viewing rules

# ip rule list
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

Adding rules

Rules select a routing table based on match conditions. Common selectors include from (source), to (destination), tos, fwmark, and iif (incoming inetrface).

  • Match by source address
# ip rule add from 10.20.30.40 table 100
# ip rule add from 10.20.31.0/24 table 200
  • Match by destination address
# ip rule add to 203.0.113.5 table 100
# ip rule add to 203.0.113.0/24 table 200
  • Match by firewall mark (with Netfilter)

Mark traffic in mangle and route by the mark value. Example: send DNS via table 101, HTTPS via table 102, and everything else via table 103.

# iptables -t mangle -A PREROUTING -i lan0 -p udp --dport 53  -j MARK --set-mark 0x1
# iptables -t mangle -A PREROUTING -i lan0 -p tcp --dport 443 -j MARK --set-mark 0x2
# iptables -t mangle -A PREROUTING -i lan0                               -j MARK --set-mark 0x3

# ip rule add fwmark 0x1 table 101
# ip rule add fwmark 0x2 table 102
# ip rule add fwmark 0x3 table 103
  • Match by input interface
# ip rule add iif lan1 table 201
# ip rule add iif lan2 table 202

Rule priorities

Rules are processed by ascending priority (pref). Lower numbers win. The kernel installs three defaults:

# ip rule list
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

When you add rules with out an explicit priority, they are assigned below 32766 (32765, 32764, ...). Set an explicit priority with pref:

# ip rule add from 10.20.31.0/24 table 200 pref 20
# ip rule add from 10.20.30.0/24 table 100 pref 10

# ip rule list
0:      from all lookup local
10:     from 10.20.30.0/24 lookup 100
20:     from 10.20.31.0/24 lookup 200
32766:  from all lookup main
32767:  from all lookup default

Routing table identifiers

Tables are addressed by numeric ID or by name via /etc/iproute2/rt_tables. Add readable names when useful:

# printf "101 corpnet\n102 guestnet\n" >> /etc/iproute2/rt_tables

Deleting rules

Any unique selector can be used to delete a rule:

# ip rule del pref 10
# ip rule del from 10.20.31.0/24
# ip rule del table 200
# ip rule del from 10.20.30.0/24 table 100 pref 10

# ip rule list
0:      from all lookup local
20:     from 10.20.31.0/24 lookup 200
32766:  from all lookup main
32767:  from all lookup default

Routing Table Management

Viewing a routing table

Inspect which tables are referenced by rules, then show table contents. Omitting the table defaults to main.

# ip rule list
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

# ip route show table main
192.0.2.0/24  dev enp0s3  proto kernel  scope link  src 192.0.2.10
10.0.5.0/24   dev enp0s8  proto kernel  scope link  src 10.0.5.20
default via 192.0.2.1 dev enp0s3

Built-in tables:

  • local: host and broadcast routes for local addresses; auto-populated.
  • main: the primary routing table used by default; typically populated from interface configuration.
  • default: empty unless explicitly used.

Adding routes to main

# ip route show table main
192.0.2.0/24  dev enp0s3  proto kernel  scope link  src 192.0.2.10
10.0.5.0/24   dev enp0s8  proto kernel  scope link  src 10.0.5.20
default via 192.0.2.1 dev enp0s3

# ip route add 172.16.10.0/24 via 192.0.2.254 dev enp0s3 table main

# ip route show table main
192.0.2.0/24    dev enp0s3  proto kernel  scope link  src 192.0.2.10
10.0.5.0/24     dev enp0s8  proto kernel  scope link  src 10.0.5.20
172.16.10.0/24  via 192.0.2.254 dev enp0s3
default via 192.0.2.1 dev enp0s3

Creating and populating a new table

A route in a non-main table is only used when a rule selects that table.

# echo "201 corpnet" >> /etc/iproute2/rt_tables

# ip rule list
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

# ip rule add from 10.0.5.0/24 table corpnet pref 50

# ip route show table corpnet
# (empty)

# ip route add table corpnet 10.0.5.0/24 dev enp0s8 scope link
# ip route add table corpnet default via 10.0.5.1 dev enp0s8

# ip route show table corpnet
10.0.5.0/24 dev enp0s8 scope link
default via 10.0.5.1 dev enp0s8

Deleting routes from a table

# ip route show table corpnet
10.0.5.0/24 dev enp0s8 scope link
default via 10.0.5.1 dev enp0s8

# ip route del default table corpnet

# ip route show table corpnet
10.0.5.0/24 dev enp0s8 scope link

# ip route del 10.0.5.0/24 table corpnet

# ip route show table corpnet
# (empty)

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.