Remote Triggered Black Hole Filtering

By Marko Milivojevic on November 24th, 2010

One of the more unpleasant experiences for any network engineer is handling Denial of Service attack. Even worse one is dealing with Distributed Denial of Service Attack, which usually looks as if the entire Internet is intent on crashing part of your network. In this article, I will explore one of the possible ways to handle this kind of attack in both enterprise and service provider networks.
I will begin by saying that while this technique has been in use for many years, but RFC-5635 detailing it has been published only recently in 2009. This RFC is very good read and I can highly recommend it as a warm-up to this article, which will focus on practical implementation and several caveats.

The biggest challenge when dealing with these kinds of attacks is detecting where they are coming from. In some networks, there are more than a few ingress points and there could be hundreds or even thousands of source addresses participating in the attack. Digesting this information and compiling the exact information takes time. During this time, not only the targets (victims) are suffering, but entire network infrastructure is under stress. In a case of service provider and carrier networks, customers other than those under direct attack may be affected. In other words, collateral damage during the attack investigation can be devastating. It is sometime necessary to “sacrifice” the intended victim, while ensuring the rest of the infrastructure and other customers are relatively unaffected by the attack.

When the infrastructure is protected and stabilized, investigation can take full force and original sources of the attack identified and prevented from further denial of service attack at the intended target.

What I described above are the guiding ideas between two types of DoS protection mechanisms using remote triggered black hole filtering, also known in the industry as RTBH filtering. These two types are destination and source based RTBH filtering.

Here are some brief characteristics of both.

  • Destination Based RTBH:
    • Requires knowledge of the target (victim) address/network.
    • Willingly sacrifices (black-holes) the communication of the target with the rest of the world.
    • Relies on BGP to “signal” black-hole from trigger to one or more enforcers – usually edge (border) routers in the network.
    • Uses unreachable next-hop to drop packets to the destination.
  • Source-Based RTBH:
    • Requires knowledge of the attack source/sources.
    • Attack sources are unable to communicate with the entire protected infrastructure, not only the intended victims.
    • Relies on BGP to “signal” black-hole from trigger to one or more enforcers – usually edge (border) routers in the network.
    • Uses Unicast Reverse Path Forwarding (uRPF) to drop packets.

Test Network

In order to properly test both kinds of RTBH, we will use the following network.

Diagram

On the diagram above, R1 will represent the Internet. Two Loopbacks will represent “good” traffic (1.1.1.1) and “evil” traffic (11.11.11.11). Target/victim host resides on R6 and is represented by a loopback interface with the address 6.6.6.6. R2 and R4 are border routers in AS2456 and they peer with R1. R5 will have multiple roles in this scenario, as we’ll see.

For the initial configuration, we’ll use the following configurations on all involved routers. I will show only relevant bits.

R1:

interface Loopback1
 ip address 1.1.1.1 255.255.255.255
!
interface Loopback11
 ip address 11.11.11.11 255.255.255.255
!
ip bgp-community new-format
!
router bgp 1
 network 1.1.1.1 mask 255.255.255.255
 network 11.11.11.11 mask 255.255.255.255
 neighbor 172.16.12.2 remote-as 2456
 neighbor 172.16.12.2 send-community
 neighbor 172.16.14.4 remote-as 2456
 neighbor 172.16.14.4 send-community
!

R2:

router ospf 1
 network 192.168.0.0 0.0.255.255 area 0
!
ip bgp-community new-format
!
router bgp 2456
 neighbor 172.16.12.1 remote-as 1
 neighbor 172.16.12.1 send-community
 neighbor 192.168.0.4 remote-as 2456
 neighbor 192.168.0.4 update-source Loopback0
 neighbor 192.168.0.4 next-hop-self
 neighbor 192.168.0.4 send-community
 neighbor 192.168.0.5 remote-as 2456
 neighbor 192.168.0.5 update-source Loopback0
 neighbor 192.168.0.5 next-hop-self
 neighbor 192.168.0.5 send-community
 neighbor 192.168.0.6 remote-as 2456
 neighbor 192.168.0.6 update-source Loopback0
 neighbor 192.168.0.6 next-hop-self
 neighbor 192.168.0.6 send-community
