In this article, I will discuss one of the new features that is supported on the Cisco ASA, starting from version 9.4(1) – Policy Based Routing. There used to be many unsupported features that discouraged placing the ASA at the edge and PBR was one of them.
CCNA Training – Resources (Intense)
Let’s start by discussing the problem before PBR was introduced and then go on to see how PBR solves this issue. Consider the network diagram below:
In this diagram, if we wanted to use both links to the Internet at the same time (via default routes), it would be impossible without PBR. This is because the Cisco ASA does not support equal-cost multi-path (ECMP) across multiple interfaces; it only supports up to three equal cost routes on the same interface.
Note: Beginning with version 9.3(2), the Cisco ASA supports ECMP across multiple interfaces as long as those interfaces are part of the same “traffic zone”.
One of the most effective methods to overcome this load balancing restriction on the Cisco ASA is to redesign the network – use a router as the edge device and let the router take care of load balancing. You can’t really blame Cisco for not enabling advanced routing features on the ASA because its job function is a firewall and not routing.
There are other ways to overcome this restriction. For example, if BGP is configured on the Cisco ASA, then you can apply policies that can effectively load balance across links. But the ASA only started supporting BGP from version 9.2(1). Another method that people tried to use was NAT. You can find an article here that describes how to use NAT to achieve some form of load balancing, even though that setup can have several challenges and is not recommended in a production environment.
Enter PBR. The PBR on the Cisco ASA works similarly to the one on Cisco routers – we use route-maps to configure policies and these route-maps are then applied to an interface.
With PBR, we can match based on several criteria such as source and/or destination address/port, protocol and so on and then perform actions such as setting a specific next-hop, interface, QoS value and so on.
Let’s configure the network above in such a way that traffic from 192.168.10.0/24 will flow through ISP1 while traffic from 192.168.20.0/24 will flow through ISP2. Of course, we also have to put NAT into consideration and for this we will configure interface PAT.
interface GigabitEthernet0/0 nameif outside1 security-level 0 ip address 220.127.116.11 255.255.255.0 ! interface GigabitEthernet0/1 nameif inside security-level 100 ip address 10.254.254.1 255.255.255.0 ! interface GigabitEthernet0/2 nameif outside2 security-level 0 ip address 18.104.22.168 255.255.255.0 ! route inside 192.168.10.0 255.255.255.0 10.254.254.2 1 route inside 192.168.20.0 255.255.255.0 10.254.254.2 1 ! object network NET1 subnet 192.168.10.0 255.255.255.0 nat (inside,outside1) dynamic interface object network NET2 subnet 192.168.20.0 255.255.255.0 nat (inside,outside2) dynamic interface ! access-list NET1_ACL extended permit ip 192.168.10.0 255.255.255.0 any access-list NET2_ACL extended permit ip 192.168.20.0 255.255.255.0 any ! route-map PBR permit 10 match ip address NET1_ACL set ip next-hop 22.214.171.124 ! route-map PBR permit 20 match ip address NET2_ACL set ip next-hop 126.96.36.199 ! interface GigabitEthernet0/1 policy-route route-map PBR
In the configuration above, I have configured two ACLs: one to match source network of 192.168.10.0/24 to any destination and the other to match source network of 192.168.20.0/24 to any destination. These ACLs are then matched under the ‘PBR’ route map which is then applied under the inside (Gi0/1) interface.
Let us test this configuration. I have configured loopack interfaces on the ISP routers: ISP1 router has a loopback with address 188.8.131.52 while ISP2 router has a loopback with address 184.108.40.206. The two internal networks are also loopback interfaces on the INSIDE router. I will also enable the “debug policy-route” command on the ASA.
We will begin by pinging from 192.168.10.0/24 to 220.127.116.11. Based on our configuration, this traffic should go to ISP1.
INSIDE#ping 18.104.22.168 repeat 2 source lo10 Type escape sequence to abort. Sending 2, 100-byte ICMP Echos to 22.214.171.124, timeout is 2 seconds: Packet sent with a source address of 192.168.10.1 !! Success rate is 100 percent (2/2), round-trip min/avg/max = 76/92/108 ms ! ! ***Debug on Cisco ASA *** PBR-ASA# debug policy-route debug policy-route enabled at level 1 PBR-ASA# pbr: policy based route lookup called for 192.168.10.1/2 to 126.96.36.199/0 proto 1 sub_proto 8 received on interface inside pbr: First matching rule from ACL(1) pbr: route map PBR, sequence 10, permit; proceed with policy routing pbr: evaluating next-hop 188.8.131.52 pbr: policy based routing applied; egress_ifc = outside1 : next_hop = 184.108.40.206
As you can see from the debug on the ASA, the traffic matched sequence 10 in the PBR route map and the next-hop configured under that entry is 220.127.116.11. The ASA then tries to find the egress interface to which that next-hop address is connected. To make this determination, it looks at its input routing table to identify a connected route to the next-hop and then uses the interface associated with that connected route as the egress interface. We can view the input routing table using the show asp table routing input command:
With the egress interface determined, the packet is then forwarded. Notice that we didn’t have to configure a route to the final destination itself (18.104.22.168) on the Cisco ASA; it was enough to provide the next-hop (which is what routing is really).
Let us now test the second network (192.168.20.0/24) by pinging to 22.214.171.124.
INSIDE#ping 126.96.36.199 repeat 2 source lo20 Type escape sequence to abort. Sending 2, 100-byte ICMP Echos to 188.8.131.52, timeout is 2 seconds: Packet sent with a source address of 192.168.20.1 !! Success rate is 100 percent (2/2), round-trip min/avg/max = 12/14/16 ms ! ! ***Debug on Cisco ASA *** PBR-ASA# pbr: policy based route lookup called for 192.168.20.1/6 to 184.108.40.206/0 proto 1 sub_proto 8 received on interface inside pbr: First matching rule from ACL(2) pbr: route map PBR, sequence 20, permit; proceed with policy routing pbr: evaluating next-hop 220.127.116.11 pbr: policy based routing applied; egress_ifc = outside2 : next_hop = 18.104.22.168
That also works. But what happens if any of the ISPs goes down? Traffic from one network will effectively be blackholed. Thankfully, we can configure the ASA to first verify if the next-hop is up before it forwards traffic to it. Let’s change our configuration a bit:
! *** Change NAT rules to Twice NAT rules so that no matter the ISP being used, there will be a NAT rule available*** object network NET1 no nat (inside,outside1) dynamic interface object network NET2 no nat (inside,outside2) dynamic interface ! nat (inside,outside1) source dynamic NET1 interface nat (inside,outside2) source dynamic NET1 interface nat (inside,outside2) source dynamic NET2 interface nat (inside,outside1) source dynamic NET2 interface ! ! ***Configure SLA monitor and tracking for ISP routers' IP addresses *** sla monitor 1 type echo protocol ipIcmpEcho 22.214.171.124 interface outside1 frequency 10 sla monitor schedule 1 life forever start-time now track 1 rtr 1 reachability ! sla monitor 2 type echo protocol ipIcmpEcho 126.96.36.199 interface outside2 frequency 10 sla monitor schedule 2 life forever start-time now track 2 rtr 2 reachability ! ! *** Remove previous set action and use tracked routes under route-map *** route-map PBR permit 10 no set ip next-hop 188.8.131.52 set ip next-hop verify-availability 184.108.40.206 1 track 1 set ip next-hop verify-availability 220.127.116.11 2 track 2 ! route-map PBR permit 20 no set ip next-hop 18.104.22.168 set ip next-hop verify-availability 22.214.171.124 1 track 2 set ip next-hop verify-availability 126.96.36.199 2 track 1
As you can see from the configuration above, we can configure more than one action to be performed on traffic that matches a route map entry. You can find the order in which set actions are applied when multiple set statements are configured under a route map entry here.
To view our configuration, we can use the show route-map command:
To test this configuration, I will shut down the ISP1 router’s interface and then try to ping 188.8.131.52 from 192.168.10.0/24. Even though this traffic should normally be forwarded to ISP1, it should now be forwarded to ISP2 because of the “verify-availability” option.
After I shut down the ISP1 router’s interface, the ASA detects that the route is down:
However, the ping from 192.168.10.0/24 to 184.108.40.206 is still successful as discussed:
INSIDE#ping 220.127.116.11 repeat 2 source lo10 Type escape sequence to abort. Sending 2, 100-byte ICMP Echos to 18.104.22.168, timeout is 2 seconds: Packet sent with a source address of 192.168.10.1 !! Success rate is 100 percent (2/2), round-trip min/avg/max = 20/22/24 ms ! ! ***Debug on ASA shows that the next configured next-hop is used *** PBR-ASA(config)# pbr: policy based route lookup called for 192.168.10.1/11 to 22.214.171.124/0 proto 1 sub_proto 8 received on interface inside pbr: First matching rule from ACL(1) pbr: route map PBR, sequence 10, permit; proceed with policy routing pbr: verified next-hop 126.96.36.199 state is DOWN pbr: evaluating verified next-hop 188.8.131.52 pbr: policy based routing applied; egress_ifc = outside2 : next_hop = 184.108.40.206
On a final note, let me point out that traffic that does not match any entry in the route map or traffic that is permitted in an ACL but matches a deny entry of a route map is routed via the normal route lookup process.
For example, if we add a third internal network of 192.168.30.0/24, configure NAT for this network, and set the default route of the ASA via ISP1, this traffic will be forwarded to ISP1 because it won’t match any entry of the PBR route-map.
! ***Add new loopback interface on INSIDE router *** INSIDE(config)#interface lo30 INSIDE(config-if)#ip address 192.168.30.1 255.255.255.0 ! ! *** On ASA, Configure NAT rule for new network and also default route pointing to ISP1 *** PBR-ASA(config)# object network NET3 PBR-ASA(config-network-object)# subnet 192.168.30.0 255.255.255.0 PBR-ASA(config-network-object)# nat (inside,outside1) dynamic interface PBR-ASA(config-network-object)# exit PBR-ASA(config)# route inside 192.168.30.0 255.255.255.0 10.254.254.2 PBR-ASA(config)# route outside1 0 0 220.127.116.11
With this configuration, assuming that ISP1 is up, if we ping 18.104.22.168 from the 192.168.30.0/24 network, normal route lookup should be used to forward the packet as shown below:
INSIDE#ping 22.214.171.124 repeat 2 source lo30 Type escape sequence to abort. Sending 2, 100-byte ICMP Echos to 126.96.36.199, timeout is 2 seconds: Packet sent with a source address of 192.168.30.1 !! Success rate is 100 percent (2/2), round-trip min/avg/max = 16/16/16 ms ! ! *** Debug on Cisco ASA *** PBR-ASA(config)# debug policy-route debug policy-route enabled at level 1 PBR-ASA(config)# pbr: policy based route lookup called for 192.168.30.1/1 to 188.8.131.52/0 proto 1 sub_proto 8 received on interface inside pbr: no route policy found; skip to normal route lookup
This brings us to the end of this article, which I hope you have found informative. In this article, we have discussed policy based routing (PBR) on the Cisco ASA and also seen how to configure it.
I know there will be several scenarios to which PBR can be applied and we have only looked at one use case; however, you should be familiar enough with it now to play around with this feature.
References and Further reading
- CLI Book 1: Cisco ASA Series General Operations CLI Configuration Guide, 9.4: Policy Based Routing: http://www.cisco.com/c/en/us/td/docs/security/asa/asa94/configuration/general/asa-general-cli/route-policy-based.html