Skip to content

flowspec injection

Thomas Mangin edited this page Apr 8, 2026 · 6 revisions

Pre-Alpha. This page describes behavior that may change. Not for production use.

Inject BGP FlowSpec rules from a script for DDoS mitigation. The scenario: a detection system identifies a DDoS target, your script constructs a FlowSpec rule that drops or rate-limits traffic matching the attack signature, and Ze advertises the rule to upstream providers that will apply the filter in their routers.

FlowSpec (RFC 8955) is the part of BGP that distributes traffic filtering rules instead of routing information. It lets you push a filter (source prefix, destination prefix, protocol, source port, destination port) to every peer that understands FlowSpec, and it is a standard mechanism for remote-triggered blackholing and traffic scrubbing.

What ships today

The bgp-nlri-flowspec plugin encodes and decodes IPv4 and IPv6 FlowSpec NLRIs, including the VPN variants. It is a normal nlri plugin, so you load it like any other family plugin and enable the families under peer { family { } }.

What ships does not include a high-level "construct a FlowSpec rule from a human-readable description" helper today. The encoding path uses the update text or update hex command with hand-constructed NLRIs. This page assumes you are comfortable at that level.

Configuration

plugin {
    external nlri-flowspec { use bgp-nlri-flowspec; encoder json; }
    external rib           { use bgp-rib;           encoder json; }
}

bgp {
    router-id 10.0.0.100;
    local { as 65000; }

    peer upstream-flowspec {
        remote { ip 10.0.0.1; as 65001; }
        local  { ip 10.0.0.100; }

        capability {
            asn4;
            route-refresh;
        }

        family {
            ipv4/unicast { prefix { maximum 1000; } }
            ipv4/flow    { prefix { maximum 1000; } }
        }

        process rib { receive [ update state ]; send [ update ] }
    }
}

The upstream must negotiate the ipv4/flow family. If it does not, FlowSpec rules you announce will not reach them; the session will still be up, just without FlowSpec.

Injecting a rule

From the CLI:

ze cli -c "peer upstream-flowspec update text \
    origin igp \
    nhop self \
    nlri ipv4/flow add <flowspec-nlri>"

The <flowspec-nlri> is the hex-encoded FlowSpec NLRI for the rule you want to advertise. Ze does not provide a high-level helper for constructing it from a human description. See the in-tree FlowSpec notes for the encoding format and the tests for examples.

Use ze bgp encode or the in-tree test fixtures to build the hex once, and have your script reuse it with parameter substitution.

From a script

An external process script can write the same command to Ze's stdin.

# inject.py (runs under `ze exabgp plugin` or a native Ze plugin)
import sys

def send_flowspec(peer, hex_nlri):
    cmd = (
        f"peer {peer} update text "
        f"origin igp nhop self "
        f"nlri ipv4/flow add {hex_nlri}"
    )
    sys.stdout.write(cmd + "\n")
    sys.stdout.flush()

# ... detection loop ...
send_flowspec("upstream-flowspec", "<hex>")

The script reads events from stdin (the bridge delivers them as JSON), and writes commands to stdout. Ze's process manager forwards the commands to the reactor.

Withdrawing a rule

ze cli -c "peer upstream-flowspec update text \
    nlri ipv4/flow del <flowspec-nlri>"

del uses the same NLRI format as add. The rule is withdrawn from the peer and the upstream removes the filter.

What could go wrong

FlowSpec family not negotiated. If the upstream does not advertise the ipv4/flow capability, your FlowSpec rules are silently not delivered. Check the capability negotiation:

ze cli -c "peer upstream-flowspec capabilities"

Look for ipv4/flow in the family list. If it is missing, FlowSpec cannot work on that session.

Missing prefix limit. FlowSpec counts as a family, so it needs a prefix { maximum }. Forgetting it is the usual mistake.

Rule that matches too much. FlowSpec rules affect production traffic the moment they are accepted upstream. A rule that matches more flows than you intended can black-hole legitimate traffic. Always test a rule against a small subset first, and always have a withdrawal path ready.

No high-level encoder. Constructing FlowSpec NLRIs by hand is error-prone. Use canned rules with parameter substitution, and test every variation before using it in production.

Upstream policy. Most transit providers apply their own policy to FlowSpec rules they receive from customers. A well-constructed rule may still be rejected because the provider does not trust customer FlowSpec in general. Check with your upstream before building anything on top of this.

See also

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally