IP-RULE(8)

๐Ÿ“ฆ
version 7.3.0 ยท 6 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, centos-stream 9, debian trixie, fedora 44, ubuntu questing, ubuntu resolute, ubuntu stonking

๐ŸŽ€ NAME ๐ŸŽ€

okay bestie, this is the manual page for ip-rule, the Linux tool for routing policy database management ๐Ÿ’… so ip rule is how you play with the routing policy database ๐Ÿฆ‹

๐Ÿ’œ SYNOPSIS ๐Ÿ’œ

ip [ OPTIONS ] rule { COMMAND | help }

ip rule [ show [ SELECTOR ]]

ip rule { add | del } SELECTOR ACTION

ip rule { flush | save | restore }

SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ dscp
        DSCP[/MASK] ] [ fwmark FWMARK[/MASK] ] [ iif STRING ] [ oif
        STRING ] [ priority PREFERENCE ] [ l3mdev ] [ uidrange NUMBER-
        NUMBER ] [ ipproto PROTOCOL ] [ sport [ NUMBER[/MASK] | NUMBER-
        NUMBER ] ] [ dport [ NUMBER[/MASK] | NUMBER-NUMBER ] ] [ tun_id
        TUN_ID ] [ flowlabel FLOWLABEL[/MASK] ]

ACTION := [ table TABLE_ID ] [ protocol PROTO ] [ nat ADDRESS ] [ realms
        [SRCREALM/]DSTREALM ] [ goto NUMBER ] SUPPRESSOR

SUPPRESSOR := [ suppress_prefixlength NUMBER ] [ suppress_ifgroup GROUP
        ]

TABLE_ID := [ local | main | default | NUMBER ]

๐ŸŒธ DESCRIPTION ๐ŸŒธ

okay so ip rule is how you manipulate the rules in the routing policy database, which is the thing that controls the route selection algorithm ๐Ÿ˜ญโœจ

Classic internet routing is kinda basic. It only makes decisions based on the destination address of packets (and in theory, but not in practice, on the TOS field) ๐Ÿ™„

But sometimes we want to route packets differently depending on more than just where they're going. We might care about the source address, the IP protocol, the transport protocol ports, or even the packet payload ๐Ÿ‘€ This slay of a task is called 'policy routing' ๐Ÿ’…

So instead of the usual destination-based routing table, ordered by the longest match rule, we swap it out for a 'routing policy database' (or RPDB) ๐Ÿฆ‹ The RPDB picks routes by running through a set of rules ๐Ÿ”ฅ

Each policy routing rule is made of a selector and an action predicate ๐Ÿ’– The RPDB gets scanned in order of decreasing priority. Quick reminder that a lower number means higher priority, see the description of PREFERENCE below ๐Ÿ™ˆ The selector of each rule gets applied to {source address, destination address, incoming interface, tos, fwmark}. If the selector matches the packet, the action is performed โœจ The action predicate can return with success. When that happens, it gives either a route or a failure indication, and the RPDB lookup is done ๐Ÿ’… Otherwise, the RPDB program just moves on to the next rule ๐Ÿงš

Semantically, the natural action is to pick the nexthop and the output device ๐ŸŒˆ

At startup, the kernel sets up the default RPDB, which has three rules ๐Ÿ‘‘

  1. Priority: 0, Selector: match anything, Action: lookup routing table local (ID 255). The local table is a special routing table with high priority control routes for local and broadcast addresses ๐Ÿ’œ
  2. Priority: 32766, Selector: match anything, Action: lookup routing table main (ID 254). The main table is the normal routing table with all the non-policy routes ๐ŸŒธ This rule can be deleted and/or overridden with other ones by the administrator ๐Ÿ™ˆ
  3. Priority: 32767, Selector: match anything, Action: lookup routing table default (ID 253). The default table is empty ๐Ÿซถ It's reserved for some post-processing if no previous default rules selected the packet ๐Ÿ’… This rule can also be deleted โœจ

Each RPDB entry has extra attributes, bestie ๐ŸŽ€ For example, each rule has a pointer to some routing table. NAT and masquerading rules have an attribute to select a new IP address to translate or masquerade to ๐Ÿฆ‹ Rules can also have some optional attributes that routes have too, namely realms ๐ŸŒˆ These values don't override the ones in the routing tables ๐Ÿ˜ค They only get used if the route didn't select any attributes ๐Ÿ’–

The RPDB can have rules of these types ๐Ÿ”ฅ

  • unicast โ€” the rule returns the route found in the routing table the rule references ๐Ÿงš
  • blackhole โ€” the rule causes a silent drop of the packet ๐Ÿคซ
  • unreachable โ€” the rule generates a Network is unreachable error ๐Ÿ’€
  • prohibit โ€” the rule generates a Communication is administratively prohibited error ๐Ÿ™…โ€โ™€๏ธ
  • nat โ€” the rule translates the source address of the IP packet into some other value ๐Ÿฆ‹

โœจ ip rule add โœจ

Use ip rule add to insert a new rule ๐Ÿ’–

๐Ÿ—‘๏ธ ip rule delete ๐Ÿ—‘๏ธ

Use ip rule delete to delete a rule ๐Ÿ˜ญ

Here are the things you can set when you add or delete a rule ๐Ÿ’…

  • type TYPE (default) โ€” the type of this rule. The valid types were listed in the previous part of this page ๐ŸŒˆ
  • from PREFIX โ€” picks the source prefix to match ๐Ÿงš
  • to PREFIX โ€” picks the destination prefix to match ๐Ÿฆ‹
  • iif NAME โ€” picks the incoming device to match ๐Ÿซถ If the interface is loopback, the rule only matches packets that started from this host. So you can make separate routing tables for forwarded and local packets and totally separate them, periodt ๐Ÿ‘‘
  • oif NAME โ€” picks the outgoing device to match ๐Ÿ’… The outgoing interface only works for packets coming from local sockets that are bound to a device ๐Ÿ™ˆ
  • tos TOS
  • dsfield TOS โ€” picks the TOS value to match โœจ
  • dscp DSCP[/MASK] โ€” picks the DSCP value to match, with an optional mask ๐Ÿ’– DSCP values can be written as plain numbers (valid values are 0-63), or with symbolic names from /usr/share/iproute2/rt_dsfield or /etc/iproute2/rt_dsfield ๐ŸŒธ The /etc one wins if it exists ๐Ÿ™Œ Heads up though, that file has full 8-bit dsfield values, but ip rule only uses the higher six bits ๐Ÿค“ ip rule show will also show DSCP values as symbolic names when it can ๐Ÿ’… The command line option -N turns that show translation off ๐Ÿšซ
  • fwmark MARK โ€” picks the fwmark value to match ๐Ÿ”ฅ
  • uidrange NUMBER-NUMBER โ€” picks the uid value to match ๐Ÿงš
  • ipproto PROTOCOL โ€” picks the ip protocol value to match ๐ŸŒˆ
  • sport NUMBER[/MASK] | NUMBER-NUMBER โ€” picks the source port value to match, with an optional mask ๐Ÿฆ‹ It supports port ranges too โœจ
  • dport NUMBER[/MASK] | NUMBER-NUMBER โ€” picks the destination port value to match, with an optional mask ๐Ÿ’œ It supports port ranges too ๐Ÿซถ
  • priority PREFERENCE โ€” the priority of this rule ๐Ÿ‘‘ PREFERENCE is an unsigned integer. A higher number means lower priority, and rules get processed in order of increasing number ๐Ÿ™ˆ Every rule should have an explicitly set, unique priority value ๐Ÿ˜ค The options preference and order are synonyms for priority ๐Ÿ’…
  • table TABLEID โ€” the routing table identifier to look up if the rule selector matches ๐ŸŒธ You can also use lookup instead of table โœจ
  • protocol PROTO โ€” the routing protocol that installed the rule ๐Ÿงš For example, when zebra installs a rule, it would get RTPROT_ZEBRA as the installing protocol ๐Ÿ’–
  • suppress_prefixlength NUMBER โ€” rejects routing decisions that have a prefix length of NUMBER or less ๐Ÿšซ
  • suppress_ifgroup GROUP โ€” rejects routing decisions that use a device belonging to the interface group GROUP ๐Ÿ™…โ€โ™€๏ธ
  • realms FROM/TO โ€” the realms to select if the rule matched and the routing table lookup succeeded ๐ŸŒˆ Realm TO only gets used if the route didn't select any realm ๐Ÿซถ
  • nat ADDRESS โ€” the base of the IP address block to translate (for source addresses) ๐Ÿฆ‹ ADDRESS can be either the start of the block of NAT addresses (selected by NAT routes), or a local host address (or even zero) ๐Ÿ’… In that last case, the router doesn't translate the packets, it masquerades them to this address ๐Ÿ‘€ Using map-to instead of nat means the same thing ๐Ÿ’–
  • flowlabel FLOWLABEL[/MASK] โ€” picks the IPv6 flow label to match, with an optional mask ๐Ÿงš
โš ๏ธ Warning: Changes to the RPDB made with these commands don't become active immediately ๐Ÿ˜ญ It's assumed that after a script finishes a batch of updates, it flushes the routing cache with ip route flush cache ๐Ÿ’€

๐Ÿงน ip rule flush ๐Ÿงน

ip rule flush also dumps all the deleted rules ๐Ÿ’…

  • protocol PROTO โ€” selects the originating protocol ๐ŸŒธ

๐Ÿ“‹ ip rule show ๐Ÿ“‹

ip rule show lists the rules โœจ This command has no arguments ๐Ÿ™ˆ The options list or lst are synonyms for show ๐Ÿ’œ

๐Ÿ’พ ip rule save ๐Ÿ’พ

  • protocol PROTO โ€” selects the originating protocol ๐Ÿฆ‹

ip rule save saves rules table information to stdout ๐Ÿซถ This command acts like ip rule show, except the output is raw data that's suitable for passing to ip rule restore ๐ŸŒˆ

โ™ป๏ธ ip rule restore โ™ป๏ธ

ip rule restore restores rules table information from stdin ๐Ÿงš This command expects a data stream like the one returned from ip rule save ๐Ÿ’– It tries to restore the rules table information exactly as it was at the time of the save ๐Ÿ‘‘ Any rules already in the table are left unchanged, and duplicates are not ignored ๐Ÿ˜ค Be careful with that one, bestie ๐Ÿ™ˆ

๐Ÿฆ‹ SEE ALSO ๐Ÿฆ‹

ip(8) ๐Ÿ’–

๐Ÿ‘ฉโ€๐Ÿ’ป AUTHOR ๐Ÿ‘ฉโ€๐Ÿ’ป

Original Manpage by Michail Litvak <mci@owl.openwall.com> ๐Ÿซถ


That's the whole tea on ip-rule, from iproute2 ๐Ÿฉท last updated 20 Dec 2011, so the vibes are a little vintage but still iconic ๐Ÿ’…โœจ stay routed, stay slay, see you in the RPDB ๐Ÿงš๐ŸŒˆ๐Ÿ’œ