ASA

Cisco ASA Inside/Outside/DMZ Configuration Walkthrough

Cisco ASA Inside/Outside/DMZ Configuration Walkthrough
In: ASA, Fundamentals

The classic Cisco ASA topology is three zones with three security levels: inside (your trusted users at level 100), outside (the internet at level 0), and a DMZ (your public-facing servers at level 50, somewhere in the middle). This article walks the entire build end to end on the lab's ASAv 9.23 - interfaces, addressing, security levels, NAT for outbound users, NAT for inbound web publishing, ACLs in both directions, and the show-output that proves traffic is actually flowing. The result is a small but realistic perimeter you could drop into a branch office tomorrow.

This is one of the longer Fundamentals walkthroughs in the Cisco ASA cluster. It assumes you have already bootstrapped the ASA from CLI and read the security-levels primer; everything else gets shown here.

Topology and Address Plan

ZoneInterfaceSubnetSecurity levelRole
insideGigabitEthernet0/110.10.0.0/24100User LAN, default gateway 10.10.0.254 (the ASA)
dmzGigabitEthernet0/2192.168.50.0/2450Public-facing servers; DMZ-WEB at 192.168.50.10
outsideGigabitEthernet0/0203.0.113.0/300Point-to-point link to the ISP, ASA at .2, ISP at .1
NAT pool(virtual)198.51.100.0/24n/aPublic block for static NAT (DMZ-WEB to .10)

Three real interfaces, three zones, three security levels. The numeric levels (100/50/0) drive the implicit allow/deny matrix between zones - high to low is permitted by default, low to high requires an explicit ACL.

Step 1: Interface Configuration

ASA-PERIM(config)# interface GigabitEthernet0/0
ASA-PERIM(config-if)#  description Outside-to-ISP
ASA-PERIM(config-if)#  nameif outside
ASA-PERIM(config-if)#  security-level 0
ASA-PERIM(config-if)#  ip address 203.0.113.2 255.255.255.252
ASA-PERIM(config-if)#  no shutdown
!
ASA-PERIM(config)# interface GigabitEthernet0/1
ASA-PERIM(config-if)#  description Inside-to-LAN
ASA-PERIM(config-if)#  nameif inside
ASA-PERIM(config-if)#  security-level 100
ASA-PERIM(config-if)#  ip address 10.10.0.254 255.255.255.0
ASA-PERIM(config-if)#  no shutdown
!
ASA-PERIM(config)# interface GigabitEthernet0/2
ASA-PERIM(config-if)#  description DMZ-Servers
ASA-PERIM(config-if)#  nameif dmz
ASA-PERIM(config-if)#  security-level 50
ASA-PERIM(config-if)#  ip address 192.168.50.1 255.255.255.0
ASA-PERIM(config-if)#  no shutdown

Verify with show interface ip brief:

ASA-PERIM# show interface ip brief
Interface                  IP-Address      OK? Method Status                Protocol
GigabitEthernet0/0         203.0.113.2     YES manual up                    up
GigabitEthernet0/1         10.10.0.254     YES manual up                    up
GigabitEthernet0/2         192.168.50.1    YES manual up                    up
Management0/0              unassigned      YES unset  administratively down down

Three data interfaces up. See interfaces and VLAN trunks if any of these are not coming up the way you expect.

Step 2: Default Route to the ISP

ASA-PERIM(config)# route outside 0.0.0.0 0.0.0.0 203.0.113.1 1

Verify the routing table now has the connected subnets plus the default:

ASA-PERIM# show route

Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP
       D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
       E1 - OSPF external type 1, E2 - OSPF external type 2, V - VPN
       i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
       ia - IS-IS inter area, * - candidate default, U - per-user static route
       o - ODR, P - periodic downloaded static route, + - replicated route
       SI - Static InterVRF
Gateway of last resort is 203.0.113.1 to network 0.0.0.0

S*    0.0.0.0 0.0.0.0 [1/0] via 203.0.113.1, outside
C        10.10.0.0 255.255.255.0 is directly connected, inside
L        10.10.0.254 255.255.255.255 is directly connected, inside
C        192.168.50.0 255.255.255.0 is directly connected, dmz
L        192.168.50.1 255.255.255.255 is directly connected, dmz
C        203.0.113.0 255.255.255.252 is directly connected, outside
L        203.0.113.2 255.255.255.255 is directly connected, outside

The default route via outside (the S* line) is the gateway of last resort. Connected and local routes for each of the three zones are present.

Step 3: Outbound PAT for Inside Users

Inside users at 10.10.0.0/24 cannot reach the internet directly because their addresses are RFC1918. The ASA needs to NAT them to the outside interface IP. The simplest pattern is Auto NAT on a network object:

ASA-PERIM(config)# object network INSIDE-NET
ASA-PERIM(config-network-object)#  subnet 10.10.0.0 255.255.255.0
ASA-PERIM(config-network-object)#  nat (inside,outside) dynamic interface

Read it as: "anything sourced from 10.10.0.0/24 on inside, headed toward outside, gets PATed to the outside interface IP." That single rule covers all outbound user traffic. The security-level 100 to 0 rule lets the traffic pass without an explicit ACL.

Step 4: Publish DMZ-WEB Inbound

The DMZ web server lives at 192.168.50.10. It needs a public IP (we will use 198.51.100.10) and an inbound ACL because traffic flowing low-to-high (outside 0 to dmz 50) is denied by default.

The static NAT, again with an Auto NAT pattern:

ASA-PERIM(config)# object network DMZ-WEB
ASA-PERIM(config-network-object)#  host 192.168.50.10
ASA-PERIM(config-network-object)#  nat (dmz,outside) static 198.51.100.10

The ACL that opens 80, 443, and ICMP echo:

ASA-PERIM(config)# access-list OUTSIDE_IN extended permit tcp any object DMZ-WEB eq www
ASA-PERIM(config)# access-list OUTSIDE_IN extended permit tcp any object DMZ-WEB eq https
ASA-PERIM(config)# access-list OUTSIDE_IN extended permit icmp any object DMZ-WEB
ASA-PERIM(config)# access-list OUTSIDE_IN extended deny ip any any log informational interval 300
ASA-PERIM(config)# access-group OUTSIDE_IN in interface outside

Two important details. First, the ACL references object DMZ-WEB, which the ASA resolves to 192.168.50.10 (the real address) because that is what is in the object. The ASA evaluates ACLs against post-NAT real addresses on inbound, which is the modern (8.3+) behavior. Second, the explicit deny ip any any log at the bottom does the same thing as the implicit deny, but it generates a syslog every time it fires. That is the line we use to debug "why is traffic getting blocked" issues, as covered in ACL troubleshooting.

Step 5: ICMP Inspection (For Pings to Come Back)

ICMP is connectionless, which means without inspection an outbound echo request leaves the firewall but the inbound echo reply gets dropped (no matching conn entry). The default global policy includes inspect icmp, which makes ICMP behave like a stateful protocol on the ASA. If ping does not work from inside out, this is one of the first things to check.

ASA-PERIM# show service-policy global | include icmp
      Inspect: icmp, packet 1244, lock fail 0, drop 0, reset-drop 0

The packet counter climbing tells you ICMP inspection is firing. See inspection engines for the full MPF model.

Step 6: End-to-End Verification

Now exercise the policy from both directions.

Outbound: inside-host to 8.8.8.8

Generate a flow from inside-host on the inside subnet:

inside-host:~# ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=51 time=23.4 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=51 time=24.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=51 time=23.8 ms

And confirm on the ASA:

ASA-PERIM# show xlate count
14 in use, 16 most used

ASA-PERIM# show xlate local 10.10.0.50
Flags: D - DNS, e - extended, I - identity, i - dynamic, r - portmap,
       s - static, T - twice, N - net-to-net
ICMP PAT from inside:10.10.0.50 1/12345 to outside:203.0.113.2 1/45678 flags ri idle 0:00:01 timeout 0:00:30

The outbound ping created an ICMP xlate entry. The inside source was PATed to the outside interface IP (203.0.113.2). When the echo reply comes back, the ASA matches it to the xlate, NATs the destination back to 10.10.0.50, and forwards it.

Inbound: 8.8.8.8 to DMZ-WEB on https

From outside, hit the public IP:

outside-tester:~# curl -sI -k https://198.51.100.10
HTTP/1.1 200 OK
Server: nginx/1.20.2

And on the ASA:

ASA-PERIM# show conn address 192.168.50.10
14 in use, 16 most used

TCP outside  8.8.8.8:51234 dmz  192.168.50.10:443, idle 0:00:01, bytes 1132, flags UIO

ASA-PERIM# show access-list OUTSIDE_IN | include hitcnt
access-list OUTSIDE_IN line 3 extended permit tcp any object DMZ-WEB eq https (hitcnt=2)

The conn entry shows the established TCP flow. The hit counter on line 3 of OUTSIDE_IN ticks up. The U flag in the conn flags means "up," meaning the TCP three-way handshake completed - which it could only do because both directions of the flow (the SYN from outside, the SYN/ACK from DMZ-WEB) made it through the firewall.

Cross-zone: DMZ to inside (Should Be Blocked)

By default, traffic from a lower security level (DMZ at 50) to a higher one (inside at 100) is denied. Test it:

dmz-host:~# ping -c 1 10.10.0.50
PING 10.10.0.50 (10.10.0.50) 56(84) bytes of data.
^C
--- 10.10.0.50 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss

ASA-PERIM# show asp drop frame | include acl-drop
Flow is denied by configured rule (acl-drop)            1612

The acl-drop counter ticks up because the implicit deny on the dmz interface (no ACL bound, default deny low-to-high) blocked the packet. show asp drop counters covers what each reason actually means.

If you do need DMZ-to-inside reachability for a specific application (a backup server pulling from a database, for example), add an explicit ACL on the dmz interface that permits exactly that flow.

The Full Working Config in One Block

Everything from this article in a single paste-able config:

!
hostname ASA-PERIM
domain-name pinglabz.lab
enable password Cisco1@3
!
interface GigabitEthernet0/0
 description Outside-to-ISP
 nameif outside
 security-level 0
 ip address 203.0.113.2 255.255.255.252
 no shutdown
interface GigabitEthernet0/1
 description Inside-to-LAN
 nameif inside
 security-level 100
 ip address 10.10.0.254 255.255.255.0
 no shutdown
interface GigabitEthernet0/2
 description DMZ-Servers
 nameif dmz
 security-level 50
 ip address 192.168.50.1 255.255.255.0
 no shutdown
!
route outside 0.0.0.0 0.0.0.0 203.0.113.1 1
!
object network INSIDE-NET
 subnet 10.10.0.0 255.255.255.0
 nat (inside,outside) dynamic interface
!
object network DMZ-WEB
 host 192.168.50.10
 nat (dmz,outside) static 198.51.100.10
!
access-list OUTSIDE_IN extended permit tcp any object DMZ-WEB eq www
access-list OUTSIDE_IN extended permit tcp any object DMZ-WEB eq https
access-list OUTSIDE_IN extended permit icmp any object DMZ-WEB
access-list OUTSIDE_IN extended deny ip any any log informational interval 300
access-group OUTSIDE_IN in interface outside
!
class-map inspection_default
 match default-inspection-traffic
policy-map global_policy
 class inspection_default
  inspect icmp
service-policy global_policy global
!
end
write memory

What This Does and Does Not Cover

This baseline gets a working three-zone perimeter with outbound PAT and inbound DMZ publishing. It does not yet have:

Each of those layers builds on the same baseline. Get the three zones, the routes, the NAT, and the ACLs right first; everything else assumes you have done so.

Key Takeaways

The classic inside/outside/DMZ ASA build is a small set of ordered steps: bring up three named interfaces with their security levels, add a default route, configure PAT for the inside subnet, add a static NAT for the DMZ server, and write an inbound ACL for the public-facing services. From there, show xlate tells you outbound NAT is firing, show conn tells you flows exist, and show access-list tells you which ACL line is matching.

The implicit security-level matrix does most of the work: outbound (high to low) is permitted by default, inbound (low to high) requires an explicit ACL. Read the security-levels article if any of that feels arbitrary; it sets up everything else.

Next: Cisco ASA Static Routing and Default Route Configuration covers tracked routes, route metrics, and multi-WAN failover. The full reading order is on the Cisco ASA pillar.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.