What is BGP FlowSpec?
Table of Contents
I recently messed about with some Junos Automate Scripts that one of my colleagues had previously been working on, that could be used to add static routes to enable Remote Triggered Blackhole (RTBH) Filtering
(which can be found here), and I found it was a bit rough around the edges (for people who aren’t cli junkies). As I do, I started looking into RTBH and saw that it’s a heavy-handed solution in trying to combat DDoS attacks against a network. RTBH technology has been around for a number of years now and has been defined in RFC 3882 and RFC 5635. In its most basic of terms, you can either blackhole all traffic from a source address and/or to a destination address by injecting the attacking/attacked prefix into BGP with a community that will rewrite the next-hop to a pre-configured discard route on edge routers. If you have massive DDoS trying to block every source address, it would be like going fishing with a shotgun. By blocking the destination address the attacker will have got their desired outcome. With that in mind, using RTBH is ideally a last resort solution. There is an alternative more subtle way of blocking unwanted attack traffic from our network. This alternative method is known as BGP FlowSpec
.
What is BGP FlowSpec⌗
BGP FlowSpec is defined in RFC 5575. RFC 5575 defines a new Multi-Protocol BGP Extension MP-BGP
, in addition, with new Network Layer Reachability Information NLRI
. The new NLRI collects 12 types of Layer 3 and Layer 4 details that are used to define a Flow Specification then actions are assigned to these routes dependant on the user’s needs. If you wanted to look at FlowSpec in a simple form, it is a firewall filter
that is injected into BGP to filter out specific port(s) and protocol(s) just as a normal ACL would do. BGP uses NLRI to exchange routing details between BGP speakers, each of the MP-BGP Extensions have their own NLRI details that are identified by their Address Family Indicator AFI
and Subsequent Address Family Indicator SAFI
. Usually IPv4 unicast routes (also known as BGP families
) are the default for BGP peers, if non IPv4 unicast routes need to be exchanged ie IPv6, EVPN, L2VPN, FlowSpec routes, then MP-BGP defines the relevant NLRI of the router that should have the next-hop of the destination families. This had been defined in RFC 2858 and RFC 4760. As stated above, as of writing, there has been 12 NLRI types defined for BGP FlowSpec, these fields will be added to NLRI field within the BGP Update Message and advertised to peers. In addition, FlowSpec does not support IPv6 yet.
FlowSpec NLRI Types⌗
These are the 12 FlowSpec NLRI types:
Type | NLRI Component |
---|---|
1 | Destination Prefix Defines the destination prefix to match |
2 | Source Prefix Defines the source prefix |
3 | IP Protocol Contains a set of {operator, value} pairs that are used to match the IP protocol value byte in IP packets. |
4 | Port This is defines whether TCP, UDP or both will be packets will be influenced |
5 | Destination Port Defines the destination port that will be influenced by FlowSpec |
6 | Source Port Defines the source port that will be influenced by FlowSpec |
7 | ICMP Type |
8 | ICMP Code |
9 | TCP flags |
10 | Packet Length Match on the total IP packet length (excluding Layer 2 but including IP header) |
11 | DSCP Match on the Class Of Service flag |
12 | Fragment Encoding |
Not all 12 types have to be defined for FlowSpec to be enabled
FlowSpec Actions⌗
RFC 5575 has defined 4 minimum Actions
that routes matching FlowSpec NRLI types can take. These actions are carried as BGP extended communities added to the FlowSpec route. These actions are:
Traffic-Rate Community⌗
The Traffic-Rate community
is non-transitive, that tells the receiving BGP peer, what to rate limit matching traffic to. If the traffic needs to be discarded or dropped, this will be limit of 0 should be used.
Traffic-Action Community⌗
The Traffic-Action community
is used to sample defined traffic. This allows sampling and logging metrics to be collected from the FlowSpec route, that could be used to get a better understand of the attack traffic.
Redirect Community⌗
The Redirect community
allows the FlowSpec traffic to be redirected into a Virtual Routing and Forward Instance VRF
. As the same Route-Targets and Route-Distinguisher can be used, you are able to import routes into a dedicated blackhole VPN or any other VPNv4.
Traffic-Marking Community⌗
The Traffic-Marking community
is used to modify the Differentiated Service Code Point DSCP
bits of a transiting IP packet to the defined value. This could be used to set to FlowSpec routes to highest discard probability, allowing traffic not to dropped/discarded until co
FlowSpec Rule Ordering⌗
It is important to note, that unlike normal firewall filters, FlowSpec routes use a different method of ordering rules. Most firewall filters and/or ACLs use the top-down approach, where in, once the filter has a match any other rules afterward are not inspected. With FlowSpec a deterministic algorithm to order the rules is used. By comparing the left component of each FlowSpec NLRI, the algorithm will use the following details to order FlowSpec Routes:
- If the types differ, the lowest type is used. If the types are the same then component values within that component are compared
- For IP values, the lowest IP prefix is chosen. If the IP addresses are the same then most specific prefix is used
- For all other types, the binary string of the contents is compared to determine the order
Validation Checks⌗
Validate checks within FlowSpec are important, because you could get into a situation where, if no validation checks are done, FlowSpec route(s) could be injected by an attacker that doesn’t own a set of prefix(es) that could blackhole traffic. Like any other unicast BGP route, the next-hop address must resolve for the route to be usable, as per the normal BGP path selection process. In addition, to a valid next-hop, RFC 5775 has defined the follow must be valid of a Flow Specification
:
- The originator of the flow specification matches the originator of the best-match unicast route for the destination prefix embedded in the flow specification.
- There are no more specific unicast routes, when compared with the flow destination prefix, that have been received from a different neighbouring AS than the best-match unicast route, which has been determined in step 1
The overall goal is to confirm that the originator of the FlowSpec route is the same as the originator of the BGP unicast route, this is done by either
using BGP’s AS Path
attribute or if that isn’t present (in iBGP situation) then the Peering IP address is used.
FlowSpec and Junos⌗
Configuring FlowSpec on a JunOS device is actually quite straightforward. I’m being naughty and I don’t actually have a topology set up to show the full verification show commands
outputs on the cli, but when I get the time to set something up, I’ll be back to edit this post. With all that said, Let’s getting cracking :p
The scenario is that we have an attack from 172.90.87.15 on TCP port 80 to the web-server 8.9.0.1. First we will inject a FlowSpec route to discard all TCP port 80 traffic to 8.9.0.1 when the source is from 172.90.87.15. We will need to make sure that we can order the terms as per the RFC requirement, this is done under the show routing-options flow
stanza:
marquk01@TestMX480# show routing-options flow
term-order standard;
Then enable MP-BGP family flow to BGP group
marquk01@TestMX480# show protocols bgp group test
type internal;
family inet {
unicast;
flow
Next configure the FlowSpec Route under routing-options flow route stanza
[edit routing-options flow route test]
marquk01@TestMX480# show
match {
destination 8.9.0.1/32;
source 172.90.87.15/32;
protocol tcp;
port 80;
}
then discard;
With these are the options available under match and then flags. You will note that they are largely the same flags that were stated in the RFC
Match Flags⌗
[edit routing-options flow]
marquk01@TestMX480# set route test match ?
Possible completions:
+ apply-groups Groups from which to inherit configuration data
+ apply-groups-except Don't inherit configuration data from these groups
destination Destination prefix for this traffic flow
+ destination-port Destination TCP/UDP port
+ dscp Differentiated Services (DiffServ) code point (DSCP) (0-63)
+ fragment
+ icmp-code ICMP message code
+ icmp-type ICMP message type
+ packet-length Packet length (0-65535)
+ port Source or destination TCP/UDP port
+ protocol IP protocol value
source Source prefix for this traffic flow
+ source-port Source TCP/UDP port
+ tcp-flags TCP flags
Then Flags⌗
[edit routing-options flow]
marquk01@TestMX480# set route test then ?
Possible completions:
accept Allow traffic through
+ apply-groups Groups from which to inherit configuration data
+ apply-groups-except Don't inherit configuration data from these groups
community Name of BGP community
discard Discard all traffic for this flow
next-term Continue the filter evaluation after matching this flow
rate-limit Rate in bits/sec to limit the flow traffic (9600..1000000000000)
routing-instance Redirect to instance identified via Route Target community
sample Sample traffic that matches this flow
Once committed you will be able to verify Flowspec routes because they are installed into their own routing table inetflow.0
and if dedicated, VRF for FlowSpec routes and the table will be under routing-instance-name.inetflow.0
. You can also check FlowSpec firewall filter by running the command show firewall filter __flowspec_default_inet___
FlowSpec Table⌗
marquk01@TestMX480> show route table inetflow.0 extensive
inetflow.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
8.9.0.1,172.90.87.15,proto=6,port=80/term:3 (1 entry, 1 announced)
TSI:
KRT in dfwd;
Action(s): discard,count
\*Flow Preference: 5
Next hop type: Fictitious
Address: 0x94359c4
Next-hop reference count: 6
State:
Local AS: 65123
Age: 4:10
Validation State: unverified
Task: RT Flow
Announcement bits (1): 0-Flow
AS path: I
Communities: traffic-rate:0:0\[/su\_tab\]
FlowSpec Firewall Filter⌗
marquk01@TestMX480> show firewall filter __flowspec_default_inet__
Filter: __flowspec_default_inet__
Counters:
Name Bytes Packets
8.9.0.1,172.90.87.15,proto=6,port=80 0 0