Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Answers

DNS Tunneling Mitigation v2

Due to some people attempt DNS tunneling to pass data frames inside of DNS records to the Internet and the lack of information around here, I'm going to share with you some basic code for DNS Tunnel Mitigation on the BIG-IPs. This irule put some overhead in your CPU so check it with caution.

The idea is to improve this code (I'm looking for less overhead) here in DevCentral and try to build a better base solution for the most common techniques. You can use the DNS Protocol Security, DNS Anti-DDoS and IP Intelligence features to get the most comprehensive solution.

Remember that there are a lot of DNS Tunneling utilities with a wide range of capabilities and options, so this is one of many forms to mitigate some of the attacks.

# DNS Tunnel Mitigation v1.1
#
#Esta iRule analiza cada consulta DNS, intentando identificar rastros comunes de un túnel vía el protocolo DNS.
#El mecanismo primario a utilizar son listas (Blancas y Negras).
#El mecanismo secundario es analizar la cantidad de consultas DNS idénticas desde una direccion IP específica hacia un dominio específico.
#por Pedro Haoa    
#    
#Evento inicial que establece variables globales estadísticas, para todas las consultas y conexiones cliente.
when RULE_INIT {
    set static::ataque 0
    set static::IP
    set static::key
    set static::query
}
when DNS_REQUEST {
    #Número máximo de consultas DNS idénticas
    set max_identical_queries 60
    set DomBlack [domain [DNS::question name] 2]
    set static::query $DomBlack
    set static::IP [IP::remote_addr]
    set static::key "$static::IP-$static::query"
    #log local2. "Consulta desde $static::IP"
if {[class match $DomBlack equals blacklist] }{
    #log local2. "Dominio $DomBlack bloqueado"
    DNS::drop
    return
} elseif {[table lookup $static::key] != ""} {
    #log local2.alert "Alerta Amarilla: Consultas identicas desde $static::IP."
    set count [table incr $static::key]
    #log local2.alert "El numero de consultas identicas desde $static::IP es $count"
if {$count > $max_identical_queries} {
    #log local2.alert "Alerta Roja: Demasiadas consultas identicas desde $static::IP"
    set static::ataque 1
    DNS::drop
    return
    }
} else {
    #Se crea una entrada en la tabla
    log local2.alert "Primera consulta desde $static::IP, $static::key"
    set static::key "$static::IP-$static::query"
    #Tabla para cada entrada IP-Dominio con expiracion para cada entrada en 60 segundos
    table set $static::key 1 indefinite 60
    }
}
1
Rate this Discussion
Comments on this Discussion
Comment made 31-May-2017 by bvberkel 27

Hi Pedro,

Nice post. I made some modifications to your script and tested it on 11.5.4, seems to be working. I did not have a look at the performance.

Kr, Bart

when RULE_INIT {
    set static::IP
    set static::key
    set static::query
    set static::lifetime
}
when DNS_REQUEST {
    set query_type [DNS::question type]
    # Check query type in datagroup and the length of the query may not be larger than 512.
    if { ([class match $query_type equals TunnelType]) and [DNS::len] > 512 } {
        # Set the maximum amount of queries to a domain withing the lifetime of the key.
        set max_identical_queries 10
        # Lifetime of the key is used to track if the domain has been queried again within the given timeframe.
        set lifetime_of_key 60
        # Set the queried domain. eg. google.com
        set queried_domain [domain [DNS::question name] 2]
        # Add everything to the global variables.
        set static::query $queried_domain
        set static::IP [IP::remote_addr]
        set static::key "$static::IP-$static::query"
        # Drop when domain is on the Blacklist.
        if { [class match $queried_domain equals Blacklist] } {
            log local2. "Alert: Domain $queried_domain blocked by Blacklist"
            DNS::drop
            DNS::return
        } elseif {[table lookup $static::key] != ""} {
            set count [table incr $static::key]
            if { $count > $max_identical_queries } {
                set static::lifetime [table lifetime -remaining $static::key]
                log local2.alert "Alert: Domain $static::query is queried more than $max_identical_queries times from $static::IP, so it will be dropped for another $static::lifetime seconds."
                DNS::drop
                DNS::return
            } else {
                log local2.alert "Alert: Domain $static::query queried $count times within $lifetime_of_key seconds from $static::IP."
            }
        } else {
            #log local2.alert "Alert: Domain $static::query queried from $static::IP."
            set static::key "$static::IP-$static::query"
            table set $static::key 1 indefinite $lifetime_of_key
        }
    }
}
ltm data-group internal Blacklist {
    records {
        google.com { }
    }
    type string
}
ltm data-group internal TunnelType {
    records {
        CNAME { }
        KEY { }
        TXT { }
    }
    type string
}
1
Comment made 31-May-2017 by Pedro Haoa

Hi,

Nice work Bart,

I'm gonna put the creation of Data Groups in the update 'cause it's a very important part of the solution.

DNS Tunnel Mitigation v2.0 it's better in terms of performance. White/Black lists help to put less overhead in the rule. Take your time to prepare some extended White/Black lists in order to improve your performance.

I hope this helps.

Pedro

0

Replies to this Discussion

placeholder+image

Hello Pedro,

First of all thank you so much for the iRule and the effort. There is NO other resource in Devcentral about this, although is one of the most requested feature for DNS (and i cannot request F5 PS irule for my lab).

I wanted to check with you, Were you able to test it in production?. I tried to use it in my lab but i could not fixed or check or solved one issue related to the table lookup function (When DNS request, first else if condition):

This is the issue
[undefined procedure: table][table lookup $static::key]
And this is the line:
} elseif {[table lookup $static::key] !=""} {

Any idea?. Thank you

0
Comments on this Reply
Comment made 18-May-2017 by Pedro Haoa

Hi Javier,

It should be:

elseif {[table lookup $static::key] != ""} ## Add a space after the operator !=

I rewrote this first attempt with a little more depured rule as a result.

I will publish my findings in an additional article, as soon as the availability of time allows me.

:-)

