# FlowSpec Actions Reference **Complete reference for all FlowSpec actions** > RFC 5575 (IPv4) / RFC 8955 (IPv6) - Extended Community-based actions --- ## Table of Contents - [Overview](#overview) - [Discard](#discard) - [Rate-Limit](#rate-limit) - [Redirect to VRF](#redirect-to-vrf) - [Mark (DSCP)](#mark-dscp) - [Community Tagging](#community-tagging) - [Combining Actions](#combining-actions) - [Extended Community Format](#extended-community-format) - [Router Support](#router-support) - [Best Practices](#best-practices) - [Common Patterns](#common-patterns) --- ## Overview FlowSpec actions define **what to do** with matched traffic. **Basic structure:** ```python announce flow route { match { } then { ; } } ``` **Actions are implemented as BGP Extended Communities** sent with the FlowSpec route. **Available actions:** | Action | Extended Community Type | Purpose | |--------|------------------------|---------| | `discard` | traffic-action (0x8006) | Drop packets | | `rate-limit` | traffic-rate (0x8006) | Limit bandwidth | | `redirect` | redirect (0x8008) | Redirect to VRF | | `mark` | traffic-marking (0x8009) | Remark DSCP | | `community` | Standard/Extended | Tag traffic | --- ## Discard **Drop matching packets completely** ### Syntax ```python then { discard; } ``` ### Extended Community ``` Traffic-action: terminal-action ``` ### Description Matching packets are **immediately dropped** at the router. **Characteristics:** - ✅ Most common action for DDoS mitigation - ✅ Hardware-based (wire-speed performance) - ✅ Zero bandwidth consumption for dropped packets - ⚠️ No logging of dropped packets (router-dependent) - ⚠️ Legitimate traffic may be affected if rule too broad --- ### Examples #### Block SYN Flood ```python announce flow route { match { destination 100.10.0.100/32; destination-port =80; protocol =tcp; tcp-flags [ syn ]; } then { discard; } } ``` **Result:** All TCP SYN packets to 100.10.0.100:80 are dropped. --- #### Block DNS Amplification ```python announce flow route { match { source-port =53; protocol =udp; packet-length >512; } then { discard; } } ``` **Result:** Large DNS responses (likely amplification) are dropped. --- #### Block All ICMP ```python announce flow route { match { protocol =icmp; } then { discard; } } ``` **Result:** All ICMP packets dropped (use during ICMP flood). --- ### Use Cases - **DDoS mitigation** - Block attack traffic completely - **Security blocking** - Block known malicious sources - **Protocol blocking** - Block entire protocols during attacks - **Emergency response** - Stop attack immediately --- ### Best Practices 1. **Be specific** - Avoid blocking legitimate traffic 2. **Monitor impact** - Check if rule affects real users 3. **Auto-expire** - Withdraw rule when attack ends 4. **Log announcements** - Track what you're blocking **Example with logging:** ```python import logging logging.info(f"[DISCARD] Blocking {source_ip} to port {port}") sys.stdout.write(f"announce flow route {{ match {{ source {source_ip}/32; }} then {{ discard; }} }}\n") sys.stdout.flush() ``` --- ## Rate-Limit **Limit bandwidth for matching traffic** ### Syntax ```python then { rate-limit ; } ``` ### Extended Community ``` Traffic-rate: ``` ### Description Matching packets are **rate-limited** to specified bandwidth. > **⚠️ Implementation-Specific Behavior** > > RFC 5575/8955 do NOT specify whether rate-limit applies per-flow or as aggregate across all matching traffic. This is **router implementation-specific**: > - Some vendors apply rate-limit **per individual flow** (per source IP) > - Some vendors apply rate-limit as **aggregate** across all matching traffic > - Consult your router vendor's documentation for exact behavior > > ExaBGP signals the rate-limit value to the router via BGP - the router enforces it according to its own implementation. **Characteristics:** - ✅ Throttle traffic instead of dropping completely - ✅ Allows some legitimate traffic through - ✅ Hardware-based policing - ⚠️ Excess traffic is dropped - ⚠️ Behavior (per-flow vs aggregate) depends on router vendor --- ### Rate Calculation > ⚠️ **IMPORTANT: Vendor Implementation Differences** > > **RFC 5575** specifies rate-limit values in **bytes per second**. > > However, **router vendors implement this differently:** > - **Juniper**: Converts bytes/sec to **bits/sec** internally (multiplies by 8) > - **Cisco**: May interpret values differently depending on platform > - **Other vendors**: Vary in implementation > > **ExaBGP follows RFC 5575** and sends values as **bytes per second**. Your router interprets these values according to its vendor-specific implementation. > > **Critical**: Always test rate-limit behavior on your specific router platform. The same ExaBGP value may result in different actual rates on different vendor equipment. **RFC 5575 Compliant (Bytes per Second):** ```python # 1 MB/sec (8 Mbps) = 1,000,000 bytes/sec rate-limit 1000000 # 10 MB/sec (80 Mbps) = 10,000,000 bytes/sec rate-limit 10000000 # 100 MB/sec (800 Mbps) = 100,000,000 bytes/sec rate-limit 100000000 # 1 GB/sec (8 Gbps) = 1,000,000,000 bytes/sec rate-limit 1000000000 ``` **Understanding the Values:** ``` ExaBGP value (bytes/sec) → Router interprets per vendor implementation RFC 5575: bytes per second Juniper: converts to bits per second (×8) Cisco: depends on platform ``` **Conversion Reference:** - 1 Mbps (megabit/sec) = 125,000 bytes/sec - 10 Mbps = 1,250,000 bytes/sec - 100 Mbps = 12,500,000 bytes/sec - 1 Gbps = 125,000,000 bytes/sec --- ### Examples #### Rate-Limit DNS Queries ```python announce flow route { match { destination-port =53; protocol =udp; } then { rate-limit 10000000; # 10 Mbps } } ``` **Result:** DNS traffic limited to 10 Mbps. --- #### Rate-Limit SYN Flood ```python announce flow route { match { destination-port =80; protocol =tcp; tcp-flags [ syn ]; } then { rate-limit 5000000; # 5 Mbps } } ``` **Result:** TCP SYN packets to port 80 limited to 5 Mbps. --- #### Rate-Limit ICMP ```python announce flow route { match { protocol =icmp; icmp-type =8; # Echo request } then { rate-limit 1000000; # 1 Mbps } } ``` **Result:** ICMP echo requests limited to 1 Mbps. --- #### Rate-Limit Attack Source ```python announce flow route { match { source 203.0.113.0/24; # Attacker network } then { rate-limit 1000000; # 1 Mbps } } ``` **Result:** All traffic from 203.0.113.0/24 limited to 1 Mbps. --- ### Graduated Response **Start with rate-limiting, escalate to discard if needed:** ```python # Step 1: Detect attack, rate-limit announce flow route { match { source 10.0.0.0/8; destination-port =80; } then { rate-limit 10000000; } # 10 Mbps } # Step 2: If still too much traffic, tighten rate announce flow route { match { source 10.0.0.0/8; destination-port =80; } then { rate-limit 1000000; } # 1 Mbps } # Step 3: If attack continues, block completely announce flow route { match { source 10.0.0.0/8; destination-port =80; } then { discard; } } ``` --- ### Use Cases - **Proportional response** - Limit before blocking - **Soft mitigation** - Allow some legitimate traffic - **Protocol throttling** - Slow down entire protocols - **Testing** - Validate rule before full block --- ### Best Practices 1. **Start conservative** - Higher rate first, lower if needed 2. **Monitor bandwidth** - Check actual traffic reduction 3. **Per-service rates** - Different limits for different services 4. **Combine with discard** - Escalate if rate-limit insufficient --- ### Vendor-Specific Notes **Extreme Networks:** - Rate values must be multiples of **22 Kbps** (22,000 bytes/sec) - Invalid rates may be rounded or rejected **Example for Extreme:** ```python # Bad: Not a multiple of 22 Kbps rate-limit 1000000 # May be rejected # Good: Multiple of 22 Kbps rate-limit 1100000 # 8.8 Mbps (50 × 22 Kbps) ``` --- ## Redirect to VRF **Redirect matching traffic to a VRF (Virtual Routing and Forwarding instance)** ### Syntax ```python then { redirect ; } ``` ### Extended Community ``` Redirect: ``` ### Description Matching packets are **redirected** to specified VRF instead of normal routing. **Characteristics:** - ✅ Traffic sent to separate routing instance - ✅ Enables scrubbing center analysis - ✅ Allows inspection without blocking - ⚠️ Requires VRF configuration on router - ⚠️ Complexity increases --- ### Route Target Format ```python # ASN:Value format redirect 65001:100 # IP:Value format redirect 192.168.1.1:100 ``` --- ### Examples #### Redirect to Scrubbing VRF ```python announce flow route { match { destination 100.10.0.0/24; # Attacked network } then { redirect 65001:999; # Scrubbing VRF route-target } } ``` **Workflow:** 1. Suspicious traffic matched 2. Redirected to VRF with route-target 65001:999 3. VRF routes traffic to scrubbing appliance 4. Clean traffic returned to production network --- #### Redirect Suspicious Sources ```python announce flow route { match { source 203.0.113.0/24; # Suspicious network } then { redirect 65001:100; # Inspection VRF } } ``` **Use case:** Send traffic from suspicious sources to IDS/IPS for deep inspection. --- ### Architecture Pattern ``` ┌─────────────────┐ │ Attack Traffic │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Edge Router │ FlowSpec: redirect 65001:999 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Scrubbing VRF │ Route-target 65001:999 │ (VRF 999) │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Scrubbing │ Analyze & clean │ Appliance │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Clean Traffic │ Return to production │ Back to Network │ └─────────────────┘ ``` --- ### Use Cases - **Scrubbing centers** - Send attack traffic for cleaning - **IDS/IPS inspection** - Deep packet inspection - **Quarantine networks** - Isolate suspicious traffic - **Logging/analysis** - Capture attack packets --- ### Best Practices 1. **Pre-configure VRFs** - VRF must exist before redirect 2. **Test redirect path** - Verify traffic reaches scrubbing 3. **Return path** - Ensure clean traffic gets back 4. **Monitor VRF** - Check scrubbing VRF capacity --- ## Mark (DSCP) **Remark DSCP field for QoS processing** ### Syntax ```python then { mark ; } ``` ### Extended Community ``` Traffic-marking: ``` ### Description Matching packets have their **DSCP field remarked** to specified value. **Characteristics:** - ✅ Packets marked for downstream QoS - ✅ Can be combined with other policies - ⚠️ Doesn't drop or rate-limit traffic - ⚠️ Requires downstream QoS config --- ### DSCP Values | DSCP | Name | Typical Use | |------|------|-------------| | 0 | BE (Best Effort) | Default | | 8 | CS1 | Low priority | | 10 | AF11 | Bulk data | | 12 | AF12 | Bulk data | | 14 | AF13 | Bulk data | | 26 | AF31 | Signaling | | 34 | AF41 | Video | | 46 | EF | Voice | --- ### Examples #### Mark Attack Traffic as Low Priority ```python announce flow route { match { source 10.0.0.0/8; # Attack source } then { mark 8; # CS1 (low priority) } } ``` **Result:** Traffic from 10.0.0.0/8 marked as low priority for QoS. --- #### Mark Suspicious Traffic ```python announce flow route { match { destination-port =80; protocol =tcp; tcp-flags [ syn ]; packet-length >1000; # Large SYN packets (suspicious) } then { mark 0; # Best effort (lowest priority) } } ``` **Result:** Large SYN packets deprioritized by downstream QoS. --- ### Use Cases - **QoS integration** - Mark for downstream handling - **Prioritization** - Deprioritize attack traffic - **Traffic classification** - Identify specific flows - **Policy enforcement** - Apply downstream policies --- ### Best Practices 1. **Downstream QoS required** - Marking alone doesn't rate-limit 2. **Consistent DSCP values** - Align with existing QoS policy 3. **Combine with rate-limit** - Mark + rate-limit for best control 4. **Monitor effectiveness** - Verify QoS policies work --- ## Community Tagging **Tag FlowSpec routes with BGP communities** ### Syntax ```python then { community [ ]; } ``` ### Description FlowSpec route itself is **tagged with communities** for downstream policy decisions. **Characteristics:** - ✅ Allows policy-based filtering - ✅ Enables selective route acceptance - ⚠️ Doesn't affect matched traffic directly - ⚠️ Requires community-based policies --- ### Examples #### Tag FlowSpec Rule for Filtering ```python announce flow route { match { source 10.0.0.0/8; } then { discard; community [ 65001:666 ]; # Mark as DDoS mitigation } } ``` **Downstream routers can:** - Accept FlowSpec routes with community 65001:666 - Reject FlowSpec routes without this community - Apply different policies based on community --- #### Tag by Attack Type ```python # SYN flood announce flow route { match { tcp-flags [ syn ]; } then { discard; community [ 65001:100 ]; # SYN flood tag } } # UDP flood announce flow route { match { protocol =udp; packet-length >1000; } then { discard; community [ 65001:200 ]; # UDP flood tag } } ``` **Use case:** Track/filter FlowSpec rules by attack type. --- ### Use Cases - **Route filtering** - Control FlowSpec propagation - **Policy decisions** - Apply different handling - **Tracking** - Identify rule types - **Logging** - Categorize mitigation actions --- ## Combining Actions **Multiple actions can be combined in a single rule.** ### Example 1: Rate-Limit + Mark ```python announce flow route { match { source 10.0.0.0/8; destination-port =80; } then { rate-limit 10000000; # 10 Mbps mark 8; # Mark as low priority } } ``` **Result:** Traffic rate-limited **AND** marked for downstream QoS. --- ### Example 2: Discard + Community ```python announce flow route { match { source 203.0.113.0/24; } then { discard; community [ 65001:666 ]; # Tag rule } } ``` **Result:** Traffic discarded, FlowSpec route tagged. --- ### Example 3: Redirect + Community ```python announce flow route { match { destination 100.10.0.0/24; } then { redirect 65001:999; # Send to scrubbing VRF community [ 65001:100 ]; # Tag as scrubbed traffic } } ``` **Result:** Traffic redirected to scrubbing, rule tagged for tracking. --- ## Extended Community Format FlowSpec actions are **BGP Extended Communities** in the FlowSpec route. ### Traffic-Rate (Rate-Limit) ``` Type: 0x8006 (traffic-rate) Value: ``` ### Traffic-Action (Discard) ``` Type: 0x8006 (traffic-action) Value: 0x01 (terminal-action / discard) ``` ### Redirect ``` Type: 0x8008 (redirect) Value: ``` ### Traffic-Marking (Mark DSCP) ``` Type: 0x8009 (traffic-marking) Value: ``` --- ## Router Support **Action support varies by router vendor/model.** ### Cisco - ✅ Discard - ✅ Rate-limit - ✅ Redirect - ⚠️ Mark (model-dependent) ### Juniper - ✅ Discard - ✅ Rate-limit - ✅ Redirect - ✅ Mark ### Arista - ✅ Discard - ✅ Rate-limit - ⚠️ Redirect (limited) - ⚠️ Mark (limited) ### FRRouting (Open Source) - ✅ Discard - ✅ Rate-limit - ✅ Redirect - ✅ Mark **Check router documentation for specific action support.** --- ## Best Practices ### 1. Choose Appropriate Action | Situation | Recommended Action | |-----------|-------------------| | Known attack, high confidence | `discard` | | Suspected attack, testing | `rate-limit` | | Need analysis | `redirect` | | QoS integration | `mark` | | Gradual escalation | `rate-limit` → `discard` | --- ### 2. Log All Actions ```python import logging def announce_with_logging(rule, action): logging.info(f"[FLOWSPEC] Action={action} Rule={rule}") sys.stdout.write(rule + "\n") sys.stdout.flush() rule = "announce flow route { match { source 10.0.0.0/8; } then { discard; } }" announce_with_logging(rule, "discard") ``` --- ### 3. Auto-Expire Rules ```python import threading import time def auto_withdraw(rule, timeout=300): time.sleep(timeout) withdraw = rule.replace('announce', 'withdraw').replace('then { discard; }', '') sys.stdout.write(withdraw + "\n") sys.stdout.flush() logging.info(f"[FLOWSPEC] Auto-withdrew rule after {timeout}s") # Announce with auto-expiry rule = "announce flow route { match { source 10.0.0.0/8; } then { discard; } }" sys.stdout.write(rule + "\n") sys.stdout.flush() threading.Thread(target=auto_withdraw, args=(rule, 300)).start() ``` --- ### 4. Monitor Impact **Track:** - Bandwidth before/after rule - Number of packets matched - False positives (legitimate traffic blocked) - Attack duration **Tools:** - Router packet counters - NetFlow/sFlow analysis - SNMP monitoring --- ### 5. Graduated Response **Escalation ladder:** ```python # Level 1: Rate-limit (warning) rate-limit 50000000 # 50 Mbps # Level 2: Tighter rate-limit rate-limit 10000000 # 10 Mbps # Level 3: Very tight rate-limit rate-limit 1000000 # 1 Mbps # Level 4: Block completely discard ``` --- ## Common Patterns ### DDoS Mitigation - Discard ```python announce flow route { match { source 10.0.0.0/8; destination-port =80; tcp-flags [ syn ]; } then { discard; } } ``` --- ### DDoS Mitigation - Rate-Limit ```python announce flow route { match { destination 100.10.0.100/32; destination-port =53; protocol =udp; } then { rate-limit 10000000; # 10 Mbps } } ``` --- ### Traffic Scrubbing - Redirect ```python announce flow route { match { destination 100.10.0.0/24; } then { redirect 65001:999; # Scrubbing VRF } } ``` --- ### QoS Integration - Mark ```python announce flow route { match { source 10.0.0.0/8; } then { mark 8; # Low priority } } ``` --- ### Combined: Rate-Limit + Mark ```python announce flow route { match { protocol =udp; packet-length >1000; } then { rate-limit 10000000; mark 0; # Best effort } } ``` --- ## Next Steps ### Learn More - **[FlowSpec Overview](FlowSpec-Overview)** - Introduction to FlowSpec - **[Match Conditions Reference](Match-Conditions)** - What traffic to match - **[DDoS Mitigation Guide](DDoS-Mitigation)** - Complete workflow ### API Reference - **[Text API Reference](Text-API-Reference)** - FlowSpec commands - **[API Commands](API-Commands)** - Command reference ### Examples - **[Quick Start](Quick-Start)** - First FlowSpec rule - **[Production Best Practices](Production-Best-Practices)** - Production deployment --- **Ready to implement DDoS mitigation?** See [DDoS Mitigation Guide](DDoS-Mitigation) → --- **👻 Ghost written by Claude (Anthropic AI)**