For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Block requests by reverse DNS record

Problem this snippet solves:

This iRule performs a reverse DNS lookup on the client IP address and blocks any which don't match a specific top level domain. This specific example sends an HTTP response. But you could also send a TCP reset using reject.

Note that due to a bug ( BZ 340659 ) with RESOLV::lookup's handling of PTR records, we use the older NAME::lookup command. See the RESOLV::lookup wiki page for details on the issue.

Code :

when CLIENT_ACCEPTED {
 
   # Trigger a name lookup for new connections
   set do_lookup 1
   log local0. "[IP::client_addr]:[TCP::client_port]: New connection to [IP::local_addr]:[TCP::local_port]"
}
when HTTP_REQUEST {
 
   # Check if we haven't done a lookup already on this connection
   if { $do_lookup }{
      log local0. "[IP::client_addr]:[TCP::client_port]: Collecting HTTP for new lookup"
 
      # Hold HTTP data until client IP address is resolved
      HTTP::collect
 
      #  Start a name resolution on the client IP address
      NAME::lookup -ptr [IP::client_addr]
   }
}
 
when NAME_RESOLVED {
 
   # FQDN of client IP address
   set ptr [string tolower [NAME::response]]
 
   log local0. "[IP::client_addr]:[TCP::client_port]: Lookup result: $ptr"
 
   # Check if ptr record ends with .mil
   if { $ptr ends_with ".mil" } {
 
      # Release HTTP data for .mil addresses and track that we've done a lookup for this connection
      log local0. "[IP::client_addr]:[TCP::client_port]: Valid ptr, releasing HTTP"
      set do_lookup 0
      HTTP::release
 
   } else {
 
      # PTR record does not end with ".mil", reject the connection
      log local0. "[IP::client_addr]:[TCP::client_port]: Invalid PTR, blocking HTTP request."
      HTTP::respond 403 content "Invalid PTR!\r\n"
      TCP::close  
   }
}
Published Mar 16, 2015
Version 1.0

3 Comments

  • The bug ( BZ 340659 ) https://support.f5.com/kb/en-us/solutions/public/12000/300/sol12378.html was resolved in 10.2.2, so I am sharing an updated iRule to do this in 11.x ========================================================================== when RULE_INIT { Set debug to 0 for no logging Set debug to 1 to just log blocks Set debug to 2 to log blocks and valid requests set static::debug 1 Ensure this points to your Data Group set static::domain_blacklist_dg "domain_block_blacklist" Set IP for your DNS Server set static::my_dns 192.168.10.1 Set name of VS if using a local Virtual Server set static::my_dns my_dns_vs } when CLIENT_ACCEPTED { set do_lookup 1 set is_blocked 0 set full_domain "" set base_domain "" if { $static::debug > 1 } { log local0. "Connection Accepted from IP_Addr:[IP::remote_addr]" } } when HTTP_REQUEST { if { $static::debug > 1 } { log local0. "Processing Request from IP_Addr:[IP::remote_addr]" log local0. "Do Lookup: $do_lookup Is Blocked: $is_blocked" log local0. "My_DNS: $static::my_dns" } if { $do_lookup } { grab the client base domain reverse lookup of IP Address set full_domain [RESOLV::lookup @$static::my_dns inet -ptr [IP::remote_addr]] grab the base domain (top level plus subdomain) from full_domain set base_domain [join [lrange [split $full_domain .] end-1 end] .] set do_lookup 0 } if { $is_blocked } { if { $static::debug > 0 } { log local0. "IP_Addr:[IP::remote_addr] Reverse_Lookup:$base_domain blacklisted (Already Blocked)" log local0. "Full Domain: $full_domain" } send a TCP reset reject } else { if { [class match $base_domain contains $static::domain_blacklist_dg] } { if { $static::debug > 0 } { log local0. "IP_Addr:[IP::remote_addr] Reverse_Lookup:$base_domain blacklisted (Blocked)" log local0. "Full Domian: $full_domain" } set is_blocked 1 send a TCP reset reject } else { if { $static::debug > 1 } { log local0. "IP_Addr:[IP::remote_addr] Reverse_Lookup:$base_domain $full_domain Accepted" } } } } ==========================================================================
  • Thank you, John, this is exactly the snippet I needed to get the lookup to work

    For anyone else needing this snippet I've formatted it as code

    Not certain I've inserted all the new lines needed.

     

    when RULE_INIT { 
    #	Set debug to 0 for no logging 
    #	Set debug to 1 to just log blocks 
    #	Set debug to 2 to log blocks and valid requests 
     
    	set static::debug 1 
     
    	#Ensure this points to your Data Group 
    	set static::domain_blacklist_dg "domain_block_blacklist" 
     
    	#Set IP for your DNS Server 
    	set static::my_dns 192.168.10.1 
    	#Set name of VS if using a local Virtual Server 
    	#set static::my_dns my_dns_vs 
    } 
     
     
    when CLIENT_ACCEPTED { 
    	set do_lookup 1 
    	set is_blocked 0 
    	set full_domain "" 
    	set base_domain "" 
     
    	if { $static::debug > 1 } { log local0. "Connection Accepted from IP_Addr:[IP::remote_addr]" } 
    } 
     
     
    when HTTP_REQUEST { 
    	if { $static::debug > 1 } { 
    		log local0. "Processing Request from IP_Addr:[IP::remote_addr]" 
    		log local0. "Do Lookup: $do_lookup Is Blocked: $is_blocked" 
    		log local0. "My_DNS: $static::my_dns" 
    	} 
    	if { $do_lookup } { 
    		# grab the client base domain reverse lookup of IP Address 
    		set full_domain [RESOLV::lookup @$static::my_dns inet -ptr [IP::remote_addr]] 
    		
    		#grab the base domain (top level plus subdomain) from full_domain 
    		set base_domain [join [lrange [split $full_domain .] end-1 end] .] 
    		set do_lookup 0 
    	} 
     
    	if { $is_blocked } { 
    		if { $static::debug > 0 } { 
    			log local0. "IP_Addr:[IP::remote_addr] Reverse_Lookup:$base_domain blacklisted (Already Blocked)" 
    			log local0. "Full Domain: $full_domain" } send a TCP reset reject 
    		} else { 
    			if { [class match $base_domain contains $static::domain_blacklist_dg] } { 
    				if { $static::debug > 0 } { 
    					log local0. "IP_Addr:[IP::remote_addr] Reverse_Lookup:$base_domain blacklisted (Blocked)" 
    					log local0. "Full Domian: $full_domain" 
    				} 
    				set is_blocked 1 
    				
    				#send a TCP reset 
    				reject 
    			} else { 
    				if { $static::debug > 1 } { 
    					log local0. "IP_Addr:[IP::remote_addr] Reverse_Lookup:$base_domain $full_domain Accepted" 
    				} 
    			}
    		}
    } 

     

  • so does this will help me to check PTR as anti spam does?