Object groups are the difference between an ACL you can read and one you cannot. Without them, an ACL that permits HTTP, HTTPS, and SSH from three jump-host source addresses to four DMZ servers takes 36 lines. With them, the same intent collapses to one. They also unlock a NAT configuration model where an inside subnet, a DMZ host, and an outside translation pool are first-class named objects you can reference everywhere by name. This article covers the four object-group types on the Cisco ASA, how they nest, and the actual show output from the lab's running OUTSIDE_IN ACL and NAT pool.
Object groups belong to the Cisco ASA Fundamentals tier. Once they click, the rest of the platform feels less arbitrary because every ACL, NAT rule, and policy-map starts referencing the same named building blocks.
Objects vs Object Groups
The ASA has two related but distinct ideas:
| Construct | Holds | Created with | Referenced from |
|---|---|---|---|
| Object | One thing: one host, one subnet, one range, one service port, one FQDN | object network NAME or object service NAME | ACLs, NAT rules, policy-maps |
| Object group | A list of things, optionally a list of other groups | object-group network NAME, object-group service NAME, etc. | ACLs, NAT rules (some), policy-maps |
Single objects are useful for NAT (one host on the inside translates to one address on the outside) and as readable handles for one specific endpoint. Object groups are useful when you have collections (three jump-host source IPs, four DMZ servers, the standard "web ports" set of 80 and 443).
The Four Object Group Types
Each type wraps a specific kind of value.
| Type | Holds | Used in |
|---|---|---|
object-group network NAME | IPv4/IPv6 hosts, subnets, ranges, FQDNs, and other network groups | ACL source/destination, NAT real/mapped, AAA target, route-map match |
object-group service NAME | TCP/UDP port lists (single, range), or unified protocol+port pairs (TCP/80 + UDP/53) | ACL service field, NAT service translation, inspection class-maps |
object-group protocol NAME | IP protocol numbers/names (tcp, udp, icmp, gre, esp, 50) | ACL protocol field |
object-group icmp-type NAME | ICMP type codes (echo, echo-reply, time-exceeded, unreachable) | ACL ICMP type field |
Network and service groups are 95% of what you use. Protocol and ICMP-type groups are useful but situational.
Network Object Groups
A network group is a list of network endpoints. Each entry is one of: a host, a subnet, a range, an FQDN, or another network group (nesting).
ASA-PERIM(config)# object-group network ADMIN-JUMP-HOSTS
ASA-PERIM(config-network-object-group)# description Permanent admin jump hosts
ASA-PERIM(config-network-object-group)# network-object host 10.10.0.50
ASA-PERIM(config-network-object-group)# network-object host 10.10.0.51
ASA-PERIM(config-network-object-group)# network-object host 10.10.0.52
ASA-PERIM(config-network-object-group)# network-object 10.99.0.0 255.255.255.0
ASA-PERIM(config-network-object-group)# group-object PARTNER-MGMT
The last line is nesting: PARTNER-MGMT is presumably another object-group network defined elsewhere, and its members get folded into ADMIN-JUMP-HOSTS. Nesting is one level deep and resolves at compile time, so there is no runtime cost.
FQDN entries are also supported and resolve at intervals (default every 60 seconds):
ASA-PERIM(config)# object-group network EXTERNAL-VENDORS
ASA-PERIM(config-network-object-group)# network-object fqdn updates.vendor-a.com
ASA-PERIM(config-network-object-group)# network-object fqdn licensing.vendor-b.com
FQDN-based ACLs are very useful for outbound-allowlists ("this server can only reach these specific cloud APIs") but require functioning DNS on the ASA, which means a working dns server-group DefaultDNS with reachable resolvers and a sane dns name-server list.
Service Object Groups
The modern syntax is unified service groups, which include the protocol in each entry:
ASA-PERIM(config)# object-group service WEB-PORTS
ASA-PERIM(config-service-object-group)# service-object tcp eq 80
ASA-PERIM(config-service-object-group)# service-object tcp eq 443
ASA-PERIM(config-service-object-group)# service-object tcp eq 8080
ASA-PERIM(config-service-object-group)# service-object tcp eq 8443
Used in an ACL:
access-list OUTSIDE_IN extended permit object-group WEB-PORTS any object-group DMZ-WEB-FARM
That single ACL line expands internally to four (one per port) and the ASA reports each line in show access-list with its own hit counter.
The legacy syntax is protocol-locked service groups, where the protocol is declared at the top:
ASA-PERIM(config)# object-group service WEB-TCP-LEGACY tcp
ASA-PERIM(config-service-object-group)# port-object eq 80
ASA-PERIM(config-service-object-group)# port-object eq 443
ASA-PERIM(config-service-object-group)# port-object range 8000 8100
Both forms still work. The unified syntax is more flexible (you can mix TCP and UDP in one group) and is what the configuration generator uses by default for new groups created via ASDM. Use the unified form for new work.
Protocol and ICMP-Type Groups
Less common but useful. Protocol groups simplify rules that need to allow several IP protocols between the same source and destination:
ASA-PERIM(config)# object-group protocol IPSEC-PROTOS
ASA-PERIM(config-protocol-object-group)# protocol-object esp
ASA-PERIM(config-protocol-object-group)# protocol-object ah
ASA-PERIM(config-protocol-object-group)# protocol-object udp
ASA-PERIM(config-protocol-object-group)# protocol-object 50
ICMP-type groups are how you write ACLs that allow only specific ICMP message types (the safe-by-default approach instead of permit icmp any any):
ASA-PERIM(config)# object-group icmp-type SAFE-ICMP
ASA-PERIM(config-icmp-object-group)# icmp-object echo-reply
ASA-PERIM(config-icmp-object-group)# icmp-object time-exceeded
ASA-PERIM(config-icmp-object-group)# icmp-object unreachable
Used in:
access-list OUTSIDE_IN extended permit icmp any any object-group SAFE-ICMP
This permits the diagnostic ICMP types that traceroute and PMTU discovery need, without permitting the rest. A nice middle ground between "all ICMP" and "no ICMP."
Real Lab: How Objects and Groups Wire Together in an ACL
From the lab's ASA-PERIM, this is the running OUTSIDE_IN ACL after the changes from Sessions 1 and 2:
ASA-PERIM# show access-list OUTSIDE_IN | begin OUTSIDE_IN
access-list OUTSIDE_IN; 5 elements; name hash: 0xe01d8199
access-list OUTSIDE_IN line 1 extended deny tcp host 198.51.100.99 any (hitcnt=1) (Last Hit=00:01:09 UTC May 10 2026)
access-list OUTSIDE_IN line 2 extended permit tcp any object DMZ-WEB eq www (hitcnt=1) (Last Hit=23:27:41 UTC May 9 2026)
access-list OUTSIDE_IN line 3 extended permit tcp any object DMZ-WEB eq https (hitcnt=2) (Last Hit=00:01:09 UTC May 10 2026)
access-list OUTSIDE_IN line 4 extended permit icmp any object DMZ-WEB (hitcnt=2) (Last Hit=01:55:20 UTC May 10 2026)
access-list OUTSIDE_IN line 5 extended deny ip any any log informational interval 300 (hitcnt=59) (Last Hit=01:55:47 UTC May 10 2026)
Notice that object DMZ-WEB appears as the destination on lines 2, 3, and 4. DMZ-WEB is a single network object (not a group), defined elsewhere as:
ASA-PERIM(config)# show running-config object id DMZ-WEB
object network DMZ-WEB
host 192.168.50.10
nat (dmz,outside) static 198.51.100.10
One object definition does double duty: it gives the ACL a readable name for the DMZ web server, AND defines the static NAT that publishes 192.168.50.10 to the outside as 198.51.100.10. Change the IP in one place and both the ACL and the NAT rule follow.
Real Lab: Auto NAT With Network Objects
Auto NAT (also called Object NAT) is configured inside an object network definition. The Section 2 NAT block from show nat detail:
ASA-PERIM# show nat detail | begin Auto NAT
Auto NAT Policies (Section 2)
1 (dmz) to (outside) source static DMZ-WEB 198.51.100.10
translate_hits = 87, untranslate_hits = 134
Source - Origin: 192.168.50.10/32, Translated: 198.51.100.10/32
2 (inside) to (outside) source dynamic INSIDE-TRANSIT interface
translate_hits = 0, untranslate_hits = 0
Source - Origin: 10.10.0.0/24, Translated: 203.0.113.2/30
3 (inside) to (outside) source dynamic INSIDE-NET interface
translate_hits = 4521, untranslate_hits = 0
Source - Origin: 10.10.10.0/24, Translated: 203.0.113.2/30
Three rules, all defined inside three object network blocks (DMZ-WEB, INSIDE-TRANSIT, INSIDE-NET). Auto NAT auto-orders by specificity, so the /32 host (DMZ-WEB) sits at line 1 even though it was configured later. INSIDE-NET racked up 4,521 forward translations (real-world inside hosts hitting the internet via PAT to the outside interface). DMZ-WEB has more reverse than forward hits because it is a public-facing server (more inbound flows opened from the internet than outbound flows initiated by the server itself).
The Built-In Service Objects
The ASA ships with a long list of named ports you can use as keywords without defining your own. www, https, ssh, smtp, domain, snmp, tftp, ntp, and dozens more all parse as themselves. access-list OUTSIDE_IN extended permit tcp any object DMZ-WEB eq www uses www as a built-in alias for port 80; you do not need to define a WWW object.
For ports the ASA does not have a name for, use the number: eq 8443, range 5060 5061, gt 1024. The full list of built-in names is in the ? output for access-list ... eq.
Object Groups Make ACLs Readable Six Months Later
Compare two ways of writing the same intent. Without object groups:
access-list OUTSIDE_IN extended permit tcp host 10.10.0.50 host 192.168.50.10 eq 80
access-list OUTSIDE_IN extended permit tcp host 10.10.0.50 host 192.168.50.10 eq 443
access-list OUTSIDE_IN extended permit tcp host 10.10.0.50 host 192.168.50.10 eq 22
access-list OUTSIDE_IN extended permit tcp host 10.10.0.50 host 192.168.50.20 eq 80
access-list OUTSIDE_IN extended permit tcp host 10.10.0.50 host 192.168.50.20 eq 443
access-list OUTSIDE_IN extended permit tcp host 10.10.0.50 host 192.168.50.20 eq 22
access-list OUTSIDE_IN extended permit tcp host 10.10.0.51 host 192.168.50.10 eq 80
... [repeat for each src x dst x port]
With object groups:
object-group network ADMIN-JUMP
network-object host 10.10.0.50
network-object host 10.10.0.51
network-object host 10.10.0.52
object-group network DMZ-SERVERS
network-object host 192.168.50.10
network-object host 192.168.50.20
object-group service ADMIN-PORTS
service-object tcp eq 22
service-object tcp eq 80
service-object tcp eq 443
!
access-list OUTSIDE_IN extended permit object-group ADMIN-PORTS object-group ADMIN-JUMP object-group DMZ-SERVERS
One ACL line, with the intent ("admins reach DMZ servers on admin ports") visible at first read. Adding a fourth jump host means one new network-object line; the ACL itself never changes. This is also the version that survives an audit: the auditor looks at OUTSIDE_IN and sees one rule, not 18.
Verify Object Groups
The ASA expands object groups internally. show access-list shows you both the compact form and the expanded form:
ASA-PERIM# show access-list OUTSIDE_IN | begin OUTSIDE_IN
access-list OUTSIDE_IN; 9 elements; name hash: 0xe01d8199
alert-interval 300
access-list OUTSIDE_IN line 1 extended permit object-group ADMIN-PORTS object-group ADMIN-JUMP object-group DMZ-SERVERS (hitcnt=44)
access-list OUTSIDE_IN line 1 extended permit tcp host 10.10.0.50 host 192.168.50.10 eq 22 (hitcnt=12)
access-list OUTSIDE_IN line 1 extended permit tcp host 10.10.0.50 host 192.168.50.10 eq 80 (hitcnt=8)
access-list OUTSIDE_IN line 1 extended permit tcp host 10.10.0.50 host 192.168.50.10 eq 443 (hitcnt=10)
... [continues for each src x dst x port]
The compact form (the first line at "line 1") shows the ACL the way you wrote it. The expanded entries beneath show every src/dst/port permutation with its individual hit counter, which is how you tell whether a specific permutation is being used.
Inspect a single group with:
ASA-PERIM# show running-config object-group id ADMIN-JUMP
object-group network ADMIN-JUMP
description Permanent admin jump hosts
network-object host 10.10.0.50
network-object host 10.10.0.51
network-object host 10.10.0.52
Or list every group with show running-config object-group (no id).
Renaming and Removing Objects Safely
Renaming an object is not a single command. The ASA's rename object works at the object level but not for object groups; the safe procedure for either is: create the new name, switch references, then delete the old.
Removing a group is rejected if anything still references it:
ASA-PERIM(config)# no object-group network ADMIN-JUMP
ERROR: removing object-group (ADMIN-JUMP) not allowed, it is being used.
To find every reference, ironically use the same show running-config | include ADMIN-JUMP grep, which finds the ACL and NAT lines that point at it. Update those first, then the delete succeeds.
Key Takeaways
Network and service object groups collapse repetitive ACLs into single readable lines and let one named object do double duty for both ACL and NAT. The four group types (network, service, protocol, icmp-type) cover almost everything you need; nesting is supported one level. Use the unified service-object syntax for new work because it lets you mix TCP and UDP in one group.
The lab's OUTSIDE_IN ACL and Auto NAT pool both reference the same DMZ-WEB object: change the IP in one place, both follow. That single principle is what makes object-driven ASA configurations maintainable years after the engineer who built them has left.
Next in this cluster: Cisco ASA Initial Setup from CLI, the day-0 bootstrap that gets a fresh ASA from "out of the box" to "passing traffic." For the broader picture, the Cisco ASA pillar has the full reading order. For deeper ACL and NAT walkthroughs, see ACL configuration and NAT explained.