Policy Routing

Policy routing is the art of deviating from destination-based shortest-path routing decisions of dynamic routing protocols. Policy routing considers aspects such as source/destination address, ports, protocol, type of service (ToS), and entry interfaces; do not confuse it with a routing policy or traffic policing. Traffic policing and shaping are sometimes summarized as traffic conditioning. Linux offers by far the most evolved policy routing approach of all Unices via multiple routing tables, the Routing Policy Database (RPDB), and the iproute2 (ip and tc) package for administration. Most other UNIX implementations implement policy routing via firewall marks and packet-mangling hooks.

Policy Routing on BSD

Policy-routing setup on BSD platforms is pretty straightforward, limited, and essentially integrated into firewall architectures. Examples 13-1 and 13-2 demonstrate its use by forwarding certain traffic based on source address or incoming interface (highlighted text).

Firewalling, NAT, and policy enforcement are done by basically the same "packet-mangling" structures.

Example 13-1. Policy-Routing Example with FreeBSD ipfilter

pass out quick on fxp0 to fxp1:192.168.2.1 from 192.168.2.200 to any


Example 13-2. Policy-Routing Example with OpenBSD Packet Filter (pf)

pass out log quick on xl0 route-to tl0:192.168.1.1 proto icmp from tl0 to any

pass out log quick on xl0 proto icmp from any to any


Linux iproute2 Policy Routing

The Linux OS can place routes within multiple routing tables that are identified by an 8-bit numeric ID or by a pseudo-name that is mapped in the file /etc/iproute2/rt_tables. By default, three tables exist: the default, the local, and the main (ID 254), as follows:

  • The default table can be discarded safely. It is reserved for last-resort postprocessing for the unlikely case that previous rules/routing tables did not process the packet.

  • The important local table (ID 255) consists of routes for local and broadcast addresses (as directly connected interfaces in Cisco lingo). The kernel maintains this table automatically. As a rule of thumb, it should not be tampered with.

  • By default, all route manipulations act on the main routing table (forwarding table). The RPDB supervises the different routing tables. Policy routing is configured via the ip rule and ip route commands.

Multiple routing tables come into play when policy routing is used, for traffic control and in the context of Multiprotocol Label Switching (MPLS) multiple routing instances (VRFs, or virtual routing and forwarding instances). In policy routing, the routing table identifier becomes one additional criterion capable of handling otherwise-identical prefix routes in different tables that will not conflict because of this tiebreaker mechanism. Example 13-3 illustrates the capabilities of the Linux policy-routing toolbox. Example 13-4 offers an example of a custom policy-routing table.

Example 13-3. Policy-Routing iproute2 Commands

