LTM DNS Blackhole

Problem this snippet solves:

DNS Black Hole from LTM with DNS Services

Code :

Author:  Hugh O'Donnell, F5 Consulting
when RULE_INIT {
Set IPV4 address that is returned for Blackhole matches for A records
set static::blackhole_reply_IPV4 "10.10.20.50"
Set IPV6 address that is returned for Blackhole matches for AAAA records
set static::blackhole_reply_IPV6 "2001:19b8:101:2::f5f5:1d"
Set TTL used for all Blackhole replies
set static::blackhole_ttl "300"


when DNS_REQUEST {
#debugging statement see all questions and request details
   # log -noname local0. "Client: [IP::client_addr] Question:[DNS::question name] Type:[DNS::question type] Class:[DNS::question class] Origin:[DNS::origin]"
 
     # Blackhole_Match is used to track when a Query matches the blackhole list
     # Ensure it is always set to 0 or false at beginning of the DNS request
     set Blackhole_Match 0
 
     # Blackhole_Type is used to track why this FQDN was added to the Blackhole_Class
     set Blackhole_Type ""
 
     # When the FQDN from the DNS Query is checked against the Blackhole class, the FQDN must start with a
     # period.  This ensures we match a FQDN and all names to the left of it.  This prevents against
     # malware that dynamically prepends characters to the domain name in order to bypass exact matches
     if {!([DNS::question name] == ".")} {
         set fqdn_name .[DNS::question name]
     }
 
     if { [class match $fqdn_name ends_with Blackhole_Class] } {
         # Client made a DNS request for a Blackhole site.
         set Blackhole_Match 1
         set Blackhole_Type [class match -value $fqdn_name ends_with Blackhole_Class ]
 
         # Prevent processing by GTM, DNS Express, BIND and GTM Listener's pool. 
         # Want to ensure we don't request a prohibited site and allow their server to identify or track the GTM source IP.
         DNS::return
     }    
 }
 
 when DNS_RESPONSE {
     # debugging statement to see all questions and request details
     # log -noname local0. "Request: $fqdn_name Answer: [DNS::answer] Origin:[DNS::origin] Status: [DNS::header rcode] Flags: RD [DNS::header rd] RA [DNS::header ra]"
 
     if { $Blackhole_Match } {
         # This DNS request was for a Blackhole FQDN. Take different actions based on the request type.
         switch [DNS::question type] {
             "A"     {
                     # Clear out any DNS responses and insert the custom response.  RA header = recursive answer
                     DNS::answer clear
                     DNS::answer insert "[DNS::question name]. $static::blackhole_ttl [DNS::question class] [DNS::question type] $static::blackhole_reply_IPV4"
                     DNS::header ra "1"
 
                     # log example:  Apr  3 14:54:23 local/tmm info tmm[4694]:
                     #     Blackhole: 10.1.1.148#4902 requested foo.com query type: A class IN A-response: 10.1.1.60
                     log -noname local0. "Blackhole: [IP::client_addr]#[UDP::client_port] requested [DNS::question name] query type: [DNS::question type] class [DNS::question class] A-response: $static::blackhole_reply_IPV4 BH type: $Blackhole_Type"
                     }
             "AAAA"     {
                     # Clear out any DNS responses and insert the custom response.  RA header = recursive answer
                     DNS::answer clear
                     DNS::answer insert "[DNS::question name]. $static::blackhole_ttl [DNS::question class] [DNS::question type] $static::blackhole_reply_IPV6"
                     DNS::header ra "1"
 
                     # log example:  Apr  3 14:54:23 local/tmm info tmm[4694]:
                     #     Blackhole: 10.1.1.148#4902 requested foo.com query type: A class IN AAAA-response: 2001:19b8:101:2::f5f5:1d
                     log -noname local0. "Blackhole: [IP::client_addr]#[UDP::client_port] requested [DNS::question name] query type: [DNS::question type] class [DNS::question class] AAAA-response: $static::blackhole_reply_IPV6 BH type: $Blackhole_Type"
                     }
             default {
                     # For other record types, e.g. MX, NS, TXT, etc, provide a blank NOERROR response
                     DNS::last_act reject
 
                     # log example:  Apr  3 14:54:23 local/tmm info tmm[4694]:
                     #     Blackhole: 10.1.1.148#4902 requested foo.com query type: A class IN unable to respond
                     log -noname local0. "Blackhole: [IP::client_addr]#[UDP::client_port] requested [DNS::question name] query type: [DNS::question type] class [DNS::question class] unable to respond  BH type: $Blackhole_Type"
                     }
         }
     }
 }
 
######----RESPONSE PAGE IRULE----------
 # Author: Hugh O.Donnell, F5 Consulting
 
 when HTTP_REQUEST {
 
     # the static HTML pages include the logo that is referenced in HTML as corp-logo.gif
     # intercept requests for this and reply with the image that is stored in an iFile defined in RULE_INIT below
     if {[HTTP::uri] ends_with "/_maintenance-page/corp-logo.png" } {
         # Present
        HTTP::respond 200 content $static::corp_logo
 
     } else {
         # Request for Blackhole webpage.  Identify what type of block was in place
         switch -glob [class match -value ".]HTTP::host[" ends_with Blackhole_Class ] {
                 "virus"     { set block_reason "Virus site" }
                 "phishing"     { set block_reason "Phishing site" }
                 "generic"     { set block_reason "Unacceptable Usage" }
                 default     { set block_reason "Denied Per Policy - Other Sites" }
         }
 
         # Log details about the blackhole request to the remote syslog server
         log -noname local0. "Blackhole: From [IP::client_addr]:[TCP::client_port] \
           to [IP::local_addr]:[TCP::local_port], [HTTP::request_num], \
           [HTTP::method],[HTTP::uri],[HTTP::version], [HTTP::host],  [HTTP::header value Referer], \
           [HTTP::header User-Agent], [HTTP::header names],[HTTP::cookie names], BH category: $block_reason,"
 
         # Send an HTML page to the user.  The page is defined in the RULE_INIT event below
         HTTP::respond 200 content "$static::block_page [HTTP::host][HTTP::uri] $static::after_url $block_reason $static::after_block_reason "
     }   
 }
 
 
 when RULE_INIT {
     # load the logo that was stored as an iFile
     set static::corp_logo [ifile get "/Common/f5ball"]
 
     # Beginning of the block page
     set static::block_page "
         
         
         Web Access Denied - Enterprise Network Operations Center
         
         
         
         
         
         
         
         
\"Enterprise

Access has been denied. URL: " set static::after_url "

Your request was denied because it is blacklisted in DNS. Blacklist category: " set static::after_block_reason "

The Internet Gateways are for official use only. Misuse violates policy. If you believe that this site is categorized incorrectly, and that you have a valid business reason for access to this site please contact your manager for approval and the Enterprise Network Operations Center via E-mail: enoc@example.com Please use the Web Access Request Form and include a business justification.   Only e-mail that originates from valid internal e-mail addresses will be processed. If you do not have a valid e-mail address, your manager will need to submit a request on your behalf.

Generated by bigip1.f5.com.

" }
Published Mar 17, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment