Wednesday, July 20, 2011

Mitigating DoS/DDoS attacks with Real Time Black Hole (RTBH) filtering


RTBH is something that I’ve been using for quite some time to mitigate inbound Denial of Service (DoS) attacks against customers. We are currently in the process of deploying an automated traffic scrubbing platform (Arbor Networks and Cisco Guards), but I still see this as an extremely valuable way to quickly put an end to an attack.


What is an DoS/DDoS attack?
Essentially, a DoS attack is when someone sends bogus traffic towards an IP (or group of IPs) with the goal of overwhelming the destination circuit. In a DoS situation, an attacker usually initiates this traffic from a compromised PC or server. A DDoS (Distributed 11Denial of Service) is when a group of PCs or servers initiate the traffic.
Types of RTBH filtering
There are two types of RTBH mitigation. Source based and destination based.
Source based RTBH is the preferred method of mitigating attacks. In this instance, the source address(es) of an attack are null routed in the network. Combined with uRPF, routers will drop this traffic as it enters the network.
Destination based RTBH should only be used as a last resort, since you are essentially completing the DoS by null routing your customer. The only time this should be done is when other customers are affected and there are too many source addresses to null route (a spoofed DDoS). Additionally, you want to contact your customer as soon as possible so that you can assist them in getting back online.
Unicast Reverse Path Filtering (uRPF)
There are two types of uRPF – strict and loose mode. In strict mode, a ingress packet must be received on an interface that the router would use to forward return packets. If that fails, the packet is dropped. Loose mode is less strict in that the source address must exist in the routing table. Additionally, any source address that is attached to the Null0 interface is dropped.
In our RTBH examples, we’ll use loose mode uRPF on our peering/transit interfaces.
Deploying RTBH
There are a few steps to fully deploying RTBH in your network.
1) Null route
First, we want to add a null route that we can use as a next-hop for traffic we wish to drop. This could be one of your own IPs, RFC1918 space, or from the RFC3330 TEST-NET blocks.
westcr1(config)#ip route 192.0.2.1 255.255.255.255 null0
Note: This should never be leaked. In my deployment, we use outbound route-maps to match on, as well as a prefix-list to sanity check longest prefixes. You could also use a tag to specifically exclude this from announcements.
westcr1(config)#ip route 192.0.2.1 255.255.255.255 null0 tag 666
This should be added to any router where you wish to drop traffic. In our network, all routers contain this static route – edge, aggregation, and core.
2) uRPF
Next, we want to enable loose-mode uRPF on our transit/peering interfaces. By doing this, mitigated traffic is dropped as soon as it enters our network. We use loose mode because traffic can be asymmetrical. That is, it could enter via one peer and return traffic could exit via another peer on a different router.
On a 7600, the command is:
ip verify unicast source reachable-via any
An actual (redacted) interface:
interface GigabitEthernet1/4
 description [transit]_A.B.C.D_TWTC_ID:##/KFFN/######/TWCS
 ip address A.B.C.D 255.255.255.252
 ip verify unicast source reachable-via any
 ip route-cache flow
 load-interval 30
 speed nonegotiate
 wrr-queue cos-map 1 1 4
 wrr-queue cos-map 1 8 0
 wrr-queue cos-map 2 6 1
 wrr-queue cos-map 2 8 2
 wrr-queue cos-map 3 6 3
 wrr-queue cos-map 3 8 6 7
 service-policy input MARK-IPP-0
3) BGP Policy
Now, we need to configure the BGP policy. But, before we do this, we want to identify a single router that is used to inject these null routes. This can be a router or a Unix based server running Quagga. We use a dedicated Cisco 7206 for this purpose.
Injection router configuration
First, we have a prefix-list of “Golden” networks that we never want to accidentally null route due to spoofing. Before adding a route, we always check the owner of the netblock an attack originates from. If it’s obviously critical infrastructure, we’re dealing with a spoofing attack. We don’t want to null route a root server or anything like that.
ip prefix-list GOLDEN:NETWORKS seq 5 permit 198.41.0.0/24 le 32
ip prefix-list GOLDEN:NETWORKS seq 10 permit 192.228.79.0/24 le 32
[...]
Next, we want to make sure we don’t null route a default route.
ip prefix-list NO-DEFAULT seq 5 permit 0.0.0.0/0
Now, it’s time for the route-map.
route-map BLACKHOLE deny 5
 match ip address prefix-list GOLDEN:NETWORKS
!
route-map BLACKHOLE deny 10
 match ip address prefix-list NO-DEFAULT
!
route-map BLACKHOLE permit 20
 match tag 187
 set ip next-hop 192.0.2.1
 set local-preference 1000
 set origin igp
 set community 65500:666 no-export
!
route-map BLACKHOLE permit 30
 set ip next-hop 192.0.2.1
 set local-preference 1000
 set origin igp
 set community 65500:666 no-export
Here, we deny anything listed in the first two prefix-lists. The 3rd stanza is used to match on known netblocks assigned to organizations such as RBN and others.
The fourth matches any other routes.
4) Static route redistribution
Now, in order to announce these prefixes, we apply the route-map to static route redistribution in our BGP config.
router bgp 65500
 address-family ipv4
  redistribute static route-map BLACKHOLE
Note: I’m assuming your router already has bgp sessions to other devices to propagate the routes.
5) Adding routes
Now, when you experience a DoS, you can find the source (we use Netflow) and add a static route such as:
nullrouter(config)#ip route 192.168.202.12 255.255.255.255 Null0 tag 80
The tag doesn’t need to be included, but we use it to identify what type of attack. In this case, it was a DoS targeting port 80. If this was an address of a known c&c server, we’d use tag 187 to identify it as such.
Now, if we login to a router that receives these routes, we should see 192.0.2.1 set as the next-hop.
atlngaxxla1#sh ip bgp 192.168.202.12
BGP routing table entry for 192.168.202.12/32, version 41279494
Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Advertised to update-groups:
     2          3          4          5          8
  Local, (Received from a RR-client), (received & used)
    192.0.2.1 from A.B.C.253 (A.B.C.253)
      Origin IGP, metric 0, localpref 1000, valid, internal, best
      Community: 65500:666 no-export
This causes uRPF to fail on your transit/peering interfaces because the route is destined to the Null0 interface, dropping traffic immediately on entering your network.
This also causes traffic initiated inside the network to be dropped.
pts/1 jrowley@SIFT01:/home/jrowley $> traceroute 192.168.202.12
traceroute to 192.168.202.12 (192.168.202.12), 30 hops max, 40 byte packets
 1  vlan18.host.domain.net (A.B.C.126)  1.791 ms  1.844 ms  1.895 ms
 2  * * *
 3  * * *
 4  * * *
 5  * * *
 6  * ^C
Considerations
It is imperative that you use this sparingly. RTBH can be like shooting yourself in the foot with a bazooka if done wrong.
Always use no-export on null routes. Even though they are typically /32s, you still want to take care that they are not leaked to your peers.
Additionally, never accept RTBH announcements from your peers (customers are ok only if your inbound policies are tight enough to only permit /32s from their own address space).
Never null route your customers unless absolutely necessary.
Don’t leave null routes in place permanently. We typically remove them after one week, except for known bad nets.