Network Security

Control Plane Protection (CPPr): Beyond CoPP with Port-Filtering

CPPr subdivides the control plane into host, transit and cef-exception subinterfaces and adds port-filtering, next to real CoPP police captures from CML.
CoPP police policy dropping 709 of 800 flood packets to protect the control plane
In: Network Security, CCIE, Labs

Every routed packet your device forwards is handled in hardware, but the packets addressed to the device - routing updates, SSH sessions, ARP, ICMP to a local interface, SNMP polls - get punted up to the CPU. That CPU is the control plane, and it is the single most valuable target on the box. Flood it and you can knock out the routing protocol adjacencies that keep the network converged. Control Plane Policing (CoPP) was the first answer to that problem, and Control Plane Protection (CPPr) is its finer-grained evolution. This article is part of the infrastructure security cluster, and it picks up exactly where CoPP leaves off.

We will explain the CPPr model in full - the way it carves the control plane into separate subinterfaces, the port-filtering feature that drops traffic to closed control-plane ports, and the per-protocol queue-thresholding that stops one protocol starving another. Then we will be honest about the platform: the Cisco IOL image we lab on does not expose the CPPr subinterfaces, so we prove the closely related CoPP behaviour with real captures from our CML lab and present the CPPr configuration from Cisco's documentation with a clear platform note.

The control plane, and why CoPP came first

When a packet is destined for the router itself, it cannot be switched in CEF like transit traffic. It is "punted" to the route processor for handling. Legitimate control traffic (an OSPF hello, a BGP keepalive, an SSH login) is low volume. An attacker who sends a high rate of packets to a router IP, or a misbehaving host looping ICMP, generates punts at a rate the CPU was never sized for. The result is high CPU, dropped protocol adjacencies, and a control plane that falls over while the data plane is still technically "up".

CoPP fixes this by attaching a QoS policy to a logical control-plane interface. You classify control traffic into classes, then police or drop each class. It is a single, aggregate policy applied to everything punted to the CPU. It is simple, universally supported, and, as we show below, genuinely effective. If you want the full CoPP build, read our deep dive on Control Plane Policing (CoPP).

What CPPr adds: three control-plane subinterfaces

CoPP treats the entire punt path as one bucket. CPPr's core idea is that not all punted traffic is equal, so it should not be policed as one lump. CPPr subdivides the control plane into three logical subinterfaces, each of which you can classify and police independently:

control-plane host

Traffic destined to any interface on the router itself - SSH and Telnet to a management IP, SNMP, ICMP echo to a local address, and the packets that feed the routing protocols. This is where port-filtering and per-protocol queue-thresholding live, because it is the surface an attacker aims at.

control-plane transit

Traffic that is software-switched through the router (transit packets that still touch the CPU, for example when a feature forces process switching). Policing here protects the CPU from transit that should never have been punted in volume.

control-plane cef-exception

Packets that CEF cannot switch and must escalate - TTL-expired packets, packets needing an ICMP unreachable, options-set packets, ARP. Policing this class blunts attacks built on deliberately un-switchable traffic.

The immediate benefit is isolation. With CoPP, a flood of cef-exception traffic (say, a TTL-expiry attack) shares one policer with your SSH management sessions. With CPPr, you can hand cef-exception a tight budget and leave the host path room to breathe, so one class of abuse cannot starve another.

Port-filtering: drop traffic to closed control-plane ports

This is the feature that has no CoPP equivalent, and it is the reason CPPr exists. Port-filtering, applied to the host subinterface, drops packets addressed to closed or non-listening TCP and UDP ports on the router before they are ever queued to the CPU. Think about what that means: if the box is not running an HTTP server, there is no legitimate reason for anyone to send it TCP 80. Normally those packets still punt to the CPU, get processed far enough to generate a reset, and cost you cycles. A port scan (exactly the kind of thing our Nmap lab generates) becomes a cheap way to load the control plane.

Port-filtering closes that door. The router tracks which control-plane ports are actually open, and the port-filter policy silently drops traffic to everything else at the punt stage. An attacker probing closed ports gets nothing and spends none of your CPU. It is the control-plane analogue of the anti-scan hardening you do on the data plane.

Queue-thresholding: no single protocol can flood the queue

The third CPPr feature is per-protocol queue-thresholding on the host subinterface. Each protocol punted to the CPU (for example, a specific Layer 4 port or protocol type) gets a maximum number of packets allowed in the punt queue at once. Once a protocol hits its threshold, further packets of that protocol are dropped even though the aggregate queue still has room. This stops a single noisy protocol from consuming the entire punt queue and blocking everything else - a subtler failure mode than raw rate, and one a single CoPP policer does not address.

The CPPr configuration model (from Cisco documentation)

CPPr is configured much like CoPP - class-maps and a policy-map - but the policy is applied to a specific control-plane subinterface rather than the aggregate. A representative build looks like this (this is the documented model; see the honest platform note below):

! Classify traffic destined to closed ports for the port-filter
class-map type port-filter PLZ-PORTFILTER
 match closed-ports
policy-map type port-filter PLZ-PF-POLICY
 class PLZ-PORTFILTER
  drop

! Aggregate policer for the host subinterface
class-map match-all PLZ-HOST-MGMT
 match access-group 120
policy-map PLZ-CPPR-HOST
 class PLZ-HOST-MGMT
  police 32000 conform-action transmit exceed-action drop

! Apply per-subinterface
control-plane host
 service-policy type port-filter input PLZ-PF-POLICY
 service-policy input PLZ-CPPR-HOST
control-plane cef-exception
 service-policy input PLZ-CEF-POLICY

