Granular, efficient and distributed firewalling based on good old BGP.

BGP can carry many different network-related information, sometimes described as address families or NLRI (Network Layer Reachability Information). One of them is FlowSpec (RFC 5575), which allows BGP to propagate a filter for a specific IPv4 packet flow. A flow, which is defined by an n-tuple, like a combination of source and destination IP address, protocol number and ports, can be discarded, rate-limited, redirected to some analysis or mitigation device etc. BGP is simply used to signal the routers to perform appropriate filtering actions for a certain flow.

BGP routers in the mesh learn what to do with the traffic that matches the n-tuple – for example, they can drop it or limit it to a some harmless rate. This technique makes BGP routers act like a big distributed firewall that can be easily programmed to mitigate some malicious traffic, a DDoS, for example.

The added value of using BGP to propagate filtering information is that DDoS mitigation actions are distributed across the network and therefore closer to the source of the attack.

The specification was written by guys from Cisco, Juniper, Arbor Networks and NTT America, but only Juniper implements it at the time of writing. Here is an example for the Junos OS. First, let us statically define a flow:

[edit routing-options flow]

route TestFlowRoute {

match {

destination 10.10.10.10/32;

source 192.168.1.1/32;

protocol tcp;

tcp-flags ack;

}

then rate-limit 1m;

}

term-order standard;



This locally defined static “flow route” is installed in the inetflow.0 routing table and it is known from a Flow protocol with a Fictitious next-hop type:

matjaz@router.re0> show route table inetflow.0

inetflow.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)

+ = Active Route, - = Last Active, * = Both

10.10.10.10,192.168.1.1,proto=6,tcp-flag:10/term:1

*[Flow/5] 00:34:40

Fictitious



We can inject these kind of routes into BGP with an appropriate import policy. For example:

[edit protocols bgp group iBgp]

type internal;

import [ ImportStaticFlowSpec ...more policy... ];

family inet {

unicast;

flow;

}

[edit policy-options policy-statement ImportStaticFlowSpec]

term Import {

from rib inetflow.0;

then accept;

}



Now our statically defined flow route is being advertised to our BGP neighbours:

matjaz@router.re0> show route advertising-protocol bgp x.y.z.w table inetflow.0

inetflow.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)

Prefix Nexthop MED Lclpref AS path

10.10.10.10,192.168.1.1,proto=6,tcp-flag:10/term:1

* Self 100 I



Let us check the receiving BGP router. Here, our test flow route is shown as hidden because it failed the validation:

matjaz@router.re0> show route table inetflow.0 hidden extensive

inetflow.0: 1 destinations, 1 routes (0 active, 0 holddown, 1 hidden)

10.10.10.10,192.168.1.1,proto=6,tcp-flag:10/term:N/A (1 entry, 0 announced)

BGP /-101

Next hop type: Fictitious

Address: 0x9011424

Next-hop reference count: 1

State: <Hidden Int Ext>

Local AS: myAS Peer AS: myAS

Age: 2:56

Validation State: unverified

Task: BGP_myAS.x.y.z.q+179

AS path: I

AS path: Recorded

Communities: myAS:65533 traffic-rate:0:1000000

Validation state: Reject, Originator: x.y.z.q

Via: 0.0.0.0/4, Active

Localpref: 100

Router ID: x.y.z.q

The receiving router performs a validation process before installing the flow route into the routing table and setting up the firewall filter. A flow route is accepted if it passes the following criteria:

The originator of a flow route matches the originator of the best match unicast route for the destination address that is embedded in the route.

There are no more specific unicast routes, when compared to the destination address of the flow route, for which the active route has been received from a different next-hop autonomous system.

In our example, the originator of the best matched route toward the destination address 10.10.10.10 does not match. However, you can bypass the validation process and write your own import policy to check the received flow routes, like this:

[edit protocols bgp group iBgp]

family inet {

unicast;

flow {

no-validate FlowSpecRoutes;

}

}

[edit policy-options policy-statement FlowSpecRoutes]

from community FlowSpec;

then accept;



Please, check Juniper documentation and RFC for more details.

The feature has been implemented in GRNET – Greek academic, research and educational network as a Firewall on Demand service (here is an interesting talk by Leonidas Poulopoulos from GRNET at 2nd SEE Regional RIPE Meeting in Skopje).