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.