Reflexive access lists
By stretch | Tuesday, November 25, 2008 at 7:02 a.m. UTC
A typical approach to network perimeter security is to allow outbound traffic not explicitly denied, and to deny inbound traffic unless it is explicitly allowed. Although simple in concept, this approach requires significant considerations regarding the return path of internally initiated sessions. Consider the following scenario:
Clients resides on the secure 192.168.0.0/24 subnet, which is connected to the Internet by R1. We can place both inbound and outbound access lists on R1's F0/1 interface to restrict communication between our internal network and the Internet.
For the sake of an example, let's assume we want to allow web traffic from the client to web servers on the Internet. We can leave outbound traffic (from client to server) unrestricted by simply not including an ACL, but how would we restrict return traffic from the Internet? Obviously we can't simply deny all traffic, or nothing would work. Nor can we allow all traffic, as it would leave the secure subnet exposed.
We also can't simply allow all TCP traffic with a source port of 80, as an attacker could easily send malicious traffic using 80 as his source port. And we can't restrict inbound traffic to certain source IP addresses, as we'd have to create a new entry for every server we want to access on the Internet. We could allow inbound traffic to the client's source port, but this is typically a randomly-chosen high port number which can't be practically matched with static configuration. But what if we could record and match each source address/port pair automatically?
Enter reflexive access lists. To employ reflexive ACLs, three access lists are actually needed: one for inbound traffic, one for outbound traffic, and one (the reflexive ACL) to keep track of dynamic entries. Outbound traffic matched in the outbound ACL is reflected to the reflexive ACL; that is, the source and destination addresses and ports are swapped and the entry is recorded in the reflexive ACL with an expiration timer. Traffic in the other direction is matched against the inbound ACL, which in turn evaluates the entries in the reflexive ACL.
First let's create an outbound ACL named Egress to reflect entries for outgoing packets:
Router(config)# ip access-list extended Egress Router(config-ext-nacl)# permit ip any any reflect Mirror Router(config-ext-nacl)# interface f0/1 Router(config-if)# ip access-group out Egress
Any packet matched by Egress will be reflected into our reflexive ACL, named Mirror. Since Egress matches all IP traffic, we reflect entries for TCP, UDP, and ICMP. If we wanted, we could have specified only TCP, for example, to only match TCP traffic. While TCP sessions are relatively simple to track, IOS can also roughly track UDP and ICMP "sessions," even though these aren't true session-oriented protocols.
Now when a client in 192.168.0.0/24 initiates a TCP session to a server on the Internet we can see a reflected entry is created in Mirror:
Router# show ip access-lists Mirror Reflexive IP access list Mirror permit tcp host 126.96.36.199 eq www host 192.168.0.123 eq 62839 (7 matches) (time left 294)
Now, to put our reflexive ACL into action! We'll create an inbound ACL named Ingress to evaluate Mirror, and apply it inbound to FastEthernet0/1:
Router(config)# ip access-list extended Ingress Router(config-ext-nacl)# evaluate Mirror Router(config-ext-nacl)# interface f0/1 Router(config-if)# ip access-group in Ingress
Now packets inbound on FastEthernet0/1 are only allowed in if they are permitted by Ingress, which is essentially just a reference to Mirror. Note, however, that we are free to add normal entries to Ingress both before and after the
evaluate statement if we want. With all three components in place, we can see the static outbound entries (Egress), the static inbound entries (Ingress), and the dynamic inbound entries (Mirror):
Router# show ip access-lists Extended IP access list Egress 10 permit ip any any reflect Mirror (76 matches) Extended IP access list Ingress 10 evaluate Mirror Reflexive IP access list Mirror permit tcp host 188.8.131.52 eq www host 192.168.0.123 eq 62839 (7 matches) (time left 248)
One last item to note is the expiration timer on the Mirror entry. This timer is reset to 300 seconds with each new packet that would cause the reflection. If no new traffic has been seen before the timer expires, the entry is erased. Additionally, when the router detects a session has been closed (for example, using the FIN flag in TCP), the timer is immediately reduced and the entry is removed shortly thereafter.
Posted in Security
November 25, 2008 at 9:13 a.m. UTC
But consider that router generated traffic is not reflected and therefore return traffic will be blocked by the ingress ACL. Important when using routing protocols on the same link!
November 25, 2008 at 1:36 p.m. UTC
Please tell me, is CBAC (for simple L4 and L3 protocols, ie. TCP, UDP, ICMP...) using the same mechanism as reflexive access-lists. Works pretty much the same, doesn't it?
November 25, 2008 at 2:21 p.m. UTC
Very informative stretch, thanks.
Two questions though: one is the same as Praetor's, the other is related to NAT. In your example you are NAT overloading from 192.168.0.0/24 to your WAN IP, so wouldn't this ACL for this particular scenario be overkill? Doesn't NAT overload do this same process by default? Are there any benefits to applying this to a NATed interface? Thanks.
November 25, 2008 at 4:58 p.m. UTC
Awesome explanation..Yeah i agree with Praetor...does CBAC work the same way... if yes where can one find the logs or the "reflexive access-list" created by CBAC?
November 26, 2008 at 9:13 a.m. UTC
Nice, can see some use for it rather than using CBAC, CBAC limited, you could have a requirement to open a particular protocol not covered by CBAC, ALSO CBAC inspection chew up the processor by adding in alot of inspections
November 26, 2008 at 11:04 a.m. UTC
CBAC is more robust, as it can monitor applications that utilize multiple ports when establishing a session, like FTP.
December 14, 2008 at 4:27 p.m. UTC
I prefer CBAC when possible, but not all ios images have the CBAC features. CBAC looks as the communication in much more detail. However, I have seen a couple of occasions that inspecting TCP absolutely killed performance for an application.
March 11, 2009 at 9:35 a.m. UTC
hm, can somebody explain me why this feature is only usable with named ACLs ?
seems so with IOS: C2600-ADVSECURITYK9-M Version 12.4(21)
April 23, 2010 at 3:57 a.m. UTC
Just Amazing, everyday there is something new on your blog to learn. Thanks a lot
May 28, 2011 at 8:09 a.m. UTC
June 6, 2012 at 10:33 a.m. UTC
great post. understood in a single reading. thanks.
December 21, 2012 at 12:54 p.m. UTC
Amazing explanation. its much easier to understand than cisco website.
July 27, 2013 at 11:42 p.m. UTC
thank you very much
August 16, 2013 at 9:20 p.m. UTC
Great post. Thank you.
January 17, 2014 at 2:08 p.m. UTC
Dude, how can I send you a coin ?, of course you deserve more than that. You always save me time when I look for explanations.
Question: Reflexive access list, Is there any other way to explain it more easily than this article do ?.
Answer: NO WAY.
A million thanks.
November 19, 2014 at 9:38 p.m. UTC
Great post, and especially good where CBAC won't work due to IOS constraints, e.g. 2651XM with 12.3T IOS that only has 32MB flash. Can't upgrade to 12.4T or later due to flash size. 12.3T version has a bug that causes most inspected traffic to get dropped.
Reflexive ACL works the same way as CBAC for the most part, and doesn't suffer from the inspection bug.
April 4, 2016 at 7:24 a.m. UTC
Great post. Amazing explanation..
Thanks you very much !!!!
April 24, 2016 at 9:17 a.m. UTC
Thumb up for the post (the technical details), but the challenge required in order to post comments was the funniest and inspired surprise of this page. Very nice.
May 22, 2016 at 10:29 p.m. UTC
Really Good Explanation of How Reflexive ACL works.