-
Notifications
You must be signed in to change notification settings - Fork 458
FlowSpec Overview
BGP-based traffic filtering and DDoS mitigation
β ExaBGP was the FIRST open-source FlowSpec implementation (now also supported by GoBGP, FRRouting, BIRD)
- What is FlowSpec?
- Why FlowSpec Matters
- How FlowSpec Works
- Use Cases
- Match Conditions
- Actions
- Configuration
- DDoS Mitigation
- Integration Examples
- Best Practices
- Limitations
- Next Steps
BGP FlowSpec (Flow Specification) is a BGP extension that allows you to distribute traffic filtering rules via BGP.
RFCs:
- RFC 5575 - Dissemination of Flow Specification Rules (IPv4)
- RFC 8955 - Dissemination of Flow Specification Rules (IPv6)
Key concept: Instead of announcing "here's a route to a network," FlowSpec announces "here's a rule to filter/rate-limit/redirect specific traffic."
Example:
# Block all TCP traffic from 10.0.0.0/8 to port 80
announce flow route {
match {
source 10.0.0.0/8;
destination-port =80;
protocol =tcp;
}
then {
discard;
}
}The router receives this BGP update and immediately applies the filter in hardware/fast path.
Traditional DDoS mitigation:
- Detect attack
- SSH into routers
- Manually configure ACLs
- Apply to interfaces
- Remove ACLs when attack ends
Issues:
- β±οΈ Slow: Minutes to deploy (attack already causing damage)
- π§ Manual: Requires human intervention
- π Error-prone: Manual configuration mistakes
- π Doesn't scale: Can't update hundreds of routers quickly
Automated DDoS mitigation with FlowSpec:
- Detection system identifies attack
- Detection system tells ExaBGP via API
- ExaBGP announces FlowSpec rule via BGP
- All routers receive rule and apply filter immediately
- Attack blocked in seconds
Advantages:
- β‘ Fast: Seconds to deploy network-wide
- π€ Automated: No human required
- β Reliable: API-driven, no manual config
- π Scalable: Updates all routers simultaneously via BGP
- π Granular: Match on multiple packet fields
ββββββββββββββββββββ
β DDoS Detection β (FastNetMon, custom detection)
β System β
ββββββββββ¬ββββββββββ
β Detects attack
β
βΌ
ββββββββββββββββββββ
β ExaBGP β Converts to FlowSpec rule
β (FlowSpec β Announces via BGP
β Generator) β
ββββββββββ¬ββββββββββ
β BGP FlowSpec UPDATE
β
βΌ
ββββββββββββββββββββ
β Routers β Receive FlowSpec
β (Cisco, Juniper,β Apply filter in hardware
β Arista, etc.) β Drop/rate-limit matching traffic
ββββββββββββββββββββ
β
β Filtered traffic
βΌ
Attack blocked β
- Detection: DDoS detection system identifies malicious traffic
- API Call: Detection system sends FlowSpec rule to ExaBGP via API
- BGP UPDATE: ExaBGP encodes rule as FlowSpec BGP message
- Propagation: FlowSpec rule propagates to all BGP peers
- Filtering: Routers apply filter in fast path (hardware)
- Result: Attack traffic dropped immediately
Speed: Entire process takes seconds, not minutes or hours.
Automated attack blocking:
- SYN floods
- UDP amplification
- DNS floods
- HTTP floods
- Volumetric attacks
Example:
# Block SYN flood from 10.0.0.0/8 to port 80
announce flow route {
match {
source 10.0.0.0/8;
destination-port =80;
protocol =tcp;
tcp-flags [ syn ];
}
then {
discard;
}
}Limit traffic instead of blocking entirely:
# Rate-limit DNS queries
announce flow route {
match {
destination-port =53;
protocol =udp;
}
then {
rate-limit 1000000; # 1 MB/sec (bytes/sec per RFC 5575)
}
}Redirect suspicious traffic to scrubbing center:
# Redirect to VRF for inspection
announce flow route {
match {
destination 100.10.0.0/24;
}
then {
redirect 65001:100; # Route target for scrubbing VRF
}
}Block specific protocols during attacks:
# Block all ICMP (during ICMP flood)
announce flow route {
match {
protocol =icmp;
}
then {
discard;
}
}Block traffic from specific regions (combined with BGP communities):
# Block traffic from AS 64512
announce flow route {
match {
source 203.0.113.0/24; # Address range from that AS
}
then {
discard;
}
}FlowSpec rules match traffic based on packet fields.
match {
destination 100.10.0.0/24;
}Match packets destined for this network.
match {
source 10.0.0.0/8;
}Match packets from this network.
match {
protocol =tcp; # TCP (6)
protocol =udp; # UDP (17)
protocol =icmp; # ICMP (1)
protocol =6; # Numeric form
}match {
destination-port =80; # Exactly port 80
destination-port =80|=443; # Port 80 OR 443
destination-port >=1024&<=65535; # Port range
destination-port >1023; # Ports above 1023
}Operators:
-
=N- Equals N -
>N- Greater than N -
<N- Less than N -
>=N- Greater or equal -
<=N- Less or equal -
>=N&<=M- Range from N to M (AND) -
=N|=M- N OR M
match {
source-port =1234;
source-port >=1024&<=65535; # Ephemeral ports
}match {
tcp-flags [ syn ]; # SYN flag set
tcp-flags [ syn ack ]; # SYN+ACK
tcp-flags [ fin ]; # FIN flag
tcp-flags [ rst ]; # RST flag
tcp-flags [ psh ]; # PSH flag
tcp-flags [ urg ]; # URG flag
tcp-flags [ fin syn rst psh ack urg ]; # All flags
}Use for:
- SYN floods:
tcp-flags [ syn ](without ACK) - Connection resets:
tcp-flags [ rst ]
match {
packet-length =1500; # Exactly 1500 bytes
packet-length >1500; # Larger than MTU (fragmented)
packet-length <64; # Tiny packets
packet-length >=64&<=1500; # Normal range
}Use for:
- Block fragmented packets:
packet-length >1500 - Block tiny packets:
packet-length <64
match {
icmp-type =8; # Echo request (ping)
icmp-type =0; # Echo reply
icmp-type =3; icmp-code =3; # Port unreachable
}Common ICMP types:
- 0 - Echo reply
- 3 - Destination unreachable
- 8 - Echo request
- 11 - Time exceeded
match {
dscp =46; # EF (Expedited Forwarding)
dscp =0; # Best effort
}match {
fragment [ is-fragment ]; # Any fragment
fragment [ first-fragment ]; # First fragment only
fragment [ last-fragment ]; # Last fragment only
fragment [ not-a-fragment ]; # Not fragmented
}Use for:
- Block all fragments:
fragment [ is-fragment ] - Allow only non-fragmented:
fragment [ not-a-fragment ]
All conditions must match:
match {
source 10.0.0.0/8; # AND
destination 100.10.0.0/24; # AND
destination-port =80; # AND
protocol =tcp; # AND
tcp-flags [ syn ]; # All must match
}What to do with matching traffic.
then {
discard;
}Completely drop matching packets. Most common action for DDoS mitigation.
then {
rate-limit 1000000; # 1 MB/sec (bytes per second per RFC 5575)
}
β οΈ Vendor Implementation Warning: RFC 5575 specifies rate-limit in bytes per second, but routers may interpret differently. Juniper converts to bits/sec (Γ8), Cisco varies by platform. Always test on your equipment!
Rate calculation (RFC 5575 - bytes/sec):
- 1 MB/sec (8 Mbps) = 1,000,000 bytes/sec
- 10 MB/sec (80 Mbps) = 10,000,000 bytes/sec
- 100 MB/sec (800 Mbps) = 100,000,000 bytes/sec
Use for:
- Limiting specific protocols
- Throttling rather than blocking
See Actions Reference for detailed vendor differences.
then {
redirect 65001:100; # Route target
}Redirect traffic to a VRF (Virtual Routing and Forwarding instance) for:
- Scrubbing center analysis
- IDS inspection
- Quarantine network
then {
mark 46; # Mark with DSCP EF
}Remark DSCP field for QoS policy.
then {
community [ 65001:666 ]; # Tag with community
}Tag traffic for downstream policy decisions.
neighbor 192.168.1.1 {
router-id 192.168.1.2;
local-address 192.168.1.2;
local-as 65001;
peer-as 65000;
# Enable FlowSpec address family
family {
ipv4 flowspec;
ipv6 flowspec;
}
# API for dynamic rules
api {
processes [ flowspec-controller ];
}
}
process flowspec-controller {
run /etc/exabgp/api/flowspec.py;
encoder text;
}neighbor 192.168.1.1 {
# ... config ...
family {
ipv4 flowspec;
}
flow {
route {
match {
destination 100.10.0.0/24;
destination-port =80;
protocol =tcp;
}
then {
discard;
}
}
}
}Configuration:
process flowspec-api {
run /etc/exabgp/api/flowspec.py;
encoder text;
}
neighbor 192.168.1.1 {
# ... config ...
family {
ipv4 flowspec;
}
api {
processes [ flowspec-api ];
}
}API Script:
#!/usr/bin/env python3
import sys
import time
time.sleep(2)
# Announce FlowSpec rule
rule = (
"announce flow route { "
"match { "
"source 10.0.0.0/8; "
"destination-port =80; "
"protocol =tcp; "
"tcp-flags [ syn ]; "
"} "
"then { discard; } "
"}"
)
sys.stdout.write(rule + "\n")
sys.stdout.flush()
# Keep running
while True:
time.sleep(60)Workflow:
- Monitor β DDoS detection system monitors traffic
- Detect β Identifies attack pattern
- Generate β Creates FlowSpec rule
- Announce β Sends to ExaBGP via API
- Propagate β ExaBGP announces to routers via BGP
- Block β Routers drop attack traffic
- Cleanup β Auto-withdraw rule when attack ends
#!/usr/bin/env python3
"""
syn_flood_blocker.py - Detect and block SYN floods
"""
import sys
import time
import collections
# Track SYN packets per source
syn_counts = collections.defaultdict(int)
blocked_sources = set()
THRESHOLD = 1000 # SYN packets per second
CHECK_INTERVAL = 1
def detect_syn_flood():
"""Detect SYN flood attacks"""
# Your detection logic here
# Returns source IP if attack detected
for source, count in syn_counts.items():
if count > THRESHOLD and source not in blocked_sources:
return source
return None
def block_source(source_ip):
"""Block source with FlowSpec"""
rule = (
f"announce flow route {{ "
f"match {{ source {source_ip}/32; tcp-flags [ syn ]; }} "
f"then {{ discard; }} "
f"}}"
)
sys.stdout.write(rule + "\n")
sys.stdout.flush()
blocked_sources.add(source_ip)
sys.stderr.write(f"[BLOCKED] SYN flood from {source_ip}\n")
time.sleep(2)
while True:
attacker = detect_syn_flood()
if attacker:
block_source(attacker)
# Reset counters
syn_counts.clear()
time.sleep(CHECK_INTERVAL)def block_udp_amplification(protocol_port):
"""Block UDP amplification attacks"""
protocols = {
'dns': 53,
'ntp': 123,
'ssdp': 1900,
'chargen': 19,
}
port = protocols.get(protocol_port, protocol_port)
rule = (
f"announce flow route {{ "
f"match {{ destination-port ={port}; protocol =udp; packet-length >512; }} "
f"then {{ discard; }} "
f"}}"
)
sys.stdout.write(rule + "\n")
sys.stdout.flush()
sys.stderr.write(f"[BLOCKED] UDP amplification on port {port}\n")
# Block DNS amplification
block_udp_amplification('dns')FastNetMon is a DDoS detection system with ExaBGP integration.
Architecture:
FastNetMon (detector) β ExaBGP (FlowSpec generator) β Routers (filters)
FastNetMon config:
# Enable ExaBGP integration
enable_ban_for_tcp_syn_flood = on
exabgp = on
exabgp_flow_spec_announces = on
# ExaBGP command pipe
exabgp_command_pipe = /var/run/exabgp.cmdExaBGP config:
process fastnetmon {
run /etc/exabgp/api/fastnetmon.py;
encoder text;
}
neighbor 192.168.1.1 {
# ... config ...
family {
ipv4 flowspec;
}
api {
processes [ fastnetmon ];
}
}#!/usr/bin/env python3
"""
custom_detector.py - Custom DDoS detection with FlowSpec
"""
import sys
import time
import requests
DETECTION_API = "http://localhost:5000/detect"
def get_attack_info():
"""Query detection system"""
response = requests.get(DETECTION_API)
if response.status_code == 200:
data = response.json()
if data.get('attack_detected'):
return data
return None
def announce_flowspec(attack):
"""Generate and announce FlowSpec rule"""
source = attack['source_ip']
dest_port = attack['destination_port']
protocol = attack['protocol']
rule = (
f"announce flow route {{ "
f"match {{ source {source}/32; destination-port ={dest_port}; protocol ={protocol}; }} "
f"then {{ discard; }} "
f"}}"
)
sys.stdout.write(rule + "\n")
sys.stdout.flush()
sys.stderr.write(f"[BLOCKED] Attack from {source} to port {dest_port}\n")
time.sleep(2)
while True:
attack = get_attack_info()
if attack:
announce_flowspec(attack)
time.sleep(5)Bad (too broad):
# Blocks ALL TCP traffic
match {
protocol =tcp;
}
then {
discard;
}Good (specific):
# Blocks only SYN flood from specific source
match {
source 10.0.0.0/8;
destination-port =80;
protocol =tcp;
tcp-flags [ syn ];
}
then {
discard;
}Try rate-limiting before blocking:
# Step 1: Rate-limit
then {
rate-limit 10000000; # 10 Mbps
}
# Step 2: If still too much, block
then {
discard;
}Set TTL or withdraw rules after attack ends:
import time
import threading
def withdraw_after_timeout(rule, timeout=300):
"""Auto-withdraw rule after timeout (seconds)"""
time.sleep(timeout)
withdraw = rule.replace('announce', 'withdraw')
sys.stdout.write(withdraw + "\n")
sys.stdout.flush()
# Announce with auto-expiry
rule = "announce flow route { ... }"
sys.stdout.write(rule + "\n")
sys.stdout.flush()
threading.Thread(target=withdraw_after_timeout, args=(rule, 300)).start()import logging
logging.basicConfig(filename='/var/log/flowspec.log', level=logging.INFO)
def announce_rule(rule):
sys.stdout.write(rule + "\n")
sys.stdout.flush()
logging.info(f"Announced FlowSpec rule: {rule}")Alert humans when auto-blocking:
def send_alert(message):
"""Send alert to NOC"""
requests.post("https://alerts.example.com/webhook", json={
"text": message,
"severity": "high"
})
# When blocking
send_alert(f"FlowSpec: Blocking SYN flood from {source_ip}")A September 2024 APNIC article highlights FlowSpec's key advantage:
"Lingua Franca" Across Vendors
FlowSpec is a standardized protocol that works across multiple vendors' equipment without requiring vendor-specific firewall management interfaces.
Key Benefits:
- β Vendor-agnostic: Works on Juniper, Cisco, Nokia, Arista, Extreme, FRR
- β On-premises mitigation: No third-party cloud scrubbing centers needed
- β Standardized: One API (ExaBGP) β many router vendors
- β Fast deployment: Seconds to propagate network-wide via BGP
- β Granular filtering: L3/L4 header matching
Compared to alternatives:
- Traditional ACLs: Manual, slow, device-specific
- Cloud scrubbing: Expensive, adds latency, requires traffic redirection
- Proprietary on-premises: Vendor lock-in, complex integration
FlowSpec eliminates these issues by using BGP as the control plane.
FlowSpec requires router support:
- β Cisco ASR 1000/9000, NCS 5500, IOS-XR, IOS-XE
- β Juniper MX, PTX, Junos (most platforms)
- β Arista EOS
- β Nokia SR OS
- β Huawei routers
- β Extreme Networks
- β FRRouting (open source)
- β Some low-end/consumer routers don't support FlowSpec
Check router documentation for FlowSpec support.
β οΈ Important: FlowSpec implementation varies significantly between vendors.
Known limitations (per APNIC 2024 analysis):
Arista:
- Limited fragment flag support
- Missing some TCP flags
Extreme Networks:
- Only partial fragment support
- Rate-limit values must be multiples of 22 Kbps
Cisco ASR 9000:
- Maximum 5 values per range in a single rule
- Example: Can't match ports 80,443,8080,8443,3000,5000 in one rule
All vendors:
- Hard limits on number of rules (varies by model)
- No TTL field filtering (hinders spoofed traffic detection)
- Limited visibility into rule effectiveness (can't see per-rule stats easily)
Important: ExaBGP supports the full RFC 5575/8955 specification. It sends exactly what you tell it to send via the API. Users must understand their router's specific FlowSpec capabilities and limitations when crafting rules.
- Some routers limit number of FlowSpec rules (e.g., 1000-10,000)
- Rules consume TCAM (ternary content-addressable memory) space
- Too many rules can degrade performance
- Cross-ASN deployments face rule validation challenges
Best practice: Keep rules focused and clean up expired rules.
Example limits:
- Small routers: ~1,000 rules
- Enterprise routers: ~10,000 rules
- Carrier-grade routers: ~50,000+ rules
FlowSpec filters at the router, after packets arrive.
Can't prevent:
- Bandwidth exhaustion from spoofed sources
- Attacks that flood uplink before reaching router
- DDoS that consumes all bandwidth upstream
Solution: Combine with:
- Upstream scrubbing for volumetric attacks (> line capacity)
- BCP 38 (source address validation) to prevent spoofing
- Rate-limiting before FlowSpec rules kick in
Problem: Limited visibility into effectiveness of each rule.
Can't easily see:
- How many packets matched each rule
- Which rules are still active vs. stale
- Per-rule bandwidth consumption
Workaround:
- Use router-specific CLI to check rule hit counts
- Implement TTL-based rule expiration
- Log rule announcements/withdrawals in ExaBGP
- Monitor overall traffic reduction (before/after)
- Match Conditions Reference - All match types detailed
- Actions Reference - All actions detailed
- DDoS Mitigation Guide - Complete DDoS mitigation workflow
- Text API Reference - FlowSpec API commands
- JSON API Reference - Receiving FlowSpec messages
- FastNetMon Integration - DDoS detection integration
- Production Best Practices - Production deployment
Ready for DDoS protection? See DDoS Mitigation Guide β
π» Ghost written by Claude (Anthropic AI)
π Home
π Getting Started
π§ API
π‘οΈ Use Cases
π Address Families
βοΈ Configuration
π Operations
π Reference
- Architecture
- BGP State Machine
- Communities (RFC)
- Extended Communities
- BGP Ecosystem
- Capabilities (AFI/SAFI)
- RFC Support
- Migration (3.4β4.x)
π Community
π External
- GitHub Repo β
- Slack β
- Issues β
π» Ghost written by Claude (Anthropic AI)