!

R4:

router ospf 1
 network 192.168.0.0 0.0.255.255 area 0
!
ip bgp-community new-format
!
router bgp 2456
 neighbor 172.16.14.1 remote-as 1
 neighbor 172.16.14.1 send-community
 neighbor 192.168.0.2 remote-as 2456
 neighbor 192.168.0.2 update-source Loopback0
 neighbor 192.168.0.2 next-hop-self
 neighbor 192.168.0.2 send-community
 neighbor 192.168.0.5 remote-as 2456
 neighbor 192.168.0.5 update-source Loopback0
 neighbor 192.168.0.5 next-hop-self
 neighbor 192.168.0.5 send-community
 neighbor 192.168.0.6 remote-as 2456
 neighbor 192.168.0.6 update-source Loopback0
 neighbor 192.168.0.6 next-hop-self
 neighbor 192.168.0.6 send-community
!

R5:

router ospf 1
 network 192.168.0.0 0.0.255.255 area 0
!
ip bgp-community new-format
!
router bgp 2456
 neighbor 192.168.0.2 remote-as 2456
 neighbor 192.168.0.2 update-source Loopback0
 neighbor 192.168.0.2 send-community
 neighbor 192.168.0.4 remote-as 2456
 neighbor 192.168.0.4 update-source Loopback0
 neighbor 192.168.0.4 send-community
 neighbor 192.168.0.6 remote-as 2456
 neighbor 192.168.0.6 update-source Loopback0
 neighbor 192.168.0.6 send-community
!

R6:

interface Loopback6
 ip address 6.6.6.6 255.255.255.255
!
router ospf 1
 log-adjacency-changes
 network 192.168.0.0 0.0.255.255 area 0
!
ip bgp-community new-format
!
router bgp 2456
 network 6.6.6.6 mask 255.255.255.255
 network 192.168.0.6 mask 255.255.255.255
 neighbor 192.168.0.2 remote-as 2456
 neighbor 192.168.0.2 update-source Loopback0
 neighbor 192.168.0.2 send-community
 neighbor 192.168.0.4 remote-as 2456
 neighbor 192.168.0.4 update-source Loopback0
 neighbor 192.168.0.4 send-community
 neighbor 192.168.0.5 remote-as 2456
 neighbor 192.168.0.5 update-source Loopback0
 neighbor 192.168.0.5 send-community
!

We can see in the above configurations that we are dealing with relatively simple iBGP full mesh configuration with OSPF as IGP in AS2456 and there is eBGP peering between edge routers. Router R1 is advertising its interfaces Loopback1 and Loopback11, while R6 is advertising Loopback0 and Loopback6. These should be visible and reachable from each other. Let’s make sure they are before we proceed!

R1:

R1#show ip route bgp
     6.0.0.0/32 is subnetted, 1 subnets
B       6.6.6.6 [20/0] via 172.16.12.2, 01:49:54
     192.168.0.0/32 is subnetted, 1 subnets
B       192.168.0.6 [20/0] via 172.16.12.2, 01:49:54

R1#ping 6.6.6.6 source Loopback1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/4 ms
R1#ping 6.6.6.6 source Loopback11

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/4/4 ms
R1#ping 192.168.0.6 source Loopback1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.0.6, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/3/4 ms
R1#ping 192.168.0.6 source Loopback11

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.0.6, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/3/4 ms

We don’t need to verify anything on R6, but I will just briefly show you the BGP table there.

R6:

R6#show ip bgp
BGP table version is 14, local router ID is 192.168.0.6
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
* i1.1.1.1/32       192.168.0.4              0    100      0 1 i
*>i                 192.168.0.2              0    100      0 1 i
*> 6.6.6.6/32       0.0.0.0                  0         32768 i
* i11.11.11.11/32   192.168.0.4              0    100      0 1 i
*>i                 192.168.0.2              0    100      0 1 i
*> 192.168.0.6/32   0.0.0.0                  0         32768 i

RTBH Signaling Infrastructure

