Export GTM/DNS Configuration in CSV - tmsh cli script
Problem this snippet solves: This is a simple cli script used to collect all the WideIP, LB Method, Status, State, Pool Name, Pool LB, Pool Members, Pool Fall back, Last Resort pool info in CSV format. A sample output would be like below, One can customize the code to extract other fields available too. Check out my other codeshare of LTM report. Note: The codeshare may get multiple version, use the latest version alone. The reason to keep the other versions is for end users to understand & compare, thus helping them to modify to their own requirements. Hope it helps. How to use this snippet: Login to the GTM/DNS, create your script by running the below commands and paste the code provided in snippet, tmsh create cli script gtm-config-parser Delete the proc blocks, so it looks something like below, create script gtm-config-parser { ## PASTE THE CODE HERE ## } and paste the code provided in the snippet. Note: When you paste it, the indentation may be realigned, it shouldn't cause any errors, but the list output would show improperly aligned. Feel free to delete the tab spaces in the code snippet & paste it while creating, so indentation is aligned properly. And you can run the script like below, tmsh run cli script gtm-config-parser > /var/tmp/gtm-config-parser-output.csv And get the output from the saved file, open it on excel. Format it & use it for audit & reporting. cat /var/tmp/gtm-config-parser-output.csv Feel free to add more elements as per your requirements. For version 13.x & higher, there requires a small change in the code. Refer the comments section. Thanks to @azblaster Code : proc script::run {} { puts "WIP,LB-MODE,WIP-STATUS,WIP-STATE,POOL-NAME,POOL-LB,POOL-MEMBERS,POOL-FB,LASTRESORT-POOL" foreach { obj } [tmsh::get_config gtm wideip all-properties] { set wipname [tmsh::get_name $obj] set wippools [tmsh::get_field_value $obj pools] set lbmode [tmsh::get_field_value $obj "pool-lb-mode"] set lastresort [tmsh::get_field_value $obj "last-resort-pool"] foreach { status } [tmsh::get_status gtm wideip $wipname] { set wipstatus [tmsh::get_field_value $status "status.availability-state"] set wipstate [tmsh::get_field_value $status "status.enabled-state"] } foreach wippool $wippools { set pool_name [tmsh::get_name $wippool] set pool_configs [tmsh::get_config /gtm pool $pool_name all-properties] foreach pool_config $pool_configs { set pool_lb [tmsh::get_field_value $pool_config "load-balancing-mode"] set pool_fb [tmsh::get_field_value $pool_config "fallback-mode"] if { [catch { set member_name [tmsh::get_field_value $pool_config "members" ]} err] } { set pool_member $err } else { set pool_member "" set member_name [tmsh::get_field_value $pool_config "members"] foreach member $member_name { append pool_member "[lindex $member 1] " } } puts "$wipname,$lbmode,$wipstatus,$wipstate,$pool_name,$pool_lb,$pool_member,$pool_fb,$lastresort" } } } } Tested this on version: 11.63.5KViews2likes6CommentsImplementing Client Subnet DNS Requests
Problem this snippet solves: Update 2018-10-23: As of BIG-IP DNS 14.0 there is now a checkbox feature for edns-client-subnet. Please see: Using Client Subnet in DNS Requests. The following is still useful if you want to customize your responses. Original post: Using an iRule and edns-client-subnet (ECS) we can improve the accuracy of F5 GTM’s topology load balancing. DevCentral Article: Implementing Client Subnet DNS Requests How to use this snippet: There are two different iRules. One is an LTM iRule and the second is a GTM iRule. These should be deployed separately. Code : # # LTM iRule # # comply with draft to respond with ECS when DNS_REQUEST { if { [DNS::edns0 exists] &! [catch { DNS::edns0 subnet address }] } { set ecs_address [DNS::edns0 subnet address] set ecs_source [DNS::edns0 subnet source] set ecs_scope [DNS::edns0 subnet scope] log local0. "Received EDNS request from [IP::client_addr]:$ecs_address/$ecs_source/$ecs_scope" } } when DNS_RESPONSE { if { [info exists ecs_address] } { DNS::edns0 subnet address $ecs_address DNS::edns0 subnet source $ecs_source #DNS::edns0 subnet scope $ecs_scope # hardcode the desired scope to be /24, not sure this is OK DNS::edns0 subnet scope 24 } } # # GTM iRule # when DNS_REQUEST { set ldns [IP::client_addr] log local0. "LDNS LOC: $ldns [whereis $ldns]" if { [DNS::edns0 exists] &! [catch { DNS::edns0 subnet address }] } { set gtm_ecs_address [DNS::edns0 subnet address] set gtm_ecs_source [DNS::edns0 subnet source] set gtm_ecs_scope [DNS::edns0 subnet scope] set ldns $gtm_ecs_address log local0. "ECS LOC: $gtm_ecs_address [whereis $ldns]" } set loc [whereis $ldns] if { $loc contains "NA" } { log local0. "NA" } elseif { $loc contains "AS" } { log local0. "Asia" } elseif { $loc contains "EU" } { log local0. "Europe" } else { log local0. "All other" } } Tested this on version: 11.62.5KViews1like16CommentsDNS Tunnel Mitigation v2
Problem this snippet solves: (Solution from Pedro Haoa) 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. How to use this snippet: LTM + AFM + DNS Services 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 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 } } Code : 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 } } } Tested this on version: No Version Found2.3KViews2likes6CommentsExport GTM/DNS Virtual Servers Configuration in CSV - tmsh cli script
Problem this snippet solves: This is a simple cli script used to collect all the virtual-servers name, its destination created in a server or ltm server. A sample output would be like below, How to use this snippet: This is similar to my other share - https://devcentral.f5.com/s/articles/Export-GTM-DNS-Configuration-in-CSV-tmsh-cli-script Login to the GTM/DNS, create your script by running the below commands and paste the code provided in snippet, tmsh create cli script gtm-vs Delete the proc blocks, so it looks something like below, create script gtm-vs { ## PASTE THE CODE HERE ## } and paste the code provided in the snippet. Note: When you paste it, the indentation may be realigned, it shouldn't cause any errors, but the list output would show improperly aligned. Feel free to delete the tab spaces in the code snippet & paste it while creating, so indentation is aligned properly. And you can run the script like below, tmsh run cli script gtm-vs > /var/tmp/gtm-vs-output.csv And get the output from the saved file, open it on excel. Format it & use it for audit & reporting. cat /var/tmp/gtm-vs-output.csv Feel free to add more elements as per your requirements. Code : proc script::run {} { puts "Server,Virtual-Server,Destination" foreach { obj } [tmsh::get_config gtm server] { set server [tmsh::get_name $obj] foreach { vss } [tmsh::get_config gtm server $server virtual-servers] { set vs_set [tmsh::get_field_value $vss virtual-servers] foreach vs $vs_set { set vs_name [tmsh::get_name $vs] puts $server,$vs_name,[tmsh::get_field_value $vs destination] } } } } Tested this on version: 13.11.4KViews3likes2CommentsDNS Blackhole
Problem this snippet solves: The blackhole requirement is to intercept DNS requests for prohibited FQDNs, not sent those to BIND for recursive look-up, return a DNS response with an A record to an LTM virtual server, and have a LTM virtual server with a second iRule that will log the request and serve a static page. The solution uses an iRule to the listener virtual server. This virtual server processes all GTM/BIND traffic. Incoming requests are matched against an external data group that contains a list of prohibited FQDNs. This data group file can be edited directly in the GUI at System - File Management - Data Group File List (line terminator should be LF only, not CR-LF). Alternately, the file can be edited manually and re-loaded by doing a "tmsh load sys config verify" then "tmsh load sys config". The blackhole iRule will log all requests for prohibited FQDNs and return a DNS response that matches an LTM virtual server. The blackhole iRule only provides valid responses for A records, however all blackhole DNS requests are logged. How to use this snippet: Create the list of FQDNs for the BIG-IP external data group. Example format is below. File can be stored in /config/Blackhole_Class, although v11.1 provides a method to upload via GUI which is recommended. The second field is the reason why the site was added to the Blackhole class. ".3322.org" := "virus", ".3322.com" := "malware", ".3322.net" := "phishing", Make the external file accessible On Internal-GTM's GUI, go to System - File Management - Data Group File List - Import. File Name: upload Blackhole_Class file Name: Blackhole_Class File Contents: String Key / Value Pair Separator: := Create data group as external file: On Internal-GTM's GUI, go to Local Traffic - iRules - Data Group List - Create Name: Blackhole_Class Type: (External File) Path/Filename: Blackhole_Class File Contents: string Access Mode: Read Only Create the Blackhole iRule On Internal-GTM's GUI, go to Local Traffic - iRules - Create. Name: DNS_blackhole (can be renamed) iRule Source is attached below. Apply the Blackhole iRule to the GTM listener virtual server. Go to Local Traffic - Virtual Servers. Click on the Virtual Server created automatically for the GTM listener. Name will be of form: vs_10_1_1_152_53_gtm, where the first 4 numbers are the IP address of the Listener. Go to the resources tab and assign the DNS_Blackhole iRule created above. Create iFile for the Organization's Logo that will be used with the block page. Download a copy of the image to be used Rename file to corp-logo.gif (optional) Go to System - File Management - iFile List - Import Name: corp-logo.gif Go to Local Traffic - iRules - iFile List - Create Name: corp-logo.gif File name: Create iRule to log client requests and send an HTML page to notify customers they have violated the Blackhole. This iRule should be copied from the attached file. Go to Local Traffic - iRules - Create Name: DNS_blackhole_block_page iRule Source attached below. Create virtual server for client requests. The IP address should match the DNS response defined in ::blackhole_reply in the DNS_Blackhole iRule. Go to Local Traffic - Virtual Servers - Create Name: DNS_blackhole_block_page Destination: 10.1.1.80 (update per local requirements) Port: 80 HTTP profile: http iRules: DNS_blackhole_block_page Code : # DNS Blackhole # This iRule interrogates all queries that arrive on the GTM listener. If the query matches # a list of prohibited FQDNs, a standardized response is given and the request is logged. # This response IP address could be a honeypot server or an LTM virtual server. # Blackhole functionality can be used to prevent malware, virus C2 servers, adware, or other sites. # # Author: Hugh O'Donnell, F5 Consulting # # Usage: # 1) apply to GTM listener virtual server that is defined at Local Traffic - Virtual Servers # 2) create a string data group called "Blackhole_Class". The FQDNs must start with a period. # 3) update the answer static variable with the IP address to return # # Known Issues: # 1) Only A and AAAA records are returned for blackhole requests. The response for other request # types will be logged and returned with no answer. # # Revision history: # 12-11-2011: Initial Revision when RULE_INIT { # Set IPV4 address that is returned for Blackhole matches for A records set static::blackhole_reply_IPV4 "10.1.1.26" # 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" } } } } # DNS Blackhole Block Page # # This iRule presents an HTML page to the user and logs details of the HTML request. # It is used in conjuction with the DNS Blackhole iRule to ensure users are aware that # their request was blocked by the Blackhole and actions to take if this block was in error. # # Author: Hugh O'Donnell, F5 Consulting # # Usage: # 1) Add the corporate logo that will be displayed to System - File Management - iFile List # 2) Make the iFile accessible to be used in this iRule by giving associating the iFile name corp_logo_gif # with the iFile at: Local Traffic - iRules - iFile List. # 3) Ensure list of FQDNs in the DNS Blackhole is in a data group called "Blackhole_Class". This can be # verified at Local Traffic - iRules - Data Group List. # 4) Apply this iRule to the port 80 virtual server that the Blackhole iRule sends out, which is specified in variables # static::blackhole_reply_IPV4 and static::blackhole_reply_IPV6 in v11.1+ version of Blackhole iRule 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.gif" } { # Present HTTP::respond 200 content $static::corp_logo_gif } 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_gif [ifile get "/Common/corp-logo.gif"] # Beginning of the block page set static::block_page " Web Access Denied - Enterprise Network Operations Center <!-- .mainbody { background-color: #C0C0C0; color: #000000; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0px; padding: 20px 0px 20px 0px; position: relative; text-align: center; width: 100%; } .bdywrpr { width:996px; height:auto; text-align:left; margin:0 auto; z-index:1; position: relative; } #banner-wrapper { width: 950px; padding: 0px; margin: 0px; overflow:hidden; background-color: #000033; background-repeat: no-repeat; } #banner-image { float: left; margin-left: auto; margin-right: auto; padding: 3px 0px 2px 7px; width: 950px; } #textbody { background-color: #FFFFFF; color: #000000; font-family: Verdana, Geneva, sans-serif; font-size: 13px; width: 950px; padding:0px; text-align:justify; margin: 0px; } --> 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. " }1.4KViews0likes1CommentDisable DNS Express to allow recursion of a delegated sub-domain
Problem this snippet solves: If you are using GTM to act both a authoritative slave with DNS Express and as a recursive cache, recursion will not work if a request is made for a delegated sub-domain if the parent domain exists in DNS Express. i.e. domain.com exists in DNS Express but has delegated the dev.domain.com sub-domain to a different set of name server. Any request to dev.domain.com will just get a referral rather than being recursed. This is because of the order of operations in GTM, https://support.f5.com/kb/en-us/solutions/public/14000/500/sol14510.html. Recursion is the very last process that could happen and since DNS Express makes an authoritative referral response no recursion will occur. How to use this snippet: To use this your listener and corresponding DNS profile need to have DNS Express configured and recursion enabled(cache). Then the iRule just needs to be attached to the listener. Code : when DNS_REQUEST { #query DNS Express to look for a sub-domain delegation set rrr [DNS::query dnsx [DNS::question name] [DNS::question type]] #evaluate if the queried zone is defined in DNS Express #empty response indicates DNS Express does not have the requested domain #so we should exit and continue to recursion if {$rrr equals "{} {} {}"}{return} #check if DNS Express response is a delegated sub-domain referral if { [lindex $rrr 0] equals "" && [DNS::type [lindex [lindex $rrr 1] 0]] equals "NS"} { #no ANSWER was returned AND AUTHORITY is an NS record(not a SOA) #this is a referral so we should disble DNS Express to allow for the subdomain to be recursed DNS::disable dnsx } } Tested this on version: 11.61.3KViews0likes6CommentsDNS Tunneling Protection
Problem this snippet solves: This snippet helps blocking DNS tunneling that may be observed in modern enterprise networks. There is a Data Group List that allows you to specify DNS domain names that are known to be used for DNS tunneling and you do not want to receive email alerts for them. There is one known DNS domain used for tunneling - *.mac.sophosxl.net. We saw DNS tunnels from MacBooks with Sophos Antivirus installed. How to use this snippet: Just add this iRule to your Virtual Server (VS) that serves as DNS for your clients. This VS must have an DNS profile attached, so you need a BIG-IP DNS license. Do not forget to add Data Group List, like this ltm data-group internal DGL-DNS-TUNNEL { records { mac.sophosxl.net { } } type string } If you need to configure email alerts add this code to /config/user_alert.conf: alert SECPOL_DNS_TUNNEL "Detected DNS tunneling for (.*)" { snmptrap OID=".1.3.6.1.4.1.3375.2.4.0.302"; email toaddress="$ALERT_ADDRESS" fromaddress="$ADC_ADDRESS" body="Security Policy: Detected DNS tunneling" } Replace $ALERT_ADDRESS and $ADC_ADDRESS with appropriate email addresses that are valid in your environment Code : when DNS_REQUEST { if {[string length [DNS::question name]] > 231} { if {[class match [DNS::question name] ends_with DGL-DNS-TUNNEL]} { log local0. "Detected possible DNS tunneling for [IP::remote_addr]. Request [DNS::question name] dropped" } else { log local0. "Detected DNS tunneling for [IP::remote_addr]. Request [DNS::question name] dropped" } DNS::drop } } Tested this on version: 13.01.2KViews0likes3CommentsBIG-IP DNS Forwarder Support via iRule
Problem this snippet solves: The BIG-IP DNS Product does not currently (without named) support DNS forwarders. Some customers wish to avoid exposing named but want forwarder support. How to use this snippet: Apply this iRule to your BIG-IP DNS Listener and configure a datagroup Code : when DNS_REQUEST { set forwarded 0 if {[class match [DNS::question name] ends_with forwarded_zones]}{ set count [table incr [class match -element [DNS::question name] ends_with forwarded_zones]] log "Count for [class match -element [DNS::question name] ends_with forwarded_zones]]: $count" DNS::disable dns-express cache bind gtm set forwarders [class match -value [DNS::question name] ends_with forwarded_zones] log "Query question: [DNS::question name] Type: [DNS::question type] - Forwarders: $forwarders" set forwarder_list [split $forwarders] set forwarder [lindex $forwarder_list [expr $count % [llength $forwarder_list]]] log "Forwarder: $forwarder" translate address enable snat automap node $forwarder } } Tested this on version: 13.01.2KViews0likes4CommentsCustom DNS Service health monitoring for GTM and LTM
Problem this snippet solves: This EAV monitoring is created for the purpose of custom GTM/LTM DNS health monitor. You will either use the custom health monitor to monitor your LTM pool members or GTM servers/pool members, or if you have preferred DNS servers to monitor, specify DNS servers within the monitor settings. This custom monitoring is specifically created for v11.6.1. It may or may not work for other versions. Feel free to test it out. How to use this snippet: As described in the coding comments, save this code into a text file and import it into your GTM/LTM. Create an external type monitor and enter the values written in the coding. Assign the monitor to the pool or server like what you normally do to assign a typical monitor. Do note that you can monitor EITHER the pool member / server OR specify your own DNS servers to monitor. Not both. Max allowed DNS server to monitor is 2. If you would like to deploy this monitor on GTM, I suggest that you go thru K8154 first. Code : #!/bin/sh # # Author: Darren Neo # This EAV script is created for the purpose of custom GTM/LTM DNS health monitor. # In this script, you will either use the custom health monitor to monitor your LTM pool members or GTM servers/pool members, # or if you have preferred DNS servers to monitor, specify DNS servers within the monitor settings. # This script is specifically created for v11.6.1. It may or may not work for other versions. Feel free to test it out. # # To use this, import this script to the GTM/LTM: System ›› File Management : External Monitor Program File List # Create custom external monitor on the GTM/LTM. # Monitor settings: # Type: External # External Program: select this imported script # Interval: 10 seconds (LTM), 30 seconds (GTM) # Timeout: 31 seconds (LTM), 120 seconds (GTM) # Arguments: any name to be looked up. e.g. www.f5.com # Variables (optional): DNS1, DNS2 - (specify DNS servers instead of using IP address from $1) # For GTM, create the following: data centers, prober pool, server, pool witth pool member. # - add the newly created custom external monitor to the previously created server, pool or pool member. # For LTM, create the following: pool with pool member # - add the newly created custom external monitor to pool or pool member. # # $1 and $2 arguments will be supplied automatically for all external monitors, $3 will be the argument from the monitor that calls this script: # $1 = IP (nnn.nnn.nnn.nnn notation or hostname) # $2 = port (decimal, host byte order) -- not used in this monitor, assumes default port 53 # $3 = name to be looked up # $DNS1 = variable from the monitor settings # $DNS2 = variable from the monitor settings node_ip=`echo $1 | sed 's/::ffff://'` pidfile="/var/run/`basename $0`.$node_ip..$2.pid" if [ -f $pidfile ] then kill -9 `cat $pidfile` > /dev/null 2>&1 fi # echo "EAV `basename $0`: IP - $1, DNS1 - $DNS1, DNS2 - $DNS2, Lookup - $3" | logger -p local0.debug echo "$$" > $pidfile # if DNS1 and DNS2 servers are not supplied, we will use the $1 IP address that was automatically supplied from the system # if DNS1 and DNS2 servers are supplied, we will use DNS1 and DNS2 instead of $1 if [ not $DNS1 ] && [ not $DNS2 ] then ip=`dig +time=2 +tries=2 +short @$node_ip $3 IN A` fi if [ $DNS1 ] then dns1_result=`dig +time=2 +tries=2 +short @$DNS1 $3 IN A` fi if [ $DNS2 ] then dns2_result=`dig +time=2 +tries=2 +short @$DNS2 $3 IN A` fi # echo "Using system IP address: A-Record received: $ip" | logger -p local0.debug # echo "Using system DNS1 address: A-Record received: $dns1_result" | logger -p local0.debug # echo "Using system DNS2 address: A-Record received: $dns2_result" | logger -p local0.debug # verify if A-record is valid IP address. if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || [[ $dns1_result =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || [[ $dns2_result =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] then # echo "UP" | logger -p local0.debug # Complete any cleanup activity before sending result to STDOUT as the script is stopped then. rm -f $pidfile echo "UP" else # echo "DOWN" | logger -p local0.debug rm -f $pidfile fi Tested this on version: 11.61.1KViews0likes0CommentsGTM return LDNS IP to client
Problem this snippet solves: We do a lot of our load balancing based on topology rules, so it's often very useful to know where the DNS request is actually coming from rather than just the client's IP and the DNS servers they have configured. Especially if they're behind an ADSL router doing NAT or some other similar set up. This rule simply returns the IP address of the LDNS that eventually made the query to the GTM device in the response to a lookup for the WideIP using the rule, as well as logging the response and perceived location. Code : rule "DNS_debug" partition "Common" { when DNS_REQUEST { host [IP::client_addr] log local0.err "Debug address : [IP::client_addr] [whereis [IP::client_addr]]" } }799Views1like2Comments