Reflexive access-lists is a way of filtering traffic where only return traffic
is allowed if it belongs to a session initiated on the “inside”. In a regular
access-list we can use the keyword established for filtering but that only
looks at if the TCP flag ACK has been set which is the case for all packets
except the first one in a session. This isn’t really stateful filtering.
We will use a very simple topology with three routers, diagram is below.
The objective is to allow all TCP from R3 to R1. R1 should be able to use ping
and traceroute and to establish routing peerings with R2.
If you want to try this lab yourself you can download topology, initial configs
and final configs from here.
Lets start by doing a telnet from R3 to R1 and reverse just to see that we have
reachability and that nothing is being filtered.
R3#telnet 133.16.12.1
Trying 133.16.12.1 … Open
User Access Verification
Password:
R1>
R1#telnet 133.16.23.3
Trying 133.16.23.3 … Open
User Access Verification
Password:
R3>
Everything working as expected. Now lets start creating access-lists. We will
be filtering on R2 Fa0/0. Traffic from R3 to R1 will be outbound and traffic
from R1 to R3 will be inbound.
ip access-list extended OUTBOUND
permit tcp any any reflect MYREFLECT
permit icmp any any reflect MYREFLECT
The keyword here is reflect, we need to match MYREFLECT on the inbound ACL to make
it reflexive. If we want to add more statements like UDP we can do that but
remember to use the reflect keyword.
Now we create the inbound ACL.
ip access-list extended INBOUND
permit eigrp any any
permit icmp any any echo-reply
permit icmp any any time-exceeded
permit icmp any any port-unreachable
evaluate MYREFLECT
We need to explicitally allow ICMP since ICMP is not stateful. We also need
to allow routing because the traffic is terminated on the router.
Apply ACL to R2 Fa0/0.
R2(config)#int fa0/0
R2(config-if)#ip access-group INBOUND in
R2(config-if)#ip access-group OUTBOUND out
If our configuration is correct telnet from R3 to R1 should work but not
the other way around.
R3#telnet 133.16.12.1
Trying 133.16.12.1 … Open
User Access Verification
Password:
R1>
Still working. We can also see matches in the ACL.
R2#sh ip access-lists OUTBOUND
Extended IP access list OUTBOUND
10 permit tcp any any reflect MYREFLECT (20 matches)
20 permit icmp any any reflect MYREFLECT
Now lets try from R1 to R3.
R1#telnet 133.16.23.3
Trying 133.16.23.3 …
% Destination unreachable; gateway or host down
That was denied. Are we still able to ping R1 from R3?
R3#ping 133.16.12.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 133.16.12.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 12/53/152 ms
There is also matches in the ACL.
R2#sh ip access-lists OUTBOUND
Extended IP access list OUTBOUND
10 permit tcp any any reflect MYREFLECT (20 matches)
20 permit icmp any any reflect MYREFLECT (7 matches)
Traceroute from R1.
R1#traceroute 133.16.23.3
Type escape sequence to abort.
Tracing the route to 133.16.23.3
1 133.16.12.2 !A * !A
Can R1 form an EIRGP peering?
*Mar 1 01:26:23.351: %DUAL-5-NBRCHANGE: IP-EIGRP(0) 1: Neighbor 133.16.12.1
(FastEthernet0/0) is up: new adjacency
*Mar 1 01:26:24.355: %SYS-5-CONFIG_I: Configured from console by console
R2#sh ip access-lists INBOUND
Extended IP access list INBOUND
10 permit eigrp any any (33 matches)
20 permit icmp any any echo-reply (5 matches)
30 permit icmp any any time-exceeded
40 permit icmp any any port-unreachable
50 evaluate MYREFLECT
So reflexive access-lists can be a very useful feature. If you have
a lab task that says that only traffic initiated from inside should
be allowed back in it’s a good bet to use reflexive access-lists.
If you download the .net file remember to set the IOS image dir and your working dir.
Does the router actually create a session table, or would an attacker be able to get in with by initiating a SYN packet?
It does create a session table. I just did a vol2 lab where this scenario came up again.
Rack24R4#show ip access-lists MY_REFLECT
Reflexive IP access list MY_REFLECT
permit tcp host 204.12.24.254 eq telnet host 162.24.0.5 eq 18106 (56 matches) (time left 292)
permit icmp host 204.12.24.254 host 162.24.0.5 (5 matches) (time left 68)
permit tcp host 204.12.24.254 eq telnet host 162.24.0.5 eq 56858 (17 matches) (time left 63)
You can see that IP and ports have to match so it would be very difficult to guess the ports used in the session except for the well known ports. Also you need the correct IP so you would have to spoof that and hope that RPF check is not done.