Indentical Queries DNS Reflection Attack Protection

Problem this snippet solves:

Basically, the iRule detects identical queries which come from the same network inside the TTL. Logically, DNS Resolvers are supposed to cache the answers and not to send hundreds or thousands time the same query during the TTL. If the number of those identical queries goes over the maximum authorized then two protection mechanisms are used: 1) Send an almost empty answer with the TC flag to force the LDNS to repeat the query over TCP -> protect against IP spoofing of non LDNS servers. 2) In case of TCP, rate limiting outgoing DNS responses -> limit the flow toward the LDNS network to protect against an overflow of the link and continue to serve real LDNS servers.

Code :

                # var attack will be set to 1 if attack is detected
                set attack 0
                # var max_number_of_identical_query is the max authorized of identical queries from the same network source inside the TTL 
                set max_number_of_identical_queries 10
                # var net_ldns is the source class C network of the DNS request"
                set net_ldns [IP::addr [IP::remote_addr] mask]
                # Log query details
                log local0. "Query from $net_ldns: [DNS::question name],[DNS::question class],[DNS::question type]"
                set query "[DNS::question name],[DNS::question class],[DNS::question type]"
                set key "$net_ldns-$query"
                if {[table lookup $key] !=""} {
                                log local0.alert "identical queries from $net_ldns inside the TTL. It's suspicious"
                                set count [table incr $key]
                                log local0.alert "nb of identical queries from $net_ldns is $count"
                                if {$count > $max_number_of_identical_queries} {
                                                log local0.alert "Attack detected: Too many identical requests detected from $net_ldns inside the TTL."
                                                set attack 1

                if {$attack == 1} {
                                #if attack detected and DNS over UDP, force LDNS to connect over TCP. It will prevent IP Spoofing and allows to apply all the TCP protections.
                                if {[IP::protocol] != 6} {
                                                log local0.alert "Modification of TC flag into an almost empty response to force the LDNS to retry over TCP"
                                                DNS::answer clear
                                                DNS::header tc 1
                                else {
                                                log local0.alert "Throttle outgoing response"
                                                rateclass dns_rate_shape
                } elseif {[table lookup $key] !=""} {
                                log local0.alert "Regular answer: identical query from $net_ldns inside the TTL but under the max number authorized" 
                } else {
                                log local0.alert "First Request from $net_ldns. Creation of the entry into the table"
                                set key "$net_ldns-$query"
                                table set $key 1 indefinite [DNS::ttl [DNS::answer]]  
Published Mar 18, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment