Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.
A router has two jobs that share one CPU: forwarding transit traffic, which hardware or the fast path usually does, and running software that speaks protocols, answers management requests, and makes decisions. That second part, the control plane and management plane, is small, slow, and exposed. Anything addressed to the router itself (BGP packets, SSH, SNMP, ICMP, routing protocol hellos) is handled by software and can be overwhelmed by a flood or a mistake. Control-plane policing (CoPP) and management-plane protection are the practices that keep that part alive under stress. This article explains the concepts and shows a Linux router implementation with nftables. Examples use 192.0.2.1 and 2001:db8:ffff::1 as the router, 192.0.2.2 and 2001:db8:ffff::2 as a BGP neighbour, and 192.0.2.0/27 as the management network.
What reaches the control plane
The router's own CPU handles traffic of several classes, which deserve different treatment:
| Class | Examples | Treatment |
|---|---|---|
| Routing protocols | BGP (TCP 179), OSPF, IS-IS, BFD | Accept only from known neighbours; never rate-limit hard |
| Neighbour discovery | ARP, IPv6 ND | Allow; limit only at extreme rates |
| Management | SSH, SNMP, NTP, syslog | Accept only from the management network |
| Diagnostic | ICMP echo, traceroute replies | Allow with a rate limit |
| Everything else addressed to the router | Random scans, floods | Drop, with limited logging |
On commercial routers, CoPP applies per-class policers to traffic punted to the CPU, and vendors document how. On a Linux router, the same idea maps to the input hook of the firewall, which sees only traffic destined to the router itself. Transit traffic goes through forward, which is a separate decision.
A Linux input policy
table inet cp {
set peers4 { type ipv4_addr; elements = { 192.0.2.2 } }
set peers6 { type ipv6_addr; elements = { 2001:db8:ffff::2 } }
set mgmt4 { type ipv4_addr; flags interval; elements = { 192.0.2.0/27 } }
set mgmt6 { type ipv6_addr; flags interval; elements = { 2001:db8:100::/48 } }
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
ct state invalid drop
iif lo accept
# Neighbour discovery and path MTU discovery must work
meta l4proto ipv6-icmp icmpv6 type { nd-router-solicit, nd-router-advert,
nd-neighbor-solicit, nd-neighbor-advert, packet-too-big,
destination-unreachable, time-exceeded, parameter-problem } accept
ip protocol icmp icmp type { destination-unreachable, time-exceeded } accept
# ARP is filtered in the separate arp family, not in this inet table
# Routing
ip saddr @peers4 tcp dport 179 accept
ip6 saddr @peers6 tcp dport 179 accept
ip6 saddr fe80::/10 ip6 nexthdr 89 accept
ip saddr @peers4 udp dport { 3784, 4784 } accept
# Management
ip saddr @mgmt4 tcp dport 22 accept
ip6 saddr @mgmt6 tcp dport 22 accept
ip saddr @mgmt4 udp dport 161 accept
# Ping: allowed but rate-limited
ip protocol icmp icmp type echo-request limit rate 20/second burst 40 packets accept
meta l4proto ipv6-icmp icmpv6 type echo-request limit rate 20/second burst 40 packets accept
limit rate 5/minute log prefix "cp-drop: " counter drop
counter drop
}
}
Several choices are deliberate. The ICMPv6 types listed are the ones the earlier ICMPv6 reference says must not be blocked. Neighbour discovery is never rate-limited here, because limiting it can break address resolution under load. Routing protocols are matched by source address, and OSPFv3 is accepted only from link-local sources. Echo requests are rate-limited, not dropped, because operators need ping. The final rules log a small sample of drops and count the rest, which gives visibility without letting an attack fill the disk.
Do not forget the other half: protocols that talk back
Adding ct state established,related accept early handles replies to connections the router starts, such as NTP queries and syslog messages. If you run an outbound-only service, no inbound rule is needed.
For BGP, combine the firewall with session-level protections: TCP-AO or MD5 and TTL security (see the earlier article), maximum-prefix limits, and BFD with sensible timers. The firewall limits who can talk to the process; those features limit what a valid-looking neighbour can do.
Management-plane specifics
- Separate management from transit. A management VRF or out-of-band network means a transit flood cannot lock you out. The VRF article describes how.
-
Disable what you do not use. Every listening service is something to patch.
ss -tulpnon a Linux router lists them; remove or bind to the management address. - Authenticate and encrypt. SSH with keys, SNMPv3 rather than v1 or v2c, and authenticated NTP where practical.
- Log and alert on counter growth of the drop rules.
- Rate-limit what an attacker can trigger. Anything that causes work, such as a TCP SYN to an open port, can be limited per source with a meter.
Testing safely
Use a virtual lab, not a live router, to validate rules. Check syntax with nft -c -f file, and apply with a timed rollback. Then confirm what the policy does:
nft list ruleset
nft list chain inet cp input
The counters show which rules matched. Send a controlled flood at the router from a lab host, such as ping -f against a rate-limited rule, and check that BGP stays up during the test. If you cannot show that routing survives, you have not yet protected the control plane. The rules above were written from documentation and not tested against a real router.
Summary
Control-plane protection means identifying what the router must hear, from whom, and at what rate, and dropping everything else early. Most of the benefit comes from the simplest part: refusing management and routing traffic from addresses that should never send it.
About IPYE
IPYE (https://my.ipye.com) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: ipye@turnel.com.
Disclosure: I run IPYE
Top comments (0)