As I mentioned in the introduction, RTBH relies on BGP for signaling. I neglected to mention what kind of signaling that is. When we decide that certain traffic needs to be discarded by edge routers, we need to let them know that. The simplest method is to advertise the route from one of the BGP routers in our network with a certain community attached. When edge routers receive the route with a community of our choice attached, they can then take steps to discard the traffic. Let’s put this in motion. Our signaling router will be R6.

Please note: Any router in the network can be the “trigger” router. My choice of R6 versus R5 is because I will later use R5 to illustrate couple of caveats with RTBH implementation.

Signaling router will be configured to attach a black-hole community to static routes tagged with a specific tag. You are free to choose any values. In this example I will use static tag “2456″ that will translate to BGP community “2456:2456″. Here is the configuration.

R6:

route-map RTBH-Trigger permit 10
 match tag 2456
 set community 2456:2456
!
route-map RTBH-Trigger permit 99
!
router bgp 2456
 redistribute static route-map RTBH-Trigger
!

To test the solution, let’s add two static routes pointing to Null0 on R6. One will be 192.168.6.1/32 with tag 2456 and the other one 192.168.6.2/32 without a tag. We will then observe what happens in BGP.

R6:

ip route 192.168.6.1 255.255.255.255 Null0 tag 2456
ip route 192.168.6.2 255.255.255.255 Null0

Let’s take a look at R1.

R1:

R1#show ip bgp
BGP table version is 6, local router ID is 172.16.0.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 1.1.1.1/32       0.0.0.0                  0         32768 i
*  6.6.6.6/32       172.16.14.4                            0 2456 i
*>                  172.16.12.2                            0 2456 i
*> 11.11.11.11/32   0.0.0.0                  0         32768 i
*  192.168.0.6/32   172.16.14.4                            0 2456 i
*>                  172.16.12.2                            0 2456 i
*  192.168.6.1/32   172.16.14.4                            0 2456 ?
*>                  172.16.12.2                            0 2456 ?

We are receiving both of these routes. While this is perfectly OK when we are using Null0 routes to inject prefixes into BGP, we need to ensure that RTBH signaling routes do not “leak” into neighboring autonomous systems – unless, of course, we use inter-AS signaling for RTBH, which is not something I will touch on today. The easiest way to prevent leaks is to ensure that trigger routes are not exported outside our own autonomous system, using well-known “no-export” community.

R1:

route-map RTBH-Trigger permit 10
 match tag 2456
 set community 2456:2456 no-export
!

Let’s verify the status on R1 again.

R1:

R1#show ip bgp
BGP table version is 9, local router ID is 172.16.0.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 1.1.1.1/32       0.0.0.0                  0         32768 i
*  6.6.6.6/32       172.16.14.4                            0 2456 i
*>                  172.16.12.2                            0 2456 i
*> 11.11.11.11/32   0.0.0.0                  0         32768 i
*  192.168.0.6/32   172.16.14.4                            0 2456 i
*>                  172.16.12.2                            0 2456 i
*  192.168.6.2/32   172.16.14.4                            0 2456 ?
*>                  172.16.12.2                            0 2456 ?

We can see that now only the 2nd route is present on R1. Let’s see R2.

R2:

