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 188.8.131.52 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 184.108.40.206 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.