Aug 28, 2010

Static NAT - Does the order of commands matter?

I've implemented the following scenario to demonstrate the behavior of the ASA/PIX that we could see after to change the order of the Static NAT rules.



The web server is located at dmz network and is published to the Internet using a Static NAT. The hosts located at inside network have access to the Internet and the dmz using a PAT overload over the IP addresses assigned to the firewall interfaces. The relevant settings to this article are presented below.

interface Ethernet0
 nameif outside
 security-level 0
 ip address 192.168.0.1 255.255.255.0
interface Ethernet1
 nameif inside
 security-level 100
 ip address 192.168.100.1 255.255.255.0
interface Ethernet2
 nameif dmz
 security-level 50
 ip address 192.168.50.1 255.255.255.0
access-list inside_access_in extended permit ip any any
access-list dmz_access_in extended permit ip any any
access-list outside_access_in extended permit tcp any host 192.168.0.10 eq www
global (outside) 1 interface
global (dmz) 1 interface
static (dmz,outside) 192.168.0.10 192.168.50.10 netmask 255.255.255.255
access-group outside_access_in in interface outside
access-group inside_access_in in interface inside
access-group dmz_access_in in interface dmz
route outside 0.0.0.0 0.0.0.0 192.168.0.254 1


Using the presented settings, I ran a packet-tracer to simulate HTTP traffic from an inside host to the web server:

asa# packet-tracer input inside tcp 192.168.100.20 80 192.168.50.10 80

Phase: 1
Type: FLOW-LOOKUP
Subtype:
Result: ALLOW
Config:
Additional Information:
Found no matching flow, creating a new flow

Phase: 2
Type: ROUTE-LOOKUP
Subtype: input
Result: ALLOW
Config:
Additional Information:
in 192.168.50.0 255.255.255.0 dmz

Phase: 3
Type: ACCESS-LIST
Subtype: log
Result: ALLOW
Config:
access-group inside_access_in in interface inside
access-list inside_access_in extended permit ip any any
Additional Information:

Phase: 4
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 5
Type: NAT
Subtype:
Result: ALLOW
Config:
nat (inside) 1 192.168.100.0 255.255.255.0
  match ip inside 192.168.100.0 255.255.255.0 dmz any
    dynamic translation to pool 1 (192.168.50.1 [Interface PAT])
    translate_hits = 1, untranslate_hits = 0
Additional Information:
Dynamic translate 192.168.100.20/80 to 192.168.50.1/247 using netmask 255.255.255.255

Phase: 6
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
nat (inside) 1 192.168.100.0 255.255.255.0
  match ip inside 192.168.100.0 255.255.255.0 outside any
    dynamic translation to pool 1 (192.168.0.1 [Interface PAT])
    translate_hits = 0, untranslate_hits = 0
Additional Information:

Phase: 7
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
static (dmz,outside) 192.168.0.10 192.168.50.10 netmask 255.255.255.255
  match ip dmz host 192.168.50.10 outside any
    static translation to 192.168.0.10
    translate_hits = 0, untranslate_hits = 0
Additional Information:


Phase: 8
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 9
Type: FLOW-CREATION
Subtype:
Result: ALLOW
Config:
Additional Information:
New flow created with id 2, packet dispatched to next module

Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: dmz
output-status: up
output-line-status: up
Action: allow


Although the result is indicating that the traffic would be allowed and forwarded properly, the phase 7 indicates that the static between dmz and outside would be applied to the replies from the server to the host. Trying to fix this issue, I implemented an Outside Static Identity NAT to match the traffic between inside and dmz, resulting in the rules below.
 
asa# sh run static
static (dmz,outside) 192.168.0.10 192.168.50.10 netmask 255.255.255.255
static (dmz,inside) 192.168.50.10 192.168.50.10 netmask 255.255.255.255

 
The same packet-tracer ran previously, now generated the following result:
 
asa# packet-tracer input inside tcp 192.168.100.20 80 192.168.50.10 80

Phase: 1
Type: FLOW-LOOKUP
Subtype:
Result: ALLOW
Config:
Additional Information:
Found no matching flow, creating a new flow

Phase: 2
Type: UN-NAT
Subtype: static
Result: ALLOW
Config:
static (dmz,inside) 192.168.50.10 192.168.50.10 netmask 255.255.255.255
  match ip dmz host 192.168.50.10 inside any
    static translation to 192.168.50.10
    translate_hits = 0, untranslate_hits = 1
Additional Information:
NAT divert to egress interface dmz
Untranslate 192.168.50.10/0 to 192.168.50.10/0 using netmask 255.255.255.255

Phase: 3
Type: ACCESS-LIST
Subtype: log
Result: ALLOW
Config:
access-group inside_access_in in interface inside
access-list inside_access_in extended permit ip any any
Additional Information:

Phase: 4
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 5
Type: NAT
Subtype:
Result: ALLOW
Config:
nat (inside) 1 192.168.100.0 255.255.255.0
  match ip inside 192.168.100.0 255.255.255.0 dmz any
    dynamic translation to pool 1 (192.168.50.1 [Interface PAT])
    translate_hits = 2, untranslate_hits = 0
Additional Information:
Dynamic translate 192.168.100.20/80 to 192.168.50.1/511 using netmask 255.255.255.255

Phase: 6
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
nat (inside) 1 192.168.100.0 255.255.255.0
  match ip inside 192.168.100.0 255.255.255.0 outside any
    dynamic translation to pool 1 (192.168.0.1 [Interface PAT])
    translate_hits = 0, untranslate_hits = 0
Additional Information:

Phase: 7
Type: NAT
Subtype: rpf-check
Result: ALLOW
Config:
static (dmz,inside) 192.168.50.10 192.168.50.10 netmask 255.255.255.255
  match ip dmz host 192.168.50.10 inside any
    static translation to 192.168.50.10
    translate_hits = 0, untranslate_hits = 1
Additional Information:

Phase: 8
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
static (dmz,outside) 192.168.0.10 192.168.50.10 netmask 255.255.255.255
  match ip dmz host 192.168.50.10 outside any
    static translation to 192.168.0.10
    translate_hits = 0, untranslate_hits = 0
Additional Information:

Phase: 9
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 10
Type: FLOW-CREATION
Subtype:
Result: ALLOW
Config:
Additional Information:
New flow created with id 3, packet dispatched to next module

Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: dmz
output-status: up
output-line-status: up
Action: allow

 
We can see the new static rule being matched, however the phase 8 is indicating a conflict between the existing static rules. In order to fix this issue, I removed the static between dmz and outside, then added it again, changing the order of the commands:
 
asa# sh run static
static (dmz,inside) 192.168.50.10 192.168.50.10 netmask 255.255.255.255
static (dmz,outside) 192.168.0.10 192.168.50.10 netmask 255.255.255.255

 
I ran the same packet-tracer again:
 
asa# packet-tracer input inside tcp 192.168.100.20 80 192.168.50.10 80

Phase: 1
Type: FLOW-LOOKUP
Subtype:
Result: ALLOW
Config:
Additional Information:
Found no matching flow, creating a new flow

Phase: 2
Type: UN-NAT
Subtype: static
Result: ALLOW
Config:
static (dmz,inside) 192.168.50.10 192.168.50.10 netmask 255.255.255.255
  match ip dmz host 192.168.50.10 inside any
    static translation to 192.168.50.10
    translate_hits = 0, untranslate_hits = 2
Additional Information:
NAT divert to egress interface dmz
Untranslate 192.168.50.10/0 to 192.168.50.10/0 using netmask 255.255.255.255

Phase: 3
Type: ACCESS-LIST
Subtype: log
Result: ALLOW
Config:
access-group inside_access_in in interface inside
access-list inside_access_in extended permit ip any any
Additional Information:

Phase: 4
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 5
Type: NAT
Subtype:
Result: ALLOW
Config:
nat (inside) 1 192.168.100.0 255.255.255.0
  match ip inside 192.168.100.0 255.255.255.0 dmz any
    dynamic translation to pool 1 (192.168.50.1 [Interface PAT])
    translate_hits = 3, untranslate_hits = 0
Additional Information:
Dynamic translate 192.168.100.20/80 to 192.168.50.1/37 using netmask 255.255.255.255

Phase: 6
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
nat (inside) 1 192.168.100.0 255.255.255.0
  match ip inside 192.168.100.0 255.255.255.0 outside any
    dynamic translation to pool 1 (192.168.0.1 [Interface PAT])
    translate_hits = 0, untranslate_hits = 0
Additional Information:

Phase: 7
Type: NAT
Subtype: rpf-check
Result: ALLOW
Config:
static (dmz,inside) 192.168.50.10 192.168.50.10 netmask 255.255.255.255
  match ip dmz host 192.168.50.10 inside any
    static translation to 192.168.50.10
    translate_hits = 0, untranslate_hits = 2
Additional Information:

Phase: 8
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
static (dmz,inside) 192.168.50.10 192.168.50.10 netmask 255.255.255.255
  match ip dmz host 192.168.50.10 inside any
    static translation to 192.168.50.10
    translate_hits = 0, untranslate_hits = 2
Additional Information:

Phase: 9
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 10
Type: FLOW-CREATION
Subtype:
Result: ALLOW
Config:
Additional Information:
New flow created with id 4, packet dispatched to next module

Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: dmz
output-status: up
output-line-status: up
Action: allow


Now we can not see a match to the static between dmz and outside anymore. Thus, the conflict was fixed and the traffic would be allowed and forwarded properly.
 
 
asa(config)# end
asa# wr mem

No comments:

Post a Comment