Forum Discussion

JamesS_40157's avatar
Icon for Nimbostratus rankNimbostratus
Oct 19, 2011

irule for logging DNS queries to the load balancer?

Hi all,



Before I get into what seems like an easy question and obvious answer, first a bit of background!




We are about to refresh our current production load balancers (running v 9.4.4) to brand new hardware (8950s) running v11. The current load balancers were put in to production way before anyone in the current operations team joined the company, and therefore unfortunately have lots of bad/dodgy config on them, including lots of (we suspect) old DNS entries that are no longer used or required.




Instead of just blanket migrating all the DNS entries across, we'd like to make an informed decision onto what should go to v11. Most of the DNS entries are configured in zonerunner as far as I can tell.




I'd like to point out before I go on that while i believe i have a pretty good understanding of LTM, my knowledge of GTM is practically zero! We also know for a fact (after having consultants in) that our GTM is set up completely wrong, as if we want to disable wide IPs we have to go into each individual load balancer and disable them separately...anyway...




What we'd like to do is log DNS queries when they come in, in order to determine what ones are still being requested. We are quite a highly visited site however and have a TTL on some of our main domains of just 30 seconds, therefore just adding a logging section to named.conf could end up tipping the load balancer over due to the sheer amount of logging it would suddenly create.






We know about 80% of our DNS entries are in active use - therefore I decided to create an irule on GTM that will log DNS entries for only those that we are unsure of, ie we are excluding those DNS entries that we are 100% sure are still in use. Here it is:










if { not ([DNS::rrname] equals $::knowndns) } {


log local0. "DNSQUERY [DNS::rrname] TYPE [DNS::rrtype]"















Pretty simple yeh? Unfortunately I can't work out how to apply this to GTM! As far as I can tell irules can only be applied to wide IPs, however DNS responds on the listener address. Is it possible to somehow set up a dummy wide ip with the listener IP address in order to log all DNS queries coming in? As I say, most (if not all) DNS entries are in zonerunner, so i'm unsure if this is even possible. I'd really appreciate any help on this matter!




Thanks in advance




7 Replies

  • Hi James,



    The GTM / 3-DNS / Zonerunner is just a modified version of BIND. I'm running 10.2.x on my GTM and you can verify by running "named -v"



    named -v


    BIND 9.6.1-P3



    So rather than adding an iRule to log all of the entries that are queried, you could modify your named.conf (/var/named/config/named.conf) to add logging.



    Something like this:



    logging {


    channel logfile {


    syslog daemon;


    severity error;


    print-category yes;


    print-severity yes;


    print-time yes;




    channel query_log {


    file "/var/log/query.log" versions 7 size 250m ;


    severity dynamic;


    print-time yes;


    print-category yes;


    print-severity yes;





    NOTE: I would highly recommend bouncing this concept off of F5 Support, but this should work.



    Hope this helps.
  • Hi Michael,



    Many thanks for the reply - you've confirmed my suspicions that I'd have to modify named.conf to include a logging section. Unfortunately I am very wary of doing this on our production load balancers due to the sheer number of queries they handle per second, i can imagine the logs filling up within minutes.



    I think what i may do in this case is set up a mirror port on the external interface of the load balancer and simply snoop for DNS traffic - it's ugly and will require some analysis to get the data out, but it'll work and it won't affect the load balancer performance. Thanks for the replies guys!
  • Hi James,



    If you are only worried about Disk Space Issues, that is part of a BIND Config and can be changed at will.



    file "/var/log/query.log" versions 7 size 250m ;



    file "/var/log/query.log" = File location and file name. You can change any of this to a location on the Big-IP that has lots of space.


    version 7 = Keep a total of 7 files (6 Archived / previous and 1 Active)


    size 250m = Each log file size should reach 250 meg, then roll the log file and create a new one.



    These options allow you to plan how much HDD Space your Query Logs will take, and how much history you want to keep.



    Some of my DNS Servers take almost 2 million queries per day and they only roll the logs maybe once every 2 or so days.



    Hope this helps.
  • Hi Michael,



    Adding the configuration above to named.conf generates an error in daemon.log to the effect "logging channel 'query_log' file '/var/log/query.log': permission denied".



    Creating the empty log files and changing the ownership and permissions of the logfiles fails to resolve the error - even after setting the access mode to world-writable. Any ideas?
  • I wrote this iRule to send query/response logs to remote syslog server, improvement suggestions highly appreciated:

        set hsl [HSL::open -proto UDP -pool loggers]
        set vip [string trimright [IP::local_addr] :]
        set vip [IP::local_addr]
        set client_ip [IP::remote_addr]
    when DNS_RESPONSE {
        set logline ""
        set answer ""
        set rrs [DNS::answer]
        set num_answers [llength $rrs]
        for {set i 1} {$i<=[llength $rrs]} {incr i} {
            set rr [lindex $rrs [expr {$i-1}]]
            append answer "a_name_" $i "=" [DNS::name $rr] " "
            append answer "a_ttl_" $i "=" [DNS::ttl $rr] " "
            append answer "a_class_" $i "=" [DNS::class $rr] " "
            append answer "a_type_" $i "=" [DNS::type $rr] " "
            append answer "a_data_" $i "=" [DNS::rdata $rr] " "     
        set additional ""
        set rrs [DNS::additional]
        set num_answers_add [llength $rrs]
        for {set i 1} {$i<=[llength $rrs]} {incr i} {
            set rr [lindex $rrs [expr {$i-1}]]
            append additional "ad_name_" $i "=" [DNS::name $rr] " "
            append additional "ad_ttl_" $i "=" [DNS::ttl $rr] " "
            append additional "ad_class_" $i "=" [DNS::class $rr] " "
            append additional "ad_type_" $i "=" [DNS::type $rr] " "
            append additional "ad_data_" $i "=" [DNS::rdata $rr] " "     
        set authority ""
        set rrs [DNS::authority]
        set num_answers_auth [llength $rrs]
        for {set i 1} {$i<=[llength $rrs]} {incr i} {
            set rr [lindex $rrs [expr {$i-1}]]
            append authority "auth_name_" $i "=" [DNS::name $rr] " "
            append authority "auth_ttl_" $i "=" [DNS::ttl $rr] " "
            append authority "auth_class_" $i "=" [DNS::class $rr] " "
            append authority "auth_type_" $i "=" [DNS::type $rr] " "
            append authority "auth_data_" $i "=" [DNS::rdata $rr] " "     
        append logline "<190> vip=$vip client=$client_ip" " "
        append logline "q_name=[DNS::question name] q_type=[DNS::question type] q_class=[DNS::question class]" " "
        append logline "num_answers=$num_answers num_answers_add=$num_answers_add num_answers_auth=$num_answers_auth" " "
        append logline "$answer $additional $authority"
        HSL::send $hsl $logline