Skip to content

FlowSpec Overview

Thomas Mangin edited this page Nov 10, 2025 · 7 revisions

FlowSpec Overview

BGP-based traffic filtering and DDoS mitigation

⭐ ExaBGP was the FIRST open-source FlowSpec implementation (now also supported by GoBGP, FRRouting, BIRD)


Table of Contents


What is FlowSpec?

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.


Why FlowSpec Matters

The Problem

Traditional DDoS mitigation:

  1. Detect attack
  2. SSH into routers
  3. Manually configure ACLs
  4. Apply to interfaces
  5. 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

The FlowSpec Solution

Automated DDoS mitigation with FlowSpec:

  1. Detection system identifies attack
  2. Detection system tells ExaBGP via API
  3. ExaBGP announces FlowSpec rule via BGP
  4. All routers receive rule and apply filter immediately
  5. 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

How FlowSpec Works

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  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 βœ…

Message Flow

  1. Detection: DDoS detection system identifies malicious traffic
  2. API Call: Detection system sends FlowSpec rule to ExaBGP via API
  3. BGP UPDATE: ExaBGP encodes rule as FlowSpec BGP message
  4. Propagation: FlowSpec rule propagates to all BGP peers
  5. Filtering: Routers apply filter in fast path (hardware)
  6. Result: Attack traffic dropped immediately

Speed: Entire process takes seconds, not minutes or hours.


Use Cases

1. DDoS Mitigation (Primary Use Case)

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;
    }
}

2. Rate Limiting

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)
    }
}

3. Traffic Redirection

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
    }
}

4. Protocol-Specific Blocking

Block specific protocols during attacks:

# Block all ICMP (during ICMP flood)
announce flow route {
    match {
        protocol =icmp;
    }
    then {
        discard;
    }
}

5. Geographic Blocking

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;
    }
}

Match Conditions

FlowSpec rules match traffic based on packet fields.

Destination Prefix

match {
    destination 100.10.0.0/24;
}

Match packets destined for this network.


Source Prefix

match {
    source 10.0.0.0/8;
}

Match packets from this network.


IP Protocol

match {
    protocol =tcp;     # TCP (6)
    protocol =udp;     # UDP (17)
    protocol =icmp;    # ICMP (1)
    protocol =6;       # Numeric form
}

Destination Port

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

Source Port

match {
    source-port =1234;
    source-port >=1024&<=65535;  # Ephemeral ports
}

TCP Flags

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 ]

Packet Length

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

ICMP Type/Code

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

DSCP

match {
    dscp =46;  # EF (Expedited Forwarding)
    dscp =0;   # Best effort
}

Fragment

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 ]

Multiple Match Conditions (AND Logic)

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
}

Actions

What to do with matching traffic.

Discard (Drop)

then {
    discard;
}

Completely drop matching packets. Most common action for DDoS mitigation.


Rate-Limit

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.


Redirect to VRF

then {
    redirect 65001:100;  # Route target
}

Redirect traffic to a VRF (Virtual Routing and Forwarding instance) for:

  • Scrubbing center analysis
  • IDS inspection
  • Quarantine network

Mark (DSCP Remarking)

then {
    mark 46;  # Mark with DSCP EF
}

Remark DSCP field for QoS policy.


Community Tagging

then {
    community [ 65001:666 ];  # Tag with community
}

Tag traffic for downstream policy decisions.


Configuration

Enable FlowSpec

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;
}

Static FlowSpec Rule

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;
            }
        }
    }
}

API-Based FlowSpec (Recommended)

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)

DDoS Mitigation

Automated DDoS Response

Workflow:

  1. Monitor β†’ DDoS detection system monitors traffic
  2. Detect β†’ Identifies attack pattern
  3. Generate β†’ Creates FlowSpec rule
  4. Announce β†’ Sends to ExaBGP via API
  5. Propagate β†’ ExaBGP announces to routers via BGP
  6. Block β†’ Routers drop attack traffic
  7. Cleanup β†’ Auto-withdraw rule when attack ends

Example: SYN Flood Protection

#!/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)

Example: UDP Amplification Protection

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')

Integration Examples

Integration with FastNetMon

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.cmd

ExaBGP config:

process fastnetmon {
    run /etc/exabgp/api/fastnetmon.py;
    encoder text;
}

neighbor 192.168.1.1 {
    # ... config ...
    family {
        ipv4 flowspec;
    }
    api {
        processes [ fastnetmon ];
    }
}

Integration with Custom Detection

#!/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)

Best Practices

1. Be Specific

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;
}

2. Use Rate-Limiting First

Try rate-limiting before blocking:

# Step 1: Rate-limit
then {
    rate-limit 10000000;  # 10 Mbps
}

# Step 2: If still too much, block
then {
    discard;
}

3. Auto-Expire Rules

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()

4. Log All Actions

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}")

5. Coordinate with NOC

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}")

Why FlowSpec is Powerful

"The Ultimate Weapon Against DDoS" (APNIC, 2024)

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.


Limitations

Router Support Required

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.


Vendor-Specific Implementation Differences

⚠️ 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.


Hardware Limitations

  • 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

No Spoofed Source Protection

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

Visibility Challenges

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)

Next Steps

Learn More

Examples

Integration


Ready for DDoS protection? See DDoS Mitigation Guide β†’


πŸ‘» Ghost written by Claude (Anthropic AI)

Clone this wiki locally