Protecting the Router Itself: Control-Plane Policing and Management-Plane Filters, with a Linux Example
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 -tulpn on 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
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to