Policy based Routing
In Theory
Policy Routing is a feature on Cisco routers that offers greater control over paths in a network. Normal routing is done based on the routing table. The router looks up the destination address of a packet and finds out the next hop or the outgoing interface. With Policy Routing you can override whatever the routing table says and just route packets however you like. Isn’t this what static routing does? To some degree, yes. You can use static routes to manipulate the outcome of a route lookup, but static routes integrate in the normal routing process. The router will still base it’s routing decision on the packet’s destination address. The true power of policy routing is that it can take routing decisions on other parameters like incoming interface, source address or even application type (http, ftp).
Configuring Polcy Routing is a 2 step process.
Define the route-map
A route-map can have multiple statements, each statement being identified by a SEQ. If you don’t set a number, the default is 10. One statement can have multiple match commands and multiple set commands.
A packet is passed sequentially through the route-map statements. At each statement, the packet is considered matched if it is matched by all the match commands in that statement. If at least one of the match statements is not matched, then the packet is passed to the next statement. If all match statements are matched, then all set commands are applied.
If a matched route-map statement is set to permit, then the packet is policy-routed. If a matched route-map statement is set to deny, then it is routed according to the routing table. In either case, once a matching statement is found, no other statements are checked. If no statements are matched the packet is also routed according to the routing table.
Inside the route-map configuration mode we have to define a matching criteria using the match command. There are a lot of options, but most of them have to do with manipulating routing updates. For the purpose of Policy Routing we can use the following commands. In one statement, there can be multiple match commands, and a packet will be considered to match if it matches all of them (AND logic). One match command can refer to multiple objects (ex: multiple ACLs). A packet will be considered to match that entry if it matches at least one of the objects (OR logic).
When a packet is matched, all the set commands that are configure in the statement are executed:
When using the default keyword we tell the router to first try to find a match using the routing table and then use our defined policy, basically overriding only the routing table’s default route.
As you can see, we can define an outgoing interface or a next-hop address. Just like with static routes, you must understand the differences between using the next-hop or the outgoing interface. If there are multiple set commands, the order in which they are resolved is:
set ip next-hop
set ip next-hop recursive
set interface
set ip default next-hop
set ip default interface
For IPv4 we have one more option – using EOT – Enhanced Object Tracking to see if the next hop is up or not:
SEQ is a sequence number that is used to identify multiple options for the next hop, end OBJ is the object used to track availability. As you can imagine, this next hop will be used only if the object used for tracking is returning a positive result.
Optionally, you can also set a description for the route-map entry
Use route maps for traffic filtering
Simply match incoming traffic and set the outgoing interface to NULL0:
Apply the Route Map
You probably realized that the policy must be set on the interface where we expect to receive the traffic that will be matched. Setting the route-map on the outgoing interface makes no sense because the packets have already went through the routing process so they will just be sent out.
But what if I want to policy route traffic originated from the router. It has no incoming interface, so we have to use:
Force local traffic to be checked by ACLs
By default, traffic originated locally is not checked by ACLs set on interfaces. You can use route-maps to set the next-hop of locally originated traffic to a loopback interface, and force this way the traffic from being checked by the ACLs. The loopback interface is still local but the fact that is switching from one interface to another will force the router to apply the ACLs on this traffic.
Working examples
Example 1
Here’s an example:
PBR Example Topology
In our topology, we have 5 routers, each configured with an ip address on the Lo0 interface. On R1 we will simulate 2 hosts by using Lo1, as well. We will run EIGRP for route exchange. Here’s the starting config: On R1:
On R2:
On R3:
On R4:
On R5:
Remember that by default, physical router interfaces are disabled, so you should enable them using
On R1 we can test connectivity to R5 and see how the network converged:
Use numeric when starting a traceroute to disable the DNS lookups and get a faster response. As you can see, the route goes through R2, then R4 and then R5. The reason for this is because on R2, the interface towards R4 is Fast Ethernet, while the link towards R3 is over a HDLC serial link. Since the default EIGRP metric involves bandwidth and delay the route towards R4 will be considered the best. If we had RIP running, it would have installed 2 equal routes towards R5, as the hop count is the same.
Now let’s set a route map on R2 so that traffic from 11.11.11.11 would go through R3:
To verify the configuration, we will traceroute from R1 using each Loopbacks as the source:
As you can see, when the source is 1.1.1.1, the path is R1-R2-R4-R5and when the source is 11.11.11.11, the path is R1-R2-R3-R5 To verify on R2, we can start a debug process to see how the traffic was routed.
Or we can use this command to see the policies defined and how many packets were matched:
Notice there are 6 packets that matched, because although we sent 12 packets (check the debug output), only 6 of them matched the criteria – those sourced by 11.11.11.11. Why do we have 6 packets for just one traceroute command? Traceroute uses the TTL field to discover the path to a destination. It first sends packets with TTL=1, then increases the TTL until it reaches the destination. Each router on the path should decrease the TTL when routing the packet and should drop it when the TTL reaches 0. Actually, if the packet is not for itself, it would be pointless to route it, then decrease TTL and drop it, So, incoming packet with TTL 1 that should be routed are dropped. When dropping, it also should send an ICMP reply with the Type 11 (time-exceeded) and Code 0 (time to live exceeded in transit) back to the source, thus helping traceroute to map each router along the path. Cisco routers send by default 3 UDP packets for each TTL value starting from 1 upwards. This will help find multiple routes to a destination and also compute some average values for the Round Trip Time to each router along the path. So R1 first sends 3 packets with TTL=1. They will be droped by R2, so they won’t even get to the routing part – Matches so far: 0 R1 then sends another 3 packets with TTL=2. They will pass through R2 before being dropped by R3 – Matches so far: 3 R1 then sends another 3 packets with TTL=3. They will pass through R2 and R3 before R4 responds with an ICMP Type 3 (Destination unreachable) Code 3 (Port unreachable) for each one, signaling that the packets reached the destination, but there is no one waiting this kind of traffic. Matches so far: 6 So there it is, the 6 matches that we saw, made sense.
Example 2
Let’s say I want to have an out-of-band management connection from R2 to R5, when connecting via telnet. Let’s enable telnet on R5 first:
We should be able to telnet from R2 to R5, but we are going through R4. I am using 2.2.2.2 as the source address of my telnet traffic.
Let’s set this management traffic to be out-of-band, through R3:
In order to verify, let’s create an ACL on R5 just for accounting purpose:
Back on R2, we should be able to telnet to R5, but remember to disable debugging first, otherwise we would see a lot of messages like this:
It’s just the debug ip policy that was previously started, telling us that there are locally generated packets that match the route-map. Over to R5 to verify:
Yes! The telnet traffic originated by R2 arrived on Fa0/1 via R3.
The end?
We were able to send traffic from R2 to R5, via R3, using the route-map. But is it over? Well, no, because this is just one way. If we look at R5’s routing table, it will send return traffic back to R2’s Lo0 via R4:
The solution is to enable PBR in the other direction also. You should know how to do it by now.
Last updated