Ramtin Kiaei

Securing Network Infrastructure for DNS Servers

Ramtin Kiaei
13

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

About the author

Ramtin Kiaei Based in Tehran

Ramtin Kiaei is a network architect, network designer, and technical advisor with over 15 years of experience. He is currently working for one of the biggest telecommunication and service providers companies in Iran as a Senior IP and PS Network Architecture. Before this position, he worked as a senior network specialist for various Telecom companies. He dedicated his time to developing the 5G Core; Networking technologies are very interesting for him. Ramtin has graduated from Qiau University in IT Engineering.

Comments 13