Network Security

ZBF Port-Maps: Inspecting Applications on Non-Standard Ports

ZBF port-map mapping HTTP to port 8080 alongside the system default port 80
In: Network Security, CCIE, Labs

You have a Zone-Based Firewall inspecting traffic on your Cisco IOS XE router, you write match protocol http to inspect web traffic to your DMZ, and one particular application just will not pass. The app runs on TCP 8080, not 80, and to the ZBF protocol inspector it may as well be invisible. This is not a bug. It is the single most common surprise engineers hit once they move past the basics of ZBF, and the fix is a port-map. This article is part of the PingLabz Infrastructure Security cluster and builds directly on the Zone-Based Firewall pillar, so if you have not met zones and zone-pairs yet, start there and come back.

Everything below was captured from a real cat8000v running IOS XE 17.18.02 in Cisco Modeling Labs. No output has been invented.

Protocol classification is port-based by default

When you write match protocol http in an inspect class-map, you are asking IOS to recognize HTTP. The obvious question is: how does the router know a packet is HTTP? For the well-known protocols, the answer is simpler than you might hope. IOS ships with a built-in table that maps each named protocol to its standard port, and http is defined as TCP port 80. So match protocol http really means "match TCP traffic on port 80" (plus some application-aware behavior on top for protocols that support it).

That default is fine right up until an application does not use the standard port. A management console on 8080, an internal API on 8000, a legacy web app someone stood up on 8888: all of them are HTTP by every meaningful definition, but none of them are on port 80, so match protocol http does not classify them. The inspect policy never sees them as HTTP, the class does not match, and (assuming class-default drops) the traffic is dropped. You stare at a policy that looks correct and traffic that will not pass, because the mismatch is not in your policy logic. It is in the port table underneath it.

The fix: ip port-map

The ip port-map command lets you extend (or narrow) the port definition for any protocol. To tell IOS that HTTP also lives on TCP 8080, you add one line in global configuration:

EDGE1(config)#ip port-map http port tcp 8080

That is the entire fix. You have not touched the class-map, the policy-map, or the zone-pair. You have changed the definition of what "http" means at the classification layer, and every match protocol http statement on the box immediately inherits the new port. Verify it with show ip port-map http:

EDGE1#show ip port-map http
Default mapping:  http                 tcp port 80                         system defined
Default mapping:  http                 tcp port 8080                       user defined

Read that output carefully, because it tells the whole story. There are now two entries for HTTP. The first, TCP port 80, is marked system defined: it is the built-in default that shipped with the image, and adding your own port did not remove it. The second, TCP port 8080, is marked user defined: that is your addition. From this moment on, match protocol http in any inspect class-map matches HTTP on both port 80 and port 8080. Your DMZ app on 8080 is now visible to the firewall, gets Layer 7 HTTP inspection, and passes the policy it was silently failing before.

The system defined versus user defined labeling is worth internalizing. Port-maps are additive by default: your custom port sits alongside the standard one, not on top of it. That means enabling inspection for an application on a non-standard port does not disable inspection on the standard port, so you do not accidentally break the rest of your web traffic while fixing the one app.

When you actually reach for a port-map

There are two situations where port-maps stop being trivia and become the thing that unblocks your afternoon.

App on a non-standard port
An internal web app, API, or admin console runs on 8080 / 8000 / 8888 but you still want it Layer 7 inspected as HTTP. Add the port with ip port-map http port tcp 8080 and the existing match protocol http covers it.
Narrowing a protocol with a list
You can scope a port-map to a specific set of hosts or ports with an ACL using the list <acl> keyword, so the custom mapping only applies where you intend rather than globally.

The first case is the everyday one: some service is not on its textbook port and you want the firewall to treat it as the protocol it really is. Instead of writing a crude match protocol tcp that matches all TCP indiscriminately, you keep the specific, application-aware match protocol http and simply teach IOS the extra port. You preserve the Layer 7 awareness (and the inspection quality that comes with it) rather than falling back to a blunt port-agnostic match.

The second case is the inverse and is where the list keyword earns its place. A port-map does not have to be a broad "this port is now this protocol everywhere" statement. Attach an ACL with the list option and the mapping applies only to the traffic that ACL permits, letting you say "treat TCP 8080 as HTTP, but only to these DMZ servers" rather than globally reclassifying 8080 across the whole router. That precision keeps a port-map from becoming a policy side effect you forget about six months later.

The syntax generalizes to any protocol

Nothing about port-maps is HTTP-specific. The ip port-map command takes any protocol name IOS knows and any transport and port you give it, so the same technique that rescued a web app on 8080 works for a mail service, a database, or a custom TCP application you want inspected as a named protocol rather than as anonymous TCP. The shape is always ip port-map <protocol> port {tcp | udp} <port>, and the corresponding show ip port-map <protocol> always distinguishes the built-in system defined entries from your user defined ones the same way you saw for HTTP.

Because the mapping is additive and lives at the classification layer, it is also a low-risk change to make. You are not editing an active policy-map or bouncing a zone-pair; you are adding a row to a lookup table that class-maps consult. Existing inspection for the standard port keeps working, and the new port simply starts matching. That safety is exactly why the port-map is the right tool for "make the firewall see this app as HTTP" rather than loosening a class-map to match all TCP, which would surrender the Layer 7 awareness you configured ZBF to get in the first place.

How port-maps fit the wider ZBF picture

Port-maps live at the classification layer, one level below the class-map. The chain runs: the port-map table defines what each protocol name means; the class-map type inspect uses match protocol against that table; the policy-map type inspect decides what to do with the class; and the zone-pair binds that policy to a direction. When traffic mysteriously fails to match a protocol you are certain it should, the port-map table is the first place to look, because a class-map can only match what the classifier can see. This is exactly the kind of layered structure that nested class-maps also lean on, and it is why understanding classification pays off across every ZBF policy you write.

A practical habit: when you adopt a policy from documentation or a previous engineer and traffic on an unusual port will not pass, run show ip port-map <protocol> before you touch anything else. It takes five seconds and it tells you immediately whether the classifier even knows about the port in question. Half the "ZBF is dropping my traffic" tickets are really "the protocol is on a port the classifier was never told about" tickets.

Key takeaways

  • ZBF protocol matching is port-based. match protocol http only recognizes HTTP on the system-defined port 80 by default, so an app on 8080 is invisible to the HTTP inspector.
  • One command fixes it: ip port-map http port tcp 8080 teaches IOS that 8080 is also HTTP, and every existing match protocol http immediately covers it.
  • Port-maps are additive. show ip port-map http shows the system defined port 80 and your user defined port 8080 side by side; adding a port does not remove the standard one.
  • Use them two ways: to Layer 7 inspect an app on a non-standard port, or (with the list <acl> keyword) to narrow a protocol mapping to specific hosts instead of applying it globally.
  • Check the classifier first. When ZBF drops traffic that "should" match a protocol, show ip port-map often reveals the port was never mapped in the first place.

Port-maps are a small but high-leverage piece of the router-integrated firewall story in the PingLabz Infrastructure Security cluster. To see where this classification work sits in the full policy engine, return to the Zone-Based Firewall pillar, then move on to nested class-maps for layered policy.

Written by
More from Ping Labz
Private VLAN association with isolated and community secondaries
VLAN

Private VLANs: Isolating Hosts That Share a Subnet

Private VLANs isolate hosts that share a subnet, at Layer 2, without a subnet per host. Primary, isolated, and community secondary VLANs on Cisco IOS XE, with the classic DMZ use case and real show output.
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.