R2#show ip bgp
BGP table version is 17, local router ID is 192.168.0.2
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
* i1.1.1.1/32       192.168.0.4              0    100      0 1 i
*>                  172.16.12.1              0             0 1 i
*>i6.6.6.6/32       192.168.0.6              0    100      0 i
* i11.11.11.11/32   192.168.0.4              0    100      0 1 i
*>                  172.16.12.1              0             0 1 i
r>i192.168.0.6/32   192.168.0.6              0    100      0 i
*>i192.168.6.1/32   192.168.0.6              0    100      0 ?
*>i192.168.6.2/32   192.168.0.6              0    100      0 ?
R2#show ip bgp 192.168.6.1
BGP routing table entry for 192.168.6.1/32, version 16
Paths: (1 available, best #1, table Default-IP-Routing-Table, not advertised to EBGP peer)
Flag: 0x880
  Not advertised to any peer
  Local
    192.168.0.6 (metric 66) from 192.168.0.6 (192.168.0.6)
      Origin incomplete, metric 0, localpref 100, valid, internal, best
      Community: 2456:2456 no-export
R2#show ip bgp 192.168.6.2
BGP routing table entry for 192.168.6.2/32, version 17
Paths: (1 available, best #1, table Default-IP-Routing-Table)
Flag: 0x820
  Advertised to update-groups:
        1
  Local
    192.168.0.6 (metric 66) from 192.168.0.6 (192.168.0.6)
      Origin incomplete, metric 0, localpref 100, valid, internal, best

With that verified, we can remove our test routes from R6.

R6:

no ip route 192.168.6.1 255.255.255.255 Null0 tag 2456
no ip route 192.168.6.2 255.255.255.255 Null0

Our signaling is now ready. The next step is to actually implement traffic drop. This is where things become somewhat different for destination-based and source-based RTBH. We will explore them separately.

Destination-Based RTBH

With destination-based black-hole we will be dropping the traffic going TO a particular destination. Therefore, our trigger router needs to indicate this. Our test destination (victim) is the Loopback6 on R6. Since this is directly connected interface on R6, we can’t use the static route as in the previous example, but we can simply add the community to the advertisement.

R6:

route-map Loopback6-RTBH
 set community 2456:2456
!
router bgp 2456
 network 6.6.6.6 mask 255.255.255.255 route-map Loopback6-RTBH
!

We can now see that on R2 and R4 6.6.6.6/32 is received with the community.

R2:

R2#show ip bgp 6.6.6.6
BGP routing table entry for 6.6.6.6/32, version 20
Paths: (1 available, best #1, table Default-IP-Routing-Table)
Flag: 0x880
  Advertised to update-groups:
        1
  Local
    192.168.0.6 (metric 66) from 192.168.0.6 (192.168.0.6)
      Origin IGP, metric 0, localpref 100, valid, internal, best
      Community: 2456:2456

Those with sharp eyes probably noticed that I didn’t add no-export. The reason for that is that 6.6.6.6/32 is considered to be part of AS2456. It’s perfectly OK to have it advertised to the outside world, even with the additional community set. At this moment we also want R1 to have the reachability to R6 so we can test if our black hole works. We will remove this route later on.

That said, we now have the route, again, but what do we do with it? Remember, the idea here is to drop the traffic going to this destination. In order to accomplish this task, we will need to somehow redirect the traffic on our enforcing routers (R2 and R4) and instead of sending it towards R6, drop it. We can do that by changing the next-hop attribute in BGP.

Next-hop is mandatory BGP attribute. We can see in the output above that next-hop for 6.6.6.6 is 192.168.0.6. To implement the drop, we will have to use a single Null0 static route and an imaginary address for next-hop. The usual address used for this purpose is part of the official test network, as defined by RFC-1918. This is any address from 192.0.2.0/24 subnet. I will use 192.0.2.1/32 and here is how.

R2 and R4:

ip route 192.0.2.1 255.255.255.255 Null0
!
ip community-list standard RTBH-Trigger permit 2456:2456
!
route-map UseRTBH permit 10
 match community RTBH-Trigger
 set ip next-hop 192.0.2.1
!
route-map UseRTBH permit 99
!
router bgp 2456
 neighbor 192.168.0.6 route-map UseRTBH in
!

What I did there is I created a route-map to apply in the input direction from R6 on R2 and R4. This route-map will match the trigger community and for those routes that match, set the next-hop to 192.0.2.1. Unless I have static route (or other source) for this next-hop, route would be invalid. However, I do not want the route to be invalid, because then some other route, possible less-specific, route can take the traffic. What I want is the trigger route to be considered the best, so I can explicitly drop the traffic for the destination.

Let’s see if this works. First off, let’s see the next hop on R2.

R2:

R2#show ip bgp 6.6.6.6
BGP routing table entry for 6.6.6.6/32, version 23
Paths: (1 available, best #1, table Default-IP-Routing-Table)
Flag: 0x820
  Advertised to update-groups:
        1
  Local
    192.0.2.1 from 192.168.0.6 (192.168.0.6)
      Origin IGP, metric 0, localpref 100, valid, internal, best
      Community: 2456:2456

This worked. Let’s see the ping from R1.

R1:

R1#ping 6.6.6.6 source Loopback11

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
U.U.U
Success rate is 0 percent (0/5)
R1#ping 192.168.0.6 source Loopback11

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.0.6, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/4/4 ms

We can see that from R1 we cannot ping Loopback6 on R6, but we can easily access Loopback0. If Loopback6 was under attack, this would cause traffic to that destination to be dropped by R2 and R4, adding no additional workload for R5 and R6. However… there is one minor problem. You can see that border routers are generating ICMP unreachable messages. This is causing more work for them and increases their CPU load. One can be tempted to simply disable ICMP unreachable messages on interfaces facing R1, but that can break legitimate things like Path MTU Discovery. What we need is a way to stop sending unreachables for traffic redirected to Null0 interface. You may be surprised how easily that is done.

R2 and R4:

interface Null0
 no ip unreachables
!

Let’s test again from R1.

R1:

R1#ping 6.6.6.6 source Loopback11

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
.....
Success rate is 0 percent (0/5)

Much better. Still, we’re indiscriminately dropping the traffic going to 6.6.6.6. Let’s see what we can do when we figure out who the attacker is.

Source-Based RTBH

We discovered that source of our attack is 11.11.11.11/32. We can now implement source-based RTBH. Method is very similar to the one used just before, except that we signal with the static route for 11.11.11.11/32 on R6. I will now remove the community from 6.6.6.6 and add the trigger for 11.11.11.11/32.

R6:

router bgp 2456
 no network 6.6.6.6 mask 255.255.255.255 route-map Loopback6-RTBH
 network 6.6.6.6 mask 255.255.255.255
!
ip route 11.11.11.11 255.255.255.255 Null0 tag 2456

Since our infrastructure is already in place, we should see this prefix with the next-hop of 192.0.2.1 on R2.

R2:

R2#show ip bgp 11.11.11.11
BGP routing table entry for 11.11.11.11/32, version 28
Paths: (2 available, best #1, table Default-IP-Routing-Table, not advertised to EBGP peer)
Flag: 0x820
  Not advertised to any peer
  Local
    192.0.2.1 from 192.168.0.6 (192.168.0.6)
      Origin incomplete, metric 0, localpref 100, valid, internal, best
      Community: 2456:2456 no-export
  1
    172.16.12.1 from 172.16.12.1 (172.16.0.1)
      Origin IGP, metric 0, localpref 100, valid, external

If I ping from Loopback11 of R1, no traffic should be reaching R6, while ping from Loopback1 should work. Let’s try.

R1:

R1#ping 6.6.6.6 source Loopback11

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
.....
Success rate is 0 percent (0/5)
R1#ping 6.6.6.6 source Loopback1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/3/4 ms

This seems to work… or does it? Let’s enable some debug on R6 and re-run the ping.

R6:

access-list 100 permit icmp any any echo
access-list 100 permit icmp any any echo-reply
R6#debug ip packet 100

R1:

R1#ping 6.6.6.6 source Loopback11 repeat 1

Type escape sequence to abort.
Sending 1, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
.
Success rate is 0 percent (0/1)

R6:

 IP: s=11.11.11.11 (FastEthernet0/0), d=6.6.6.6, len 100, input feature, MCI Check(64), rtype 0, forus FALSE, sendself FALSE, mtu 0, fwdchk FALSE
 IP: tableid=0, s=11.11.11.11 (FastEthernet0/0), d=6.6.6.6 (Loopback6), routed via RIB
 IP: s=11.11.11.11 (FastEthernet0/0), d=6.6.6.6, len 100, rcvd 4
 IP: s=11.11.11.11 (FastEthernet0/0), d=6.6.6.6, len 100, stop process pak for forus packet
 IP: s=6.6.6.6 (local), d=11.11.11.11 (Null0), len 100, sending

We can see that R1 is not getting any responses, but R6 is still getting the traffic! We have NOT stopped the DoS attack. To do so, we need to verify if the source of the traffic is valid. We will use uRPF feature as mentioned earlier. To be more precise, we will use loose uRPF, which will only verify if the route to the destination is valid. Null0 route is not considered valid and uRPF will fail. Let’s configure that on R2 and R4 facing R1.

R2:

interface GigabitEthernet0/1
 ip verify unicast source reachable-via any
!

R4:

interface FastEthernet0/0
 ip verify unicast source reachable-via any
!

When we re-run the ping from R1, we should see no debugging output on R6. We have now stopped the attack from 11.11.11.11! There are still few possible design-related issues.

Partial Implementation Caveats

What happens in a case that for example filtering is done only by R2, but not R4? If the traffic reached R4, it would reach R5 and ultimately R6. One way to prevent this issue from happening is to force the next-hop change on the trigger router itself. In our case this is on R6. If we decide to go with that option, we may be creating yet another problem, which is not immediately obvious. Let’s change our network so that R5 is the route-reflector, with R2, R4 and R6 being clients. I will also change where the next-hop is changed. Here is the configuration.

R2:

router bgp 2456
 no neighbor 192.168.0.4
 no neighbor 192.168.0.6
!

R4:

router bgp 2456
 no neighbor 192.168.0.2
 no neighbor 192.168.0.6
!

R5:

router bgp 2456
 neighbor 192.168.0.2 route-reflector-client
 neighbor 192.168.0.4 route-reflector-client
 neighbor 192.168.0.6 route-reflector-client
!

R6:

ip route 192.0.2.1 255.255.255.255 Null0
!
ip community-list standard RTBH-Trigger permit 2456:2456
!
route-map SetNH permit 10
 match community RTBH-Trigger
 set ip next-hop 192.0.2.1
!
route-map SetNH permit 99
!
router bgp 2456
 no neighbor 192.168.0.2
 no neighbor 192.168.0.4
 neighbor 192.168.0.5 route-map SetNH out
!

Let’s see the trigger route on R5.

R5:

R5#show ip bgp 11.11.11.11
BGP routing table entry for 11.11.11.11/32, version 62
Paths: (1 available, best #1, table Default-IP-Routing-Table, not advertised to EBGP peer)
Flag: 0x800
  Advertised to update-groups:
        2
  Local, (Received from a RR-client)
    192.0.2.1 (metric 2) from 192.168.0.6 (192.168.0.6)
      Origin incomplete, metric 0, localpref 100, valid, internal, best
      Community: 2456:2456 no-export

How can the route be valid, when there is no valid next-hop? Or is there a valid next-hop?

R5:

R5#show ip route 192.0.2.1
Routing entry for 192.0.2.1/32
  Known via "bgp 2456", distance 200, metric 0, type internal
  Last update from 192.168.0.6 00:01:20 ago
  Routing Descriptor Blocks:
  * 192.168.0.6, from 192.168.0.6, 00:01:20 ago
      Route metric is 0, traffic share count is 1
      AS Hops 0

Router R6 is advertising the 192.0.2.1 route, which means that it may still attract the traffic if only one of the border routers are misconfigured! To fix this issue, we must prevent this route from being advertised by R6. Even more filtering!

R6:

ip prefix-list NO-TRIGGER permit 192.0.2.0/24 le 32
!
route-map RTBH-Trigger deny 20
 match ip address prefix-list NO-TRIGGER
!

Now, the situation on R5 is completely different.

R5:

R5#show ip bgp 11.11.11.11
BGP routing table entry for 11.11.11.11/32, version 67
Paths: (3 available, best #3, table Default-IP-Routing-Table)
  Advertised to update-groups:
        2
  Local, (Received from a RR-client)
    192.0.2.1 (inaccessible) from 192.168.0.6 (192.168.0.6)
      Origin incomplete, metric 0, localpref 100, valid, internal
      Community: 2456:2456 no-export
  1, (Received from a RR-client)
    192.168.0.4 (metric 65) from 192.168.0.4 (192.168.0.4)
      Origin IGP, metric 0, localpref 100, valid, internal
  1, (Received from a RR-client)
    192.168.0.2 (metric 65) from 192.168.0.2 (192.168.0.2)
      Origin IGP, metric 0, localpref 100, valid, internal, best

Since next-hop is no longer advertised, the trigger route is inaccessible. In turn, it will not be advertised to enforcing edge routers and will cause the attack traffic to be routed inside the infrastructure network. To fix this issue, we should add yet another static Null0 route, this time on R5.

R5:

ip route 192.0.2.1 255.255.255.255 Null0

Again, here we need to be careful that R5 does not advertise this route, or misconfigured edge router may send the traffic towards the router-reflector! Let’s see what we have learned from this.

Learned Lesson

Hopefully this small exercise with next-hop and filtering illustrated an important issue with RTBH. It is an extremely powerful feature, but it requires careful planning and implementation. More importantly, if it’s not implemented on all of the border routers, unintended targets such as route-reflectors or trigger router may become victims of a DDoS, instead of a server or an end user. This is a potential disaster.

Also, while inviting as an idea, setting next-hop on the trigger router may cause deeper issues and require more configuration throughout the network. It’s better avoided if not required.

I hope you enjoyed this article. Happy studies!


Marko Milivojevic – CCIE #18427
Senior Technical Instructor – IPexpert
Join our Online Study List

Remote Triggered Black Hole Filtering, 5.0 out of 5 based on 4 ratings
Be Sociable, Share!

    Tags: BGP, DDoS, DoS, RTBH, Security

    9 Responses to “Remote Triggered Black Hole Filtering”

    1. jahangir says:

      Nice typology and configuration

      VA:F [1.9.22_1171]
      Rating: 0.0/5 (0 votes cast)
    2. naveen says:

      Great article marko.

      VA:F [1.9.22_1171]
      Rating: 0.0/5 (0 votes cast)
    3. Jason Parker says:

      thanks for the article! Great and practical advice

      VA:F [1.9.22_1171]
      Rating: 0.0/5 (0 votes cast)
    4. PeterA says:

      Interesting article. I am a little confused on one point that hopefully someone can clarify for me.

      After adding the route-map and static routes to R6 why is the 192.168.6.2/32 missing from the BGP table on R1? What am i missing?

      Regards,
      Peter

      VA:F [1.9.22_1171]
      Rating: 0.0/5 (0 votes cast)
      • Are you referring to 192.168.6.1/32 perhaps?


        Marko Milivojevic – CCIE #18427
        Senior Technical Instructor – IPexpert
        Join our Online Study List

        VN:F [1.9.22_1171]
        Rating: 0.0/5 (0 votes cast)
        • PeterA says:

          Im sure i am missing something here but it looks to me like you have added 2 static routes, 192.168.6.1 (tagged with 2456) and 192.168.6.2 pointing to null0. Then you redistribute both routes into BGP through the route-map RHTB-Trigger on R6.

          However when you look at the bgp table on R1, the first route to 192.168.6.1 makes it into the BGP table but the second route to 192.168.6.2 is not listed.

          I did notice that the 192.168.6.2 route appears in the route table on R1 after you add the no-export community to the first line of the router map. What i don’t understand is why?

          VA:F [1.9.22_1171]
          Rating: 0.0/5 (0 votes cast)
    5. Sepiraph says:

      This is a very interesting and informative article, I can’t wait to lab it up in gns3.

      VA:F [1.9.22_1171]
      Rating: 0.0/5 (0 votes cast)
    6. Ramcharan Arya says:

      Great Article, Excellent Job Marko !

      VA:F [1.9.22_1171]
      Rating: 0.0/5 (0 votes cast)
    7. Kamil says:

      I remember mitigating DDoS 3 o’clock in the morning on our network spread across the whole UK and analyzing the source and destination IPs with the Netflow collectors. It led me to creation of lab and then implementation of the RTBH where attacked IP is attached to route-map which auto-sets next hop to Null0 bucket as well as notify our upstream providers to auto-block (Null route) the attacked IP on their side – all based on the BGP community tags.

      Quite a fun I have to admit.

      VA:F [1.9.22_1171]
      Rating: 0.0/5 (0 votes cast)

    Leave a Reply