0
placeholder+image

DNS Tunnel Mitigation v2.0

BIG-IP AFM (Protocol Security)

In Security ›› Protocol Security : Security Profiles : DNS ››

Create a New Security Profile and exclude obsolete record types like MD, MF, MAILA, NULL, HINFO, SPF, etc. Then apply to your DNS profile associated with your Listener.

BIG-IP DNS (LTM Data Groups and iRule)

Creating DNS Tunnel Query type Data Group

create ltm data-group internal TunnelType records replace-all-with { CNAME { } } type string
modify ltm data-group internal TunnelType records add { TXT { } }
modify ltm data-group internal TunnelType records add { SRV { } }
modify ltm data-group internal TunnelType records add { KEY { } }

Creating Whitelist Data Group

create ltm data-group internal Dominios_Lista_Blanca records replace-all-with { facebook.com { data facebook.com } } type string
modify ltm data-group internal Dominios_Lista_Blanca records add { instagram.com { data instagram.com } }
modify ltm data-group internal Dominios_Lista_Blanca records add { fbcdn.net { data fbcdn.net } }
modify ltm data-group internal Dominios_Lista_Blanca records add { google.com { data google.com } }
modify ltm data-group internal Dominios_Lista_Blanca records add { googleapis.com { data googleapis.com } }

Creating Blacklist Data Group

create ltm data-group internal Dominios_Lista_Negra records replace-all-with { dnstunnel.de { data dnstunnel.de } } type string
modify ltm data-group internal Dominios_Lista_Negra records add { cutheatergroup.cn { data cutheatergroup.cn } }
modify ltm data-group internal Dominios_Lista_Negra records add { demodomain.cz { data demodomain.cz } }
modify ltm data-group internal Dominios_Lista_Negra records add { buo.cc { data buo.cc } }
modify ltm data-group internal Dominios_Lista_Negra records add { pdk.lcn.cc { data pdk.lcn.cc } }

iRule

when RULE_INIT {
    # Max DNS queries during detection period per source IP / destination domain
    set static::maxq 180
    # Detection & Blocking Period
    set static::btime 60
}
when DNS_REQUEST {
    set srcip [IP::remote_addr]
    set qtype [DNS::question type]
    set DomOrigen [domain [DNS::question name] 4]
    set key "$srcip:$DomOrigen"
if { ([class match $qtype equals TunnelType]) and [DNS::len] > 512 } {
    if {[class match $DomOrigen ends_with Dominios_Lista_Blanca] }{
        return
    } elseif {[class match $DomOrigen ends_with Dominios_Lista_Negra] }{
        DNS::drop
        return
    } elseif {[table lookup $key] ne ""} {
        set count [table incr $key]
        if {$count > $static::maxq} {
            DNS::drop
            return
        }
    } else {
        table add $key 1 indef $static::btime
        }
    }
}
0
Comments on this Reply
Comment made 01-Jun-2017 by bvberkel 27

Hi Pedro,

Good to put the black/whitelist more on top, saves cpu.

Some considerations:

  • domains like bbc.co.uk
  • length of the request
  • enforce extra testing on uncommon record types (eq. TXT, KEY)

Found a minor typo in your script, btime/ltime..

set static::btime 60

table add $key 1 indef $static::ltime

Cheers, Bart

0
Comment made 01-Jun-2017 by Pedro Haoa

Thanks Bart,

Update done.

0
Comment made 01-Jun-2017 by diego ricardo porez ramirez 3

this is a good solution ...thanks

1
placeholder+image

Hi,

Great post... and nice coincidence, I was just about to post question about state of BIG-IP in this area. I am dealing with other vendor solutions is this area and I am very curious how F5 solutions compare here.

Seems that DDoS could be at similar level but DNS leakage rather not. Solution I am looking at includes behavioral based protection, that looks like more mature and for sure implemented in code - no programming necessary.

I will appreciate a lot any know info about F5 plans in this area. F5 was dealing with DNS for long time so it's a bit strange they never really touched area of compromising DNS traffic for C&C communication and DNS leakage.

I wonder as well if Threat Intelligence offered by F5 is including know rogue DNS servers in their data feed, as well if they monitor creation of fake domains - if not it would be nice touch to do that - what do you think?

Thanks again for sharing your work.

Piotr

0
Comments on this Reply
Comment made 5 months ago by Pedro Haoa

Hi Piotr,

It's been a while. And F5 have good news in this subject since there is a wonderful tool that can automate the configuration process for DNS Tunnel and Data Exfiltration via iApps. If you need this type of service you can contact F5 Professional Services in order to deploy the solution.

0
Comment made 5 months ago by Piotr Lewandowski 1162

Hi,

Thanks for info. Am I wrong that those iApps will not be available via iApp downloads?

Piotr

0