[root@callisto:~#] ip rule help

Usage: ip rule [ list | add | del ] SELECTOR ACTION

SELECTOR := [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK ]

            [ dev STRING ] [ pref NUMBER ]

ACTION := [ table TABLE_ID ] [ nat ADDRESS ]

          [ prohibit | reject | unreachable ]

          [ realms [SRCREALM/]DSTREALM ]

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



[root@callisto:~#] ip rule list

0:      from all lookup local

32766:  from all lookup main

32767:  from all lookup default

[root@callisto:~#] ls -al /etc/iproute2/

total 36

drwxr-xr-x    2 root     root         4096 Aug 28 08:10 ./

drwxr-xr-x   86 root     root         8192 Aug 28 08:03 ../

-rw-r--r--    1 root     root          299 Mar 15  2002 rt_dsfield

-rw-r--r--    1 root     root          296 Mar 15  2002 rt_protos

-rw-r--r--    1 root     root          114 Mar 15  2002 rt_realms

-rw-r--r--    1 root     root           98 Mar 15  2002 rt_scopes

-rw-r--r--    1 root     root           81 Aug 28 08:10 rt_tables



[root@callisto:~#] cat /etc/iproute2/rt_tables

#

# reserved values

#

255     local

254     main

253     default

0       unspec



#

# local values

#

1       lab



[root@callisto:~#] cat /etc/iproute2/rt_scopes

#

# reserved values

#

#0      global

#255    nowhere

#254    host

#253    link



#

# pseudo-reserved

#

#200    site



[root@callisto:~#] ip route help

Usage: ip route { list | flush } SELECTOR

       ip route get ADDRESS [ from ADDRESS iif STRING ]

                            [ oif STRING ]  [ tos TOS ]

       ip route { add | del | change | append | replace | monitor } ROUTE

SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]

            [ table TABLE_ID ] [ proto RTPROTO ]

            [ type TYPE ] [ scope SCOPE ]

ROUTE := NODE_SPEC [ INFO_SPEC ]

NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ]

             [ table TABLE_ID ] [ proto RTPROTO ]

             [ scope SCOPE ] [ metric METRIC ]

INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...

NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS

OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]

           [ rtt NUMBER ] [ rttvar NUMBER ]

           [ window NUMBER] [ cwnd NUMBER ] [ ssthresh REALM ]

           [ realms REALM ]

TYPE := [ unicast | local | broadcast | multicast | throw |

          unreachable | prohibit | blackhole | nat ]

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

SCOPE := [ host | link | global | NUMBER ]

FLAGS := [ equalize ]

NHFLAGS := [ onlink | pervasive ]

RTPROTO := [ kernel | boot | static | NUMBER ]



[root@callisto:~#] ip route list table local

local 192.168.1.1 dev eth1  proto kernel  scope host  src 192.168.1.1

local 192.168.45.253 dev eth1  proto kernel  scope host  src 192.168.45.253

broadcast 192.168.1.0 dev eth1  proto kernel  scope link  src 192.168.1.1

broadcast 127.255.255.255 dev lo  proto kernel  scope link  src 127.0.0.1

broadcast 192.168.14.255 dev eth0  proto kernel  scope link  src 192.168.14.1

broadcast 192.168.45.255 dev eth1  proto kernel  scope link  src 192.168.45.253

broadcast 192.168.1.255 dev eth1  proto kernel  scope link  src 192.168.1.1

broadcast 192.168.14.0 dev eth0  proto kernel  scope link  src 192.168.14.1

broadcast 192.168.45.0 dev eth1  proto kernel  scope link  src 192.168.45.253

local 192.168.14.1 dev eth0  proto kernel  scope host  src 192.168.14.1

broadcast 127.0.0.0 dev lo  proto kernel  scope link  src 127.0.0.1

local 127.0.0.1 dev lo  proto kernel  scope host  src 127.0.0.1

local 127.0.0.0/8 dev lo  proto kernel  scope host  src 127.0.0.1



[root@callisto:~#] ip route list table main

192.168.1.0/24 dev eth1  scope link

192.168.14.0/24 dev eth0  scope link

192.168.45.0/24 dev eth1  proto kernel  scope link  src 192.168.45.253

127.0.0.0/8 dev lo  scope link

default via 192.168.1.254 dev eth1



[root@callisto:~#] ip route list table main scope link

192.168.1.0/24 dev eth1

192.168.14.0/24 dev eth0

192.168.45.0/24 dev eth1  proto kernel  src 192.168.45.253

127.0.0.0/8 dev lo


Example 13-4. Creating and Populating a Custom Routing Table

[root@callisto:~#] echo 1 lab >> /etc/iproute2/rt_tables

[root@callisto:~#] echo 1 lab >> /etc/iproute2/rt_realms

[root@callisto:~#] ip rule del pref 32767

[root@callisto:~#] ip rule add from 192.168.14.0/24 to 192.168.7.0/24 table lab pref      

graphics/ccc.gif              32765 realms lab/lab



[root@callisto:~#] ip rule list

0:      from all lookup local

32765:  from 192.168.14.0/24 to 192.168.7.0/24 lookup lab realms lab/lab

32766:  from all lookup main

[root@callisto:~#] ip route add default via 192.168.14.254 table lab



[root@callisto:~#] ip route flush cache



[root@callisto:~#] ip route list table lab

default via 192.168.14.254 dev eth0



[root@callisto:~#] rtacct lab

Realm      BytesTo    PktsTo     BytesFrom  PktsFrom

lab        0          0          0          0


Linux routing also incorporates the concept of realms. A routing realm essentially can be compared to a route aggregate in Border Gateway Protocol (BGP) lingo; however, it is a grouping based on human logic and not necessarily on bitmasks. Realms often are used for tracking, traffic control, and packet path-accounting purposes that can be inspected via the rtacct utility. Realms are demonstrated in Example 13-4, too. Each route can be assigned to a realm either dynamically by a routing daemon or statically via the REALM option of the ip route command. I am aware of a patched version of GateD with patches from Alexej Kuznetsov that can classify prefixes to realms and can handle multiple Linux routing table IDs. For a concise discussion of realms and scope, check out the original writings of Alexej Kuznetsov, the creator of the iproute2 toolbox, at http://www.policyrouting.org/.

Cisco IOS Policy-Routing Example

Policy-based routing (PBR) enables you to classify traffic based on extended access list criteria or assign the traffic to different service classes via an IP precedence setting. Consult the Cisco.com article "Configuring Policy-Based Routing" for further information. Example 13-5 demonstrates the use of policy route maps to achieve this goal.

Example 13-5. Cisco IOS Policy Route Map for Different Next Hops and Priority

...

!

access-list 1 permit ip 192.168.1.1

access-list 2 permit ip 192.168.2.1

!

interface ethernet 1

 ip policy route-map LAB

!

route-map LAB permit 10

 match ip address 1

 set ip precedence priority

 set ip next-hop 192.168.3.1

!

route-map LAB permit 20

 match ip address 2

 set ip precedence critical

 set ip next-hop 192.168.3.2

!

...