You are here: Home > Publications > RIPE Labs > Ramtin Kiaei > Securing Network Infrastructure for DNS Servers

Securing Network Infrastructure for DNS Servers

Ramtin Kiaei — 28 Jun 2016
In this article, I'm showing how we can mitigate DNS attacks by implementing a stateless firewall filter at the aggregation or edge router.

Introduction

It's possible that you have some DoS or DDoS attacks every day or at least every week on your DNS servers if you work for an Internet service provider. We want to mitigate the side effects of these attacks in a simple way - by using a stateless firewall filter or access control list (ACL) without the use of any Intrusion Detection Prevention (IDP) or and Intrusion Detection System (IDS). We can’t stop the attacks with this document, but we can help to mitigate them.

This document is meant for network designers, administrators, operators and system administrators. For better understanding, readers should be familiar with the Juniper Junos OS Firewall Filter and Cisco IOS MQC.

NOTE: Please be careful with discarding and rate-limiting DNS packets based on what we show in this document. Test everything in this paper in your lab environment before you use it on your live network. It is advised to tune the numbers provided in this document based on the needs of your customers, your network, your DNS server etc.

In the rest of the document, we describe the steps you can take to mitigate DDoS attacks:

Step 1: DNS query or DNS response message packet length

Do you have any idea of the length of DNS packets? This is a very general question, and I think this question is incomplete, because there are various types of DNS packets, for example query messages, response messages, recursive queries, and each type has a different packet length.

Assume we would know the "standard" packet length of all types of DNS packets, then what ? 

Before I go into the actions you can take, I have to explain some DNS attacks based on packet length. If you know the normal DNS packet length, you can filter or rate-limit suspicious packets on your network devices. 

NOTE : Why do we need to use network devices to filter or rate-limit suspicious DNS packets? Because your network devices do some sophisticated packet handling at the line-rate, but your name servers don’t. If we can filter packets some hops away from your servers, your servers become more stable.   

In order to find out the DNS packet length on your network based on your customer's behaviour, you need to capture DNS traffic at different times and at different directions for more accuracy. After that you can filter and/or rate-limit suspicious DNS packets at your network devices. Please see an example below in Figure 1 where I capture DNS packets from our customers to our DNS servers at different times:


Figure 1:  DNS query from our client to our DNS server


The figure above shows a q uery packet ( Response-Flag=0 ) from our client to our DNS Server and the total length of the packet is 108 bytes. Please notice that the frame total length is 122 bytes which means 108 bytes + 6bytes (DA) + 6bytes (SA) + 2bytes (type). We will use the IP total length (in this example it's 108 bytes).

When a client sends a DNS query to your DNS server, normally the packet length is between 50 and 550 bytes (including the IP header) , so we can filter (or rate-limit) packets that fall outside this range.


Figure 2:  DNS-Response message from our server to our client


Figure 2 shows a response message ( Response-Flag=1 ) from our server to our client. The total length of the packet is 540 bytes (including IP header). As you can also see in Figure 2, the response message is bigger than the query message. Based on my research, response packets have a size between 60 - 900 bytes.

NOTE: Of course these numbers can be bigger or smaller on your network, please check your customers' behaviour in a lab environment before taking any action on your live network.

Now let's assume the following scenario:  

  • Your client's IP address: 10.1.2.200
  • Your DNS server's IP address: 10.10.10.229  
  • Your DNS server's forwarder IP address: 8.8.8.8

Your client asks the following from your DNS server:

1. 10.1.2.200 (SP: 9003 UDP) —> to —> 10.10.10.229 (DP: 53 UDP)  50 bytes < packet length < 550 bytes

If your DNS server is a forwarder, it forwards the client's request to the forwarder IP address (for example: 8.8.8.8) and now the request comes from your DNS server:

2. 10.10.10.229 (SP: 4050 UDP) —> to —> 8.8.8.8 (DP: 53 UDP)   50  bytes < packet length < 550 bytes

Now 8.8.8.8 must respond to your DNS server's request:

  3. 8.8.8.8 (SP: 53 UDP) —> to —> 10.10.10.229 (DP: 4050 UDP)    60  bytes < packet length < 900  bytes

And now you respond to the client's query:  

4. 10.10.10.229 (SP: 53 UDP) —> to —> 10.1.2.200 (DP: 9003 UDP)  60  bytes < packet length < 900 bytes

S o, you can filter or rate limit suspicious requests (based on the packet length) to your DNS servers from untrusted to trusted zones. The image below illustrates this.

Figure 3: Filter or rate-limit at input interface from untrusted-to-trusted on aggregation or edge layer

In Figure 3, we have two DNS servers. If I want to secure these servers at the aggregation or edge layer for maximum stability, we must write a stateless firewall filter on Juniper Junos OS (or MQC on Cisco IOS) at the untrusted-to-trusted interfaces.

The following filter is written for a query packet from an untrusted DNS client to our DNS server. According to my tests, the packet length must be between 50 and 550 bytes. In this filter list every packet from

  • An untrusted-to-trusted network to your DNS servers with
  • UDP destination-port 53 and
  • Packet-length not between 50 and 550 bytes (including IP header)

must be rate-limited with a dns-rate-limiter policer:

show firewall family inet filter untrust-to-trust:         

 term dns-query {       
 
    from {                              
        source-address {                
            0.0.0.0/0;                  
        }                                                          
        destination-prefix-list {       
           your-dns-servers;               
        }                               
        packet-length-except 50-550;    
        protocol udp;                   
        destination-port 53;            
    }                                   
    then {                              
        policer dns-rate-limiter;             
        accept;                         
    }

show firewall policer:

 policer dns-rate-limiter {
 
    if-exceeding {
        bandwidth-limit 2m;
        burst-size-limit 300k;
    }
    then discard;
}

The following filter is written for a response packet from an untrusted DNS server, so the packet length must be bigger than the query packet. Every packet with destination address "your DNS server", UPD source port 53 and packet length not between 60 and 900 bytes (including IP header) must be rate-limited with a dns-rate-limited policer: 

 term dns-respond {                    
 
    from {                               
        source-address {        
            0.0.0.0/0;                  
        }                                                        
        destination-prefix-list {       
            your-dns-servers;               
        }                               
        packet-length-except 60-900;   
        protocol udp;                   
        source-port 53;                 
    }                                 
    then {                              
        policer dns-rate-limiter;             
        accept;                         
    }                                   
}          
 
policer dns-rate-limiter {
    if-exceeding {
        bandwidth-limit 2m;
        burst-size-limit 300k;
    }
    then discard;
}

 

I rate-limit suspicious packets by “policer dns-rate-limiter” with 2m (and 300k burst). Excess traffic must be discarded, but based on your network behaviour, you can filter these packets by replacing “then discard” with “then policer dns-rate-limiter accept”. Please do this carefully, because some normal packet could have a bigger or smaller packet length and if you filter these packets, your customers cannot resolve names.

NOTE: If you use Cisco devices at your aggregation or edge layer you need to be familiar with MQC (Modular QoS CLI) for filtering and/or rate-limiting suspicious packets. Here is an example:

ip access-list extended dns-response

10 permit udp any eq 53 “your-dns-servers”

 

class-map match-all dns-response

match access-group dns-response

match packet length min 60 max 900

 

policy-map dns-response

class dns-response

police 2m 300k exceed-action drop

And finally you must bind service-policy at untrust to trust interfaces.

 

Step 2: What about zero-length ?

Some DNS attacks have a special packet length: it’s Zero! Zero? Which part of the packet can be zero? IP? UDP? Total length? There is certainly no packet with total length=0 (because the IP header is 20 bytes, the TCP header is 20 bytes etc.). Also no DNS packet (query or response) with UDP packet length=0 exists. So, you must filter these packets. Please see an example below:

  show firewall family inet filter untrust-to-trust:

 term DNS-Zero {
 
    from {
        source-address {
            0.0.0.0/0;
        }
        destination-prefix-list {
            your-dns-servers;
        }
        packet-length 0-20;        <<<
    }
    then {
        discard;
    }
}

   

Step 3: DNS fragmented packets

Here is the explanation of “IP fragmentation attack” from “Wikipedia”:

IP fragmentation is the process of breaking up a single Internet Protocol (IP) datagram into multiple packets of smaller size. Every network link has a characteristic size of messages that may be transmitted, called the maximum transmission unit (MTU). Part of the TCP/IP suite is the Internet Protocol (IP) which resides at the Internet Layer of this model. IP is responsible for the transmission of packets between network end points. IP includes some features which provide basic measures of fault-tolerance (time to live, checksum), traffic prioritization (type of service) and support for the fragmentation of larger packets into multiple smaller packets (ID field, fragment offset). The support for fragmentation of larger packets provides a protocol allowing routers to fragment a packet into smaller packets when the original packet is too large for the supporting datalink frames. IP fragmentation exploits (attacks) use the fragmentation protocol within IP as an attack vector.

DNS fragmentation attacks are something like this: packets that are longer than 1,500 bytes and DF (Don't Fragment) bit set to 0, must be fragmented. This is bad news for network administrators because some fragmented packets must be sent to the CPU for processing. In addition, these packets are (probably) abnormal, and if these packets are received by your DNS servers, it will increase the response time and affect your customer’s quality of service.

So, we want to block or rate-limit each packet with a destination IP address equal to your DNS servers, source port and/or destination port 53 (from either TCP or UDP) that is fragmented:

 term dns-fragmentation {
 
    from {
        source-address {
            0.0.0.0/0;
        }
        destination-prefix-list {
            your-dns-servers;
        }
        fragment-flags more-fragments;  
        port 53;   #source-port OR destination-port , DNS-Response or DNS-Query Message.
    }
    then {
        discard;                            
    }
}

"fragment-flags more-fragments" means match the three-bit IP fragmentation flags field  in the IP header.

In the previous section, I drop fragmented DNS packets, but you can also rate-limit by firewall policer.

 

Step 4: Long DNS packets (but not fragmented)

Some DNS packets have a length of approximately 901 - 1,500 bytes. Based on my research these numbers may indicate an abnormal packet for DNS query or DNS response messages, so we must have a plan for large DNS packets. I’m sure by now you know what my plan is:

 term dns-large-packet {
 
    from {
        source-address {
            0.0.0.0/0;
        }
        destination-prefix-list {
            your-dns-servers;
        }
        packet-length 901-1500;
        protocol udp;
        port 53;
    }
    then {
        policer dns-large-packet;    
        accept;
    }
}

 

show firewall policer:

 policer dns-large-packet {
 
    if-exceeding {
        bandwidth-limit 5m;
        burst-size-limit 300k;
    }
    then discard;
}

Y ou can filter large packets,  but be careful  , because some normal DNS response or query messages can be long.

 

Step 5: Allow other DNS packets

We must also allow or rate-limit other DNS packets to the destination address of your DNS servers because at the end I want to filter any UDP packet that does not match with our firewall filter. So I have to allow or rate-limit other lengths of DNS packets:

 term DNS-allow {                     
 
    from {                              
        source-address {                
            0.0.0.0/0;                  
        }                               
        destination-prefix-list {       
            your-dns-servers;               
        }                               
        protocol udp;                   
        port 53;                        
    }                                   
    then accept; #you can rate-limit by firewall policer instead accept, but be careful for discard.      
}             

 

Step 6: Filter other UDP packets

At the end of your firewall filter, you must discard any UDP packets to your  DNS servers:

 term UDP-Filter {                        
 
    from {                              
        source-address {                
            0.0.0.0/0;                  
        }                               
        destination-prefix-list {           
              your-dns-servers         
        }                                                         
        protocol udp;                   
    }                                   
    then {                              
        discard;                        
    }                                   
}       

 

Note: Please don't forget to use "permit term" at the end, for other traffic.


Conclusion

I tried to show you how we can mitigate some DNS attacks in a simple way and without any complex devices. We certainly need IDP for detection and prevention of some anomalies in DNS packets. But I recommend that even if you have an IDP in your network, still use a stateless firewall filter, because it filters suspicious packets at line-rate without using a lot of CPU.

13 Comments

Antonio Prado says:
28 Jun, 2016 01:07 PM
btw,

if I "work for an Internet service provider" as you wrote, why I should forward my internal queries to external servers (8.8.8.8 in your example)?
Ramtin Kiaei says:
28 Jun, 2016 04:35 PM
Dear Antonio

thanks for your comment

i assumed that readers have knowledge about authoritative and non-authoritative DNS servers. if you work for Internet service provider still you can forward dns query to the 8.8.8.8.
Stéphane Bortzmeyer says:
29 Jun, 2016 09:46 AM
But why would you do so? To be sure your users data is recorded by Google? I'm not sure it is even legal, inside the EU.
Stéphane Bortzmeyer says:
28 Jun, 2016 02:35 PM
NIce tricks (I was not aware of the ability to filter by length on my Juniper). I never had a big-query attack, not a zero-length one. Is there any public reports about it?

Now, some criticism. First, a technical paper about DNS servers which does not clearly indicate if they are resolvers or authoritative servers is a bad idea. Here, it seems you talk about resolvers. In that case, like Antonio, I really wonder why you forward to a GAFA instead of directly talking to the authoritative name servers.

But, more important, the technical advice seems wrong: the maximum sizes you indicate are clearly not sufficient for DNSSEC. I know, you said that people should not blindly copy-and-paste your code, they must measure by themselves. But I'm afraid many people will not do it when they enable DNSSEC validation (which will mean increased sizes).

Also, telling that fragmentation is bad and fragments should be blocked is a really poor advice. The Internet has enough broken middleboxes that drop fragments or EDNS or "big" packets, no need to add more!
Ramtin Kiaei says:
28 Jun, 2016 04:37 PM
Dear Stéphane

thanks for your comment

yes this is a new trick for mitigating dns attacks, and no i didn’t see any public report about big-query but this trick work well for me and various companies.

and again (such as above comment), i assumed that readers have knowledge about authoritative and non-authoritative DNS servers.
in this article i didn't talk about DNSSEC, clearly if you want to implement it you must change the packet-length-filtering.

and about fragmentation: i think most of Normal DNS packets are smaller than 1500 bytes and we must have a plan for dns packets that bigger than 1500B, but you can also rate-limit by firewall policer (instead of filtering).
Ralf Weber says:
29 Jun, 2016 09:38 AM
Moin!

So if you have no report of such attacks how do you know it is working well? Just having something doesn't mean it does what it is intended to do.

On the resolver and authoritative server comment. I always asks this question in interviews (of people who have DNS in their CV) and the correct answer rate is below 20%. Given that you are using forwarding I'm not sure if you understand the benefits of having your own resolution process and how to design resilient DNS architectures. What if 8.8.8.8 fails in your setup? Then all these redundant firewalls,routers or MPLS networks won't help you.

Also not considering DNSSEC when designing something for DNS to me seems backwards/outdated. There is trend to larger packets in DNS because of this and other reasons (DNS used as singaling/communications, SPF, DKIM, DANE, etc). Your setup while done with good intension and working now might give you an unpleasant awakening months or years from now.

I've seen similar setups go kaboom during my 20+ years working on delivering DNS service to people on the Internet, so my current stance on this is: Either you are a DNS server or you leave the DNS packet alone.

So long
-Ralf
Ramtin Kiaei says:
29 Jun, 2016 11:39 AM
Dear Ralf
i think you are a system admin or system architect , but this article is good for network architect,
i said " i didn’t see any public report about big-query " , this solution work well for me because i implement it in various Service Provider that their traffic higher than 15G, and i monitor this trick everyday and every week.
anyway, you can change my firewall filter based on your " resilient DNS architectures " and you can rate-limit instead of filtering.
i didn't write about details because i wanted showing a "Hint" and clearly you must change it based on your network or DNS architecture.
Mark Andrews says:
30 Jun, 2016 01:33 AM
No. Firewalls just do not have enough knowledge of the DNS transaction to do anything with a DNS packet. Period.

Firewall vendors have demonstrated that they just don't know the DNS and can't even handle well formed DNS packets. https://ednscomp.isc.org/compliance/summary.html

DNS is no longer a simple protocol where every query for the same <qname,qtype,qclass> tuple is answered the same way sans qid. Only the DNS server has enough knowledge of the DNS traffic to determine what is / isn't a attack. Deploy a modern DNS server and let it deal with the traffic.

Fragmented DNS responses are absolutely normal and no they do not slow up the DNS resolution. In fact they are faster than switching from UDP to TCP. It is a myth that fragment reassembly is slow. You should be asking your firewall vendor for the ability to open a slit (source address, destination address, UDP with only the zero offset fragment being checked for port matching) for reply traffic rather than a pin hole based on source address, source port, destination address, destination port and protocol. Firewalls break legitimate traffic.
Ralf Weber says:
28 Jun, 2016 04:23 PM
Moin!

I agree with Stephane. Just filtering on packet sizes and fragments is a bad idea. Down the road this will have you debug problems for hours until you remember that filter once a popular domain does DNSSEC or has a large answer. I agree that you need to have some defences agains the prevalent DDOS attacks we see on DNS, but it is better to leave decisions on what to do with DNS traffic to the DNS server, unless you are 100% sure it is bogus. The code more likely understands the protocol.

So long
-Ralf
Nick Hilliard says:
28 Jun, 2016 05:01 PM
Does the DNS-Zero term block tcp acks?
Besmir says:
28 Jun, 2016 06:30 PM
Hi,

very nice article. Is there a chance these configurations might be available for Cisco IOS or pfSense?

thank you
Ramtin Kiaei says:
29 Jun, 2016 11:49 AM
Hi Besmir
thanks, yes these configurations available for Cisco with MQC (Modular QoS CLI), i wrote an example for Cisco Devices on Step1 in my article:
ip access-list extended dns-response
10 permit udp any eq 53 “your-dns-servers”
 class-map match-all dns-response
match access-group dns-response
match packet length min 60 max 900
policy-map dns-response
class dns-response
police 2m 300k exceed-action drop

and again (according to comments) : please check everything (your DNS responsibility (cache-only/resolver/forwarder/authoritative/non-authoritative), packet-size, etc ) on your "LAB" before implementing on your "Live Network"
Besmir says:
30 Jun, 2016 01:35 PM
Hi,
Thank you for your reply! Of course everything needs to go first by the LAB :)

Have a nice one!
Besmi
Add comment

You can add a comment by filling out the form below. Comments are moderated so they won't appear immediately. If you have a RIPE NCC Access account, we would like you to log in.