It’s pretty common these days to want to block private IP ranges on your firewall or router in order to protect from DDoS attacks. However, when setting one of these up at work recently, I found out that almost all of the existing posts on doing this with Cisco ACLs involve deny or mixed ACLs. For example, here’s a typical implementation:
ip access-list extended DMZ_Block
! Block private ranges
deny ip 10.0.0.0 0.255.255.255 any
deny ip 172.16.0.0 0.15.255.255 any
deny ip 192.168.0.0 0.0.255.255 any
This works fine if your ACL is already deny-centric with a explicit ‘permit any any’ at the end. But if you have one using the implicit or an explicit ‘deny any any’ at the end, then using this block gives you a mixed ACL, like this:
ip access-list extended DMZ_Block
! Block private ranges
deny ip 10.0.0.0 0.255.255.255 any
deny ip 172.16.0.0 0.15.255.255 any
deny ip 192.168.0.0 0.0.255.255 any
! Allow established connections to continue
permit tcp any any established
! Allow infrustructure traffic
permit udp any any eq domain
permit udp any eq domain any
permit tcp any any eq domain
permit tcp any eq domain any
permit udp any any eq bootps
permit udp any any eq bootpc
! Explicit deny
deny ip any any
I really dislike mixed ACLs because they are much harder to read, especially if you mix permit/deny statements willy-nilly and have a large overall ACL. So here are two permit statements (one for each direction) which allow all IP ranges except the private blocks, so you can block the private ranges in your permit-centric ACL without being forced to build a mixed ACL. First, here’s a statement blocking private ranges as source addresses, for blocking DDoS attacks.
! Block private ranges as source
permit ip 0.0.0.0 7.255.255.255 any
permit ip 8.0.0.0 1.255.255.255 any
permit ip 11.0.0.0 0.255.255.255 any
permit ip 12.0.0.0 3.255.255.255 any
permit ip 16.0.0.0 7.255.255.255 any
permit ip 24.0.0.0 7.255.255.255 any
permit ip 32.0.0.0 31.255.255.255 any
permit ip 64.0.0.0 63.255.255.255 any
permit ip 128.0.0.0 31.255.255.255 any
permit ip 160.0.0.0 7.255.255.255 any
permit ip 168.0.0.0 3.255.255.255 any
permit ip 172.0.0.0 0.15.255.255 any
permit ip 172.32.0.0 0.31.255.255 any
permit ip 172.64.0.0 0.63.255.255 any
permit ip 172.128.0.0 0.127.255.255 any
permit ip 173.0.0.0 0.255.255.255 any
permit ip 174.0.0.0 1.255.255.255 any
permit ip 176.0.0.0 15.255.255.255 any
permit ip 192.0.0.0 0.127.255.255 any
permit ip 192.128.0.0 0.31.255.255 any
permit ip 192.160.0.0 0.7.255.255 any
permit ip 192.169.0.0 0.0.255.255 any
permit ip 192.170.0.0 0.1.255.255 any
permit ip 192.172.0.0 0.3.255.255 any
permit ip 192.176.0.0 0.15.255.255 any
permit ip 192.192.0.0 0.63.255.255 any
permit ip 193.0.0.0 0.255.255.255 any
permit ip 194.0.0.0 1.255.255.255 any
permit ip 196.0.0.0 3.255.255.255 any
permit ip 200.0.0.0 7.255.255.255 any
permit ip 208.0.0.0 15.255.255.255 any
permit ip 224.0.0.0 31.255.255.255 any
Next, here’s the reverse statement, blocking private ranges as destination addresses. This is not useful for blocking DDoS attacks (as the attack has already hit the server and consumed resources by the time this ACL takes effect), but it can be particularly useful if you want to prevent a host on a DMZ from accessing your internal subnets on private address ranges:
! Block private ranges as destinations
permit ip any 0.0.0.0 7.255.255.255
permit ip any 8.0.0.0 1.255.255.255
permit ip any 11.0.0.0 0.255.255.255
permit ip any 12.0.0.0 3.255.255.255
permit ip any 16.0.0.0 7.255.255.255
permit ip any 24.0.0.0 7.255.255.255
permit ip any 32.0.0.0 31.255.255.255
permit ip any 64.0.0.0 63.255.255.255
permit ip any 128.0.0.0 31.255.255.255
permit ip any 160.0.0.0 7.255.255.255
permit ip any 168.0.0.0 3.255.255.255
permit ip any 172.0.0.0 0.15.255.255
permit ip any 172.32.0.0 0.31.255.255
permit ip any 172.64.0.0 0.63.255.255
permit ip any 172.128.0.0 0.127.255.255
permit ip any 173.0.0.0 0.255.255.255
permit ip any 174.0.0.0 1.255.255.255
permit ip any 176.0.0.0 15.255.255.255
permit ip any 192.0.0.0 0.127.255.255
permit ip any 192.128.0.0 0.31.255.255
permit ip any 192.160.0.0 0.7.255.255
permit ip any 192.169.0.0 0.0.255.255
permit ip any 192.170.0.0 0.1.255.255
permit ip any 192.172.0.0 0.3.255.255
permit ip any 192.176.0.0 0.15.255.255
permit ip any 192.192.0.0 0.63.255.255
permit ip any 193.0.0.0 0.255.255.255
permit ip any 194.0.0.0 1.255.255.255
permit ip any 196.0.0.0 3.255.255.255
permit ip any 200.0.0.0 7.255.255.255
permit ip any 208.0.0.0 15.255.255.255
permit ip any 224.0.0.0 31.255.255.255
#1 by AJJB on May 8, 2013 - 7:23 am
Hi, I’m curious how blocking private IPs helps against a DDoS attack. Is it just to defend against captured Hosts attacking your own Servers in your DMZ? Or an issue with spoofing? Anyway: Very elegant ACL, thanks for typing it all out! Same for the rest of your blog, a very informative read.
#2 by Brian Hill on May 8, 2013 - 12:13 pm
AJJB, blocking private ranges helps against certain types of DDoS attacks where the attacker sends a large number of packets with a spoofed source address in the private range. Since the source address is a private address, your endpoint will never be able to reach it, and in the case of TCP traffic, will just continually try to establish a session (SYN/ACK) until the timeout is reached. This makes it easy for the attacker to perpetuate the DDoS with minimal effort.
Oh, and thanks for the comments, glad you liked the post. 🙂
#3 by AJJB on May 14, 2013 - 8:15 am
Ah, I see. Seems like something the ISP should be able to deal with, but I’ve read somewhere this is not always the case. Thanks for the answer!