Order of operations : NAT + Routing + ACL
This is the 1st post in the series “router order of operations” and the purpose is to provide a comprehensive but clear enough overview of how operations are performed in the router and implications on what IP addresses to consider particularly when filtering with ACL.
Part1: NAT + Routing
“Routing” & “NAT” represent keystone to understand more complex situations:
Figure1: order of NAT+Routing
Rules:
– Traffic entering inside NAT interface is routed 1st then NATted
– Traffic entering outside NAT interface is NATted 1st then routed
IMPORTANT ===> For outside NAT : Make sure to have a route for the “outside local” to the outside NAT interface, or add the keyword “add-route” at the end of the “ip nat outside source static” command, otherwise, because of the “alias” feature inherited to NAT, the outside interface will respond on behalf of the outside local (if the prefix belongs to the outside interface segment) or will not be routed (if the prefix doesn’t belong to an attached subnet) (1)
Part2: NAT + Routing+ ACL
Figure2: order of NAT+Routing+ACL
Rules:
– Traffic entering inside NAT interface is always routed 1st then NATted.
– Traffic entering outside NAT interface is always NATted 1st then routed.
– Inbound ACL are performed before routing & NAT, alleviate processing overhead by filtering unnecessary traffic.
– Outbound ACL is performed after routing & NAT.
Next follows the practice lab in which, the previously stated rules are demonstrated:
Figure3: Lab topology
Note:
vhost1 and vhost2 routers are simulated inside one single router using VRF-Lite (Figure4), for more information about this technique.
Figure4: end-host deployment
Let’s suppose that the policy is to block ICMP traffic between the inside host 10.0.0.17 and the outside host 192.168.20.146, we will see that the involved IP address in the ACL changes according to the type of translation, the direction of the traffic and the NAT interface on which ACL is applied.
Each time only a single ACL is applied to a single interface, one single icmp packet is generated from inside to outside.
Here is the battery of tests to be done, observe debug results and refer to the associated rules and figures.
Tests :
Inside source | Inside NAT interface | Outside NAT interface | ||
ACL direction | inbound | outbound | inbound | Outbound |
Prefix to filter | Src=Inside local | Dst=Inside local | Dst=Outside local | Src=Outside local |
outside source | Inside NAT interface | Outside NAT interface | ||
ACL direction | inbound | outbound | inbound | outbound |
Prefix to filter | Dst=Outside local | Src=Outside local | Src=Outside global | Dst=Outside global |
A) – inside source NAT
NAT operation:
(inside local = 10.0.0.17) is seen from outside as (inside global = 192.168.20.131)
NAT(config)#ip nat inside source static 10.0.0.17 192.168.20.131
NAT#sh ip nat translations
Pro Inside global Inside local Outside local Outside global
— 192.168.20.131 10.0.0.17 — —
NAT#
For each case ICMP traffic is generated as follow:
Vhost#ping vrf vhost1 192.168.20.146 repeat 1
A1-ACL applied on outside nat interface
A1-a) inbound direction filter prefix dst=outside local
ip access-list ext outsideblock-in
10 deny ip any host 192.168.20.131
20 permit ip any any
interface FastEthernet0/1
ip access-group outsideblock-in in
NAT(config-if)#
*Mar 1 23:26:57.562: IP: tableid=0, s=10.0.0.17 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), routed via FIB
*Mar 1 23:26:57.566: NAT: s=10.0.0.17->192.168.20.131, d=192.168.20.146 [139]
*Mar 1 23:26:57.570: IP: s=192.168.20.131 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), g=192.168.20.130, len 100, forward
*Mar 1 23:26:57.706: IP: s=192.168.20.146 (FastEthernet0/1), d=192.168.20.131, len 100, access denied
Note order of operation: routing->NAT for ICMP echo and the returning traffic is blocked before entering the router.
*** Last outbound interface operation is traffic forwarding to next-hop
A1-b) outbound direction filter prefix src=outside local
ip access-list ext outsideblock-out
10 deny ip host 192.168.20.131 any
20 permit ip any any
interface FastEthernet0/1
ip access-group outsideblock-out out
NAT(config-if)#
*Mar 1 23:34:36.162: IP: tableid=0, s=10.0.0.17 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), routed via FIB
*Mar 1 23:34:36.166: NAT: s=10.0.0.17->192.168.20.131, d=192.168.20.146 [140]
*Mar 1 23:34:36.170: IP: s=192.168.20.131 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), len 100, access denied
NAT(config-if)#
Note the order of operations: routing->NAT, and then ACL blocked it outbound at the outside NAT interface.
A2-acl applied on inside nat interface
A2-a) inbound direction filter prefix src=inside local
ip access-list ext insideblock-in
10 deny ip host 10.0.0.17 any
20 permit ip any any
interface FastEthernet0/0
ip access-group insideblock-in in
Vhost#p vrf vhost1 192.168.20.146 repeat 1
Type escape sequence to abort.
Sending 1, 100-byte ICMP Echos to 192.168.20.146, timeout is 2 seconds:
U
Success rate is 0 percent (0/1)
Vhost#
NAT#
*Mar 1 22:53:08.410: IP: s=10.0.0.17 (FastEthernet0/0), d=192.168.20.146, len 100, access denied
NAT#
The debug confirm that inbound ACL at the inside NAT interface is performed 1st before any other operations and filter the inside local as source of the traffic
A2-b) outbound direction filter prefix dst=inside local
ip access-list ext insideblock-out
10 deny ip any host 10.0.0.17
20 permit ip any any
interface FastEthernet0/0
ip access-group insideblock-out out
Vhost#
Vhost#p vrf vhost1 192.168.20.146 repeat 1
Type escape sequence to abort.
Sending 1, 100-byte ICMP Echos to 192.168.20.146, timeout is 2 seconds:
.
Success rate is 0 percent (0/1)
Vhost#
NAT(config-if)#
*Mar 1 23:14:36.762: IP: tableid=0, s=10.0.0.17 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), routed via FIB
*Mar 1 23:14:36.766: NAT: s=10.0.0.17->192.168.20.131, d=192.168.20.146 [137]
*Mar 1 23:14:36.770: IP: s=192.168.20.131 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), g=192.168.20.130, len 100, forward
*Mar 1 23:14:36.918: NAT*: s=192.168.20.146, d=192.168.20.131->10.0.0.17 [137]
*Mar 1 23:14:36.922: IP: tableid=0, s=192.168.20.146 (FastEthernet0/1), d=10.0.0.17 (FastEthernet0/0), routed via FIB
*Mar 1 23:14:36.926: IP: s=192.168.20.146 (FastEthernet0/1), d=10.0.0.17 (FastEthernet0/0), len 100, access denied
Note the order of operations: Routing=>NAT for ICMP echo, but NAT=>Routing for ICMP reply and outbound ACL at the inside NAT interface
B) – outside source NAT
NAT operation:
(inside local = 10.0.0.17) is seen from outside as (inside global = 192.168.20.131)
(outside global = 192.168.20.146) is seen from inside as (outside local = 10.0.0.35)
As stated in (1) make sure to have a route for the outside local to the outside interface, or add the keywork “add-route” at the end of the “ip nat outside source static” command otherwise because of the “alias” feature inherited to NAT, the outside interface will respond on behalve of 10.0.0.35 (10.0.0.35 belongs to the outside inteface segment)
ip nat outside source static 192.168.20.146 10.0.0.35 add-route
or
ip nat outside source static 192.168.20.146 10.0.0.35
ip route 10.0.0.35 255.255.255.255 fa0/1
NAT(config)#do sh ip nat tra
Pro Inside global Inside local Outside local Outside global
— — — 10.0.0.35 192.168.20.146
— 192.168.20.131 10.0.0.17 — —
NAT(config)#
For each case ICMP traffic is generated from vhost1 (10.0.0.17) toward vhost2 (192.168.20.146) as follow :
Vhost#ping vrf vhost1 10.0.0.35 repeat 1
Here are normal operations without filtering:
NAT(config)#
*Mar 2 02:07:20.597: IP: tableid=0, s=10.0.0.17 (FastEthernet0/0), d=10.0.0.35 (FastEthernet0/1), routed via RIB
*Mar 2 02:07:20.605: NAT: s=10.0.0.17->192.168.20.131, d=10.0.0.35 [204]
*Mar 2 02:07:20.605: NAT: s=192.168.20.131, d=10.0.0.35->192.168.20.146 [204]
*Mar 2 02:07:20.609: IP: s=192.168.20.131 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), g=192.168.20.146, len 100, forward
*Mar 2 02:07:20.721: NAT*: s=192.168.20.146->10.0.0.35, d=192.168.20.131 [204]
*Mar 2 02:07:20.725: NAT*: s=10.0.0.35, d=192.168.20.131->10.0.0.17 [204]
*Mar 2 02:07:20.733: IP: tableid=0, s=10.0.0.35 (FastEthernet0/1), d=10.0.0.17 (FastEthernet0/0), routed via FIB
*Mar 2 02:07:20.737: IP: s=10.0.0.35 (FastEthernet0/1), d=10.0.0.17 (FastEthernet0/0), g=10.0.0.34, len 100, forward
NAT(config)#
Note the order of operations: routing=>NAT then NAT=>Routing for the returning traffic
B1-acl applied on outside nat interface
B1-a) inbound filter prefix src=outside global
ip access-list ext outsideblock-in
10 deny ip host 192.168.20.146 any
20 permit ip any any
interface FastEthernet0/1
ip access-group outsideblock-in in
NAT(config-if)#
*Mar 2 02:16:45.621: IP: tableid=0, s=10.0.0.17 (FastEthernet0/0), d=10.0.0.35 (FastEthernet0/1), routed via RIB
*Mar 2 02:16:45.625: NAT: s=10.0.0.17->192.168.20.131, d=10.0.0.35 [207]
*Mar 2 02:16:45.629: NAT: s=192.168.20.131, d=10.0.0.35->192.168.20.146 [207]
*Mar 2 02:16:45.633: IP: s=192.168.20.131 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), g=192.168.20.146, len 100, forward
*Mar 2 02:16:45.745: IP: s=192.168.20.146 (FastEthernet0/1), d=192.168.20.131, len 100, access denied
B1-b) outbound filter prefix dst=outside global
ip access-list ext outsideblock-out
10 deny ip any host 192.168.20.146
20 permit ip any any
interface FastEthernet0/1
ip access-group outsideblock-out out
NAT(config-if)#
*Mar 2 02:19:31.969: IP: tableid=0, s=10.0.0.17 (FastEthernet0/0), d=10.0.0.35 (FastEthernet0/1), routed via RIB
*Mar 2 02:19:31.973: NAT: s=10.0.0.17->192.168.20.131, d=10.0.0.35 [208]
*Mar 2 02:19:31.977: NAT: s=192.168.20.131, d=10.0.0.35->192.168.20.146 [208]
*Mar 2 02:19:31.981: IP: s=192.168.20.131 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), len 100, access denied
B2- acl applied on inside nat interface
B2-a) inbound filter prefix dst=outside local
ip access-list ext insideblock-in
10 deny ip any host 10.0.0.35
20 permit ip any any
interface FastEthernet0/0
ip access-group insideblock-in in
NAT(config-if)#
*Mar 2 02:10:45.613: IP: s=10.0.0.17 (FastEthernet0/0), d=10.0.0.35, len 100, access denied
B2-b) outbound filter prefix src=outside local
ip access-list ext insideblock-out
10 deny ip host 10.0.0.35 any
20 permit ip any any
interface FastEthernet0/0
ip access-group insideblock-out out
NAT(config-if)#
*Mar 2 02:12:11.393: IP: tableid=0, s=10.0.0.17 (FastEthernet0/0), d=10.0.0.35 (FastEthernet0/1), routed via RIB
*Mar 2 02:12:11.397: NAT: s=10.0.0.17->192.168.20.131, d=10.0.0.35 [206]
*Mar 2 02:12:11.401: NAT: s=192.168.20.131, d=10.0.0.35->192.168.20.146 [206]
*Mar 2 02:12:11.405: IP: s=192.168.20.131 (FastEthernet0/0), d=192.168.20.146 (FastEthernet0/1), g=192.168.20.146, len 100, forward
*Mar 2 02:12:11.517: NAT*: s=192.168.20.146->10.0.0.35, d=192.168.20.131 [206]
*Mar 2 02:12:11.517: NAT*: s=10.0.0.35, d=192.168.20.131->10.0.0.17 [206]
*Mar 2 02:12:11.525: IP: tableid=0, s=10.0.0.35 (FastEthernet0/1), d=10.0.0.17 (FastEthernet0/0), routed via FIB
*Mar 2 02:12:11.529: IP: s=10.0.0.35 (FastEthernet0/1), d=10.0.0.17 (FastEthernet0/0), len 100, access denied
Conclusion
– Write down your expectations in term of address translation, routing and filtering.
– Make sure to choose your IP addresses to filter, the ACL direction and the interface to which ACL is applied with the order of operations in mind.