Notice the two things CoPP cannot do: a type port-filter policy that matches closed-ports, and a service-policy bound specifically to control-plane host rather than the whole control plane. That granularity is the entire value proposition.

Honest platform note: our IOL image exposes CoPP, not CPPr

We build these labs on Cisco IOL-XE (17.18) in CML. CPPr needs the control-plane host / transit / cef-exception subinterfaces, and this image does not implement them. The verification commands simply do not exist on the platform:

EDGE1#show control-plane host open-ports
                       ^
% Invalid input detected at '^' marker.

EDGE1#configure terminal
EDGE1(config)#control-plane host
                            ^
% Invalid input detected at '^' marker.

That is a real result, and we are not going to fabricate CPPr show output to paper over it. CPPr's subinterface model, port-filtering, and queue-thresholding are hardware and IOS-XE platform features you should verify on your own gear (many ISR and ASR platforms expose them). What our lab can prove, cleanly and repeatably, is the closely related CoPP behaviour that CPPr builds on. So that is what we captured.

What we could prove: real CoPP policing an ICMP flood

On EDGE1 we applied a deliberately tight CoPP policy - police ICMP to the control plane at 8 kbps and drop the excess:

access-list 150 permit icmp any any
class-map match-all PLZ-ICMP-CLASS
 match access-group 150
policy-map PLZ-COPP
 class PLZ-ICMP-CLASS
  police 8000 conform-action transmit exceed-action drop
control-plane
 service-policy input PLZ-COPP

Then our Debian attacker at 192.168.99.100 flooded the router's control plane with a fast ICMP stream:

j@llmbits$ sudo ping -f -c 800 -i 0.002 192.168.99.1
--- 192.168.99.1 ping statistics ---
800 packets transmitted, 91 received, 88.625% packet loss, time 7446ms

88.6% loss. The router only answered 91 of the 800 flood packets, and the reason is on the policer counters, which match the attack exactly:

EDGE1#show policy-map control-plane
 Control Plane
  Service-policy input: PLZ-COPP
    Class-map: PLZ-ICMP-CLASS (match-all)
      Match: access-group 150
      police:
          cir 8000 bps, bc 1500 bytes
        conformed 91 packets, 8918 bytes; actions:
          transmit
        exceeded 709 packets, 69482 bytes; actions:
          drop
        conformed 1000 bps, exceeded 2000 bps

Read those numbers: 91 conformed (transmitted) plus 709 exceeded (dropped) equals the 800 packets sent, and the 91 conformed is exactly what the VM got back. The CPU only ever processed the 91 conforming packets; the other 709 were dropped before they reached the process level. That is a control plane defending itself in real time, with counters you can point at.

CPPr as the finer-grained evolution of CoPP

Everything you just saw the CoPP policer do, CPPr does too - but per-subinterface, plus port-filtering and queue-thresholding on top. The mental model is a straight line:

CoPPOne aggregate policer on the whole control plane. Simple, universal, proven here.
CPPr subinterfacesSeparate host / transit / cef-exception policers so one class cannot starve another.
CPPr port-filterDrop traffic to closed control-plane ports at the punt stage - defeats port scans cheaply.
CPPr queue-thresholdCap each protocol's share of the punt queue so no single protocol floods it.

The practical guidance: deploy CoPP everywhere - it is supported on virtually every platform and it works, as our capture shows. Where your platform exposes the CPPr subinterfaces, layer CPPr on top for the extra isolation and the port-filter. They are not competitors; CPPr is CoPP with a finer knife. For a head-to-head on when each is the right call, see our companion article on CoPP vs CPPr.

Deploying it without locking yourself out

Two cautions before you push either policy. First, police conservatively at the start. Our 8 kbps ICMP policer was deliberately brutal to make the drops obvious in a lab; on a production box a policer that tight on the wrong class will drop your own management traffic and routing adjacencies. Baseline the normal punt rate first, then set the conform rate with headroom above it. Second, always leave an explicit permit for the protocols that keep the box reachable and converged - SSH from your management range, the routing protocols, ARP, and BFD if you run it. A CoPP or CPPr policy that accidentally starves OSPF will flap every adjacency on the device, which is a self-inflicted outage that looks exactly like the attack you were defending against.

With CPPr specifically, the port-filter is the safest single win to deploy first: dropping traffic to genuinely closed ports has no legitimate victim, so it rarely causes collateral damage. The per-protocol queue-thresholds and the per-subinterface policers are where you want a maintenance window and a rollback plan, because a mis-scoped class-map on the host subinterface can quietly drop the very sessions you use to fix it.

Key Takeaways

  • The control plane is the CPU, and it is the target. Packets punted to the route processor are the ones that take a router down, so they need their own protection.
  • CoPP is one aggregate policer. Our lab proved it: an 8 kbps policer dropped 709 of 800 flood packets (88.6% loss) and only let 91 conforming packets reach the CPU.
  • CPPr subdivides the control plane into host, transit, and cef-exception subinterfaces so one class of traffic cannot starve another.
  • Port-filtering is CPPr's unique feature - it drops traffic to closed control-plane ports at the punt stage, making port scans cheap to absorb.
  • Queue-thresholding caps each protocol's share of the punt queue.
  • Platform honesty: our IOL image does not expose the CPPr subinterfaces (the commands return % Invalid input), so verify CPPr on hardware that supports it - but CoPP is universal and should be on every box.

Control-plane protection is a core pillar of device hardening. Continue with the rest of the infrastructure security cluster to pair this with anti-spoofing, management-plane lockdown, and authenticated logging.

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.