dns
23 TopicsExport 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.7KViews2likes6CommentsDNS 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.5KViews0likes1CommentExport 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 Request and Response Filtering using URL DB and IPI subscriptions
Problem this snippet solves: This iRule solution is applied to a DNS resolver or a catch all (0.0.0.0/0:53) DNS virtual server where the BIG-IP is a default gateway. It allows the BIG-IP to explicitly or transparently intercept all DNS Requests and Responses from the client and apply security filtering controls. This solution is suited to almost any outbound DNS scenario where you need to protect the client from accessing malicious threats or undesirable content intentionally or unintentionally. One example where you may find this solution handy, is on a Guest or BYOD network where you need a transparent method of adding security when you don’t have control of the client. How to use this snippet: DNS Interception: Protecting the Client Code : # Author: Brett Smith @f5.com # # This iRule is applied to a DNS resolver (DNS Profile required) or a catch all (0.0.0.0/0:53) DNS virtual server where the BIG-IP is a default GW. # # Configurable Parameters for DNS_REQUEST filtering: # 1. DNS Request Filtering On or Off - Enable or Disable all DNS_REQUEST filtering. # 2. URL Categories e.g. Adult_Content, Hacking. If the DNS Question (FQDN - e.g. playboy.com) matches a category in the data group (default: dns_request_url_categories_dg), # NXDOMAIN will be returned in the response. To obtain a list of possible URL Categories and their descriptions, run: tmsh list sys url-db url-category { description } # 3. DNS Question Type e.g. A, AAAA, ANY etc. Only the Question Types configured in the data group (default: dns_request_question_type_dg) will be filtered. # 4. FQDN/TLD Whitelist e.g. f5.com or .gov. Any FQDN/Domain in the whitelist data group will bypass DNS_REQUEST filtering regardless of the Question Type or URL Category. # # Configurable Parameters for DNS_RESPONSE filtering: # 1. DNS Response Filtering On or Off - Enable or Disable all DNS_RESPONSE filtering. # 2. IP/Subnet Whitelist e.g 192.168.0.0/16 or 1.1.1.1. Any IP or IP Subnet in the whitelist data group will bypass DNS_RESPONSE filtering. # 3. IPI Threat Categories e.g. Spam Sources, Phishing. If the DNS RDATA (A & AAAA only) matches a category in the data group, NXDOMAIN will be returned in the response. # # Global Parameters # 1. Logging Control - Off, Level 1 (NXDOMAIN and Whitelist Matching) and Level 2 (All DNS Requests & Responses) when RULE_INIT { # DNS Request filtering - URL DB control. # 0 = DNS Request filter off, 1 = DNS Request filter on. set static::dns_request_filter 1 # URL categories data group. Any categories (Bot_Networks, etc) in this DG will be blocked based on the DNS question name. set static::dns_request_url_categories_dg "dns_request_url_categories_dg" # DNS request questions type data group. Question types (A,AAAA,etc) in the DNS request that match the DG will be sent for URL category filtering. set static::dns_request_question_type_dg "dns_request_question_type_dg" # FQDN whitelist data group. Any FQDN/Domain in this DG will bypass DNS request URL category filtering. set static::dns_request_fqdn_whitelist_dg "dns_request_fqdn_whitelist_dg" # DNS Response filtering - IP intelligence (reputation) control. # 0 = DNS Response filter off, 1 = DNS Response filter on. set static::dns_response_filter 1 # IP address whitelist data group. Any IP or IP Subnet in this DG will bypass DNS response filtering regardless of the IP intelligence (reputation) value. # If a AAAA record is contained in the Resource Record (RR), it is also returned in the DNS response. set static::dns_response_ip4_whitelist_dg "dns_response_ip_whitelist_dg" # IP intelligence categories data group. If the DNS RDATA (A & AAAA only) matches a category in the data group, NXDOMAIN will be returned in the response. set static::dns_response_ipi_categories_dg "dns_response_ipi_categories_dg" # Debug logging control. # 0 = logging off, 1 = informational logging, 2 = debug logging set static::debug_dns 2 } when DNS_REQUEST { if { $static::debug_dns >= 2 } { log local0. "Client IP: [IP::client_addr], Question: [DNS::question name], Type: [DNS::question type]" } # If DNS Request filtering is enabled, filter the request. if { $static::dns_request_filter } { # If the Question Name (eg. f5.com) is in the Whitelist, bypass URL filtering. if { ![class match [DNS::question name] ends_with $static::dns_request_fqdn_whitelist_dg] } { # If the Question Type matches, filter the request. if { [class match [DNS::question type] equals $static::dns_request_question_type_dg] } { # Determine the URL Category for the Question Name. set url_category [lindex [CATEGORY::lookup http://[DNS::question name]] 0] # If the URL Category is matched, return NXDOMAIN to the client. if { [class match $url_category ends_with $static::dns_request_url_categories_dg] } { # URL Category matched - Log. if { $static::debug_dns >= 1 } { log local0. "Client IP: [IP::client_addr], Question: [DNS::question name], Type: [DNS::question type], URL Category: $url_category - Respond with NXDOMAIN" } # Return NXDOMAIN to the client. DNS::answer clear DNS::header opcode QUERY DNS::header rcode NXDOMAIN DNS::return } } } else { # FQDN/TLD Whitelist matched - Log. if { $static::debug_dns >= 1 } { log local0. "Client IP: [IP::client_addr], Question: [DNS::question name], Type: [DNS::question type], FQDN/TLD Whitelist: Match Found - Bypass Request Filtering" } } } } when DNS_RESPONSE { # If Response Filter is enabled, filter the response. if { $static::dns_response_filter } { set threat_categories "" if { [DNS::ptype] eq "ANSWER" } { # Loop through each Resource Record(s). foreach rr [DNS::answer] { switch [DNS::type $rr] { "A" { # If the IP is not in the whitelist, filter the response. if { ![class match [DNS::rdata $rr] equals $static::dns_response_ip4_whitelist_dg] } { set threat_categories [IP::reputation [DNS::rdata $rr]] # If a Threat Category is returned and matches, filter the request. if { [class match $threat_categories contains $static::dns_response_ipi_categories_dg] } { # Threat Category matched - Log. if { $static::debug_dns >= 1 } { log local0. "Client IP: [IP::client_addr], Question: [DNS::question name], Type: A, Threat Category: $threat_categories - Respond with NXDOMAIN" } # Return NXDOMAIN to the client. DNS::answer clear DNS::header opcode QUERY DNS::header rcode NXDOMAIN } } else { # IP Whitelist matched - Log. if { $static::debug_dns >= 1 } { log local0. "Client IP: [IP::client_addr], Question: [DNS::question name], Type: [DNS::question type], IP Whitelist: Match Found - Bypass Response Filtering" } } } "AAAA" { # As IP::reputation doesn't support IPv6, use the Threat Category response from the A record. i.e. If the A record is bad assume the AAAA record is also bad. if { [class match $threat_categories contains $static::dns_response_ipi_categories_dg] } { # Threat Category matched - Log. if { $static::debug_dns >= 1 } { log local0. "Client IP: [IP::client_addr], Question: [DNS::question name], Type: AAAA, Threat Category: $threat_categories - Respond with NXDOMAIN" } # Return NXDOMAIN to the client. DNS::answer clear DNS::header opcode QUERY DNS::header rcode NXDOMAIN } } } } } } # Log the DNS response if { $static::debug_dns >= 2 } { log local0. "Client IP: [IP::client_addr], Answer: [DNS::answer], RCODE: [DNS::header rcode]" } } #Data Groups: create ltm data-group internal dns_request_url_categories_dg type string modify ltm data-group internal dns_request_url_categories_dg records add {"Adult_Content"} modify ltm data-group internal dns_request_url_categories_dg records add {"Advanced_Malware_Command_and_Control"} modify ltm data-group internal dns_request_url_categories_dg records add {"Advanced_Malware_Payloads"} modify ltm data-group internal dns_request_url_categories_dg records add {"Bot_Networks"} modify ltm data-group internal dns_request_url_categories_dg records add {"Compromised_Websites"} modify ltm data-group internal dns_request_url_categories_dg records add {"Elevated_Exposure"} modify ltm data-group internal dns_request_url_categories_dg records add {"Emerging_Exploits"} modify ltm data-group internal dns_request_url_categories_dg records add {"Files_Containing_Passwords"} modify ltm data-group internal dns_request_url_categories_dg records add {"Hacking"} modify ltm data-group internal dns_request_url_categories_dg records add {"Keyloggers"} modify ltm data-group internal dns_request_url_categories_dg records add {"Malicious_Embedded_Link"} modify ltm data-group internal dns_request_url_categories_dg records add {"Malicious_Embedded_iFrame"} modify ltm data-group internal dns_request_url_categories_dg records add {"Malicious_Web_Sites"} modify ltm data-group internal dns_request_url_categories_dg records add {"Militancy_and_Extremist"} modify ltm data-group internal dns_request_url_categories_dg records add {"Mobile_Malware"} modify ltm data-group internal dns_request_url_categories_dg records add {"Newly_Registered_Websites"} modify ltm data-group internal dns_request_url_categories_dg records add {"Nudity"} modify ltm data-group internal dns_request_url_categories_dg records add {"Peer-to-Peer_File_Sharing"} modify ltm data-group internal dns_request_url_categories_dg records add {"Phishing_and_Other_Frauds"} modify ltm data-group internal dns_request_url_categories_dg records add {"Proxy_Avoidance"} modify ltm data-group internal dns_request_url_categories_dg records add {"Sex"} modify ltm data-group internal dns_request_url_categories_dg records add {"Spyware"} modify ltm data-group internal dns_request_url_categories_dg records add {"Tasteless"} modify ltm data-group internal dns_request_url_categories_dg records add {"Web_and_Email_Spam"} create ltm data-group internal dns_request_question_type_dg type string modify ltm data-group internal dns_request_question_type_dg records add {"A"} modify ltm data-group internal dns_request_question_type_dg records add {"AAAA"} modify ltm data-group internal dns_request_question_type_dg records add {"ANY"} modify ltm data-group internal dns_request_question_type_dg records add {"CNAME"} modify ltm data-group internal dns_request_question_type_dg records add {"MX"} create ltm data-group internal dns_request_fqdn_whitelist_dg type string modify ltm data-group internal dns_request_fqdn_whitelist_dg records add {"f5.com"} create ltm data-group internal dns_response_ip_whitelist_dg type ip modify ltm data-group internal dns_response_ip_whitelist_dg records add {"10.0.0.0/8"} modify ltm data-group internal dns_response_ip_whitelist_dg records add {"172.16.0.0/12"} modify ltm data-group internal dns_response_ip_whitelist_dg records add {"192.168.0.0/16"} create ltm data-group internal dns_response_ipi_categories_dg type string modify ltm data-group internal dns_response_ipi_categories_dg records add {"BotNets"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Networks"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Denial of Service"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Illegal"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Infected Sources"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Phishing"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Proxy"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Scanners"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Spam Sources"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Web Attacks"} modify ltm data-group internal dns_response_ipi_categories_dg records add {"Windows Exploits"} Tested this on version: 11.5999Views1like2CommentsGTM Translation
Problem this snippet solves: When GTM responds with the IP address of the virtual server, there are different NAT translations that must be performed depending on where the request is coming from. This iRule looks at 4 classes (DataGroups) to determine which (If any) of the NAT translations it must perform on the response. This iRule differs from the pinhole example by only examining the response and the 'client' IP address. The hostname requested is ignored so there is only 1 event that needs to fire. Note that although developed for GTM, this is an LTM iRule and is attached to the LTM VS that is created by the GTM when you configure a listener address How to use this snippet: These data-groups are required but MAY be empty if no translations are necessary. local_address_class (type: address) - Holds a list of networks and their type (string internal or 3dp) gte_translate_3dp (type: address) - Translations for 3dp networks gte_translate_internet (type: address) - Translations for the internet gte_translate_internal (type: address) - Translations for internal addresses Code : timing on # gte_translate_external # # Hamish Marson (hamish@travellingkiwi.com) 2011 # # When GTM responds with the IP address of the virtual server, there are different NAT translations that # must be performed depending on where the request is coming from. This iRule looks at 4 classes (DataGroups) # to determine which (If any) of the NAT translations it must perform on the response. # # CLASS Type Description # local_address_class Address - Holds a list of networks and their type. Type is a string internal or 3dp # gte_translate_3dp Address - Translations for 3dp networks # gte_translate_internet Address - Translations for The Internet # gte_translate_internal Address - Translations for Internal addresses # # The translation dataGroups MUST exist. But MAY be empty if no translations are requirted (e.g. For Internal) # # Extensions... Current.y hardcoded for 3 types of address (internal, 3dp or (default) internet. This could be # extended by building the translation class name from the value returned from local_address_class. However extra # error checking would also be required to take into account mis-configuration of the local_address_class dataGroup # to make non-existant dataGroup names. # when DNS_RESPONSE { set GTE_CLASS_INTERNET "gte_translate_internet" set GTE_CLASS_INTERNAL "gte_translate_internal" set GTE_CLASS_3DP "gte_translate_3dp" set LOCAL_CLASS_ADDRESS "local_address_class" set gteHSL [HSL::open -proto UDP -pool hsl-log-01] set gteLogPrefix "<190>[virtual]:gte_translate_external:[IP::client_addr]:0:" # Grab the answer from GTM set rrs [DNS::answer] #HSL::send $gteHSL "$gteLogPrefix: checking DNS::answers" foreach rr $rrs { #HSL::send $gteHSL "$gteLogPrefix: checking RR type ==> [DNS::type $rr]" # Lookup the IP address returned in the GTE_CLASS if { [DNS::type $rr] == "A" } { set dstip [DNS::rdata $rr] #HSL::send $gteHSL "$gteLogPrefix: checking A data ==> [DNS::rdata $rr] ($dstip)" set gteAddClass [class match -value [IP::client_addr] equals $LOCAL_CLASS_ADDRESS ] switch -exact $gteAddClass { internal { set transIP [class match -value $dstip equals $GTE_CLASS_INTERNAL] } 3dp { set transIP [class match -value $dstip equals $GTE_CLASS_3DP] } default { set transIP [class match -value $dstip equals $GTE_CLASS_INTERNET] } } if { $transIP ne "" } { HSL::send $gteHSL "$gteLogPrefix: translate ($gteAddClass) $dstip => $transIP" DNS::rdata $rr $transIP return } else { HSL::send $gteHSL "$gteLogPrefix: no match for ($gteAddClass) $dstip" return } } } }722Views0likes6CommentsGTM Selective Persistence
Problem this snippet solves: GTM has the ability to persist client requests to a virtual (or real) server for a configurable duration. This persistence is set at the Wide IP level, and is a yes/no proposition. There is no configuration option to selectively set persistence. GTM hasn't yet implemented a persist command like the one that is available in LTM iRules either. But as usual, there is another way to solve the problem with F5 gear, courtesy of your friendly neighborhood F5 Support Team! Utilizing iRules to inspect the source of the request, you can use the cname command to redirect selected queries from a persistence-enabled WideIP to a Wide IP defined on the GTM where persistence is not configured. To configure this scenario, define two Wide IP's, one with persistence and one without. Apply the iRule below to the persistence enabled Wide IP. The iRule checks for known source addresses for which persistence is not required and sends a CNAME redirect to a Wide IP with no persistence. How to use this snippet: iRule Source: GTM Selective Persistence rule "SelectivePersist-rule" { when DNS_REQUEST { if { [IP::addr [IP::client_addr] equals 10.1.0.0/16] \ or [IP::addr [IP::client_addr] equals 10.2.0.0/16] } { cname "myService-noPersist.gtm.example.com" } } } GTM doesn’t yet support class lists, but when it does, you’ll be able to create a class lookup instead of nested elseif’s for longer lists of addresses. In the meantime, as an alternative, you could use regions and the matchregion command to avoid multiple IP::addr executions. Code : # Wide IP Definitions # Wide IP with Persistence and iRule wideip { name "myService.gtm.example.com" persist yes persist_ttl 1800 pool_lbmode rr pool "myPool" rule "SelectivePersist-rule" } # Wide IP with No Persistence wideip { name "myService-noPersist.gtm.example.com" pool_lbmode rr pool "myPool" }711Views0likes0CommentsBIG-IP DNS Express - Private Zone Blocker
Problem this snippet solves: With BIG-IP DNS; you cannot enable/disable configured DNS Express Zones on a per-listener basis. This makes scenarios where a single BIG-IP DNS system has listeners exposed to internal networks with RFC1918 addresses and public Internet networks. DNS Express doesn't support DNS Views, in short. This iRule allows you to configure a datagroup containing "disabled_zones" and the iRule will validate if the query matches a zone listed in disabled_zones. If it gets a match, it simply returns nothing. Additionally, the iRule examines all responses and checks that resource records in the response do not contain RFC1918 addresses and if it finds them, it removes those Resource Records. All code in the "DNS_RESPONSE" event can be commented or deleted if this behavior isn't desired. How to use this snippet: enable iRule on DNS listener (most likely a listener available only to private network clients) and configure "disabled_zones" data group as shown in example. Log lines can be deleted or commented out once proper operation of the rule is confirmed and understood or retained for purposes of auditing queries that are dropped/blocked. Code : when DNS_REQUEST { log "Got request from: [IP::remote_addr] for [DNS::question name]" if {[class match [DNS::question name] ends_with disabled_zones]}{ log "Query for [DNS::question name] is for a disabled zone - Dropping" DNS::return } } when DNS_RESPONSE { log "Got Response = [DNS::answer]" set rrs [DNS::answer] set privateresponse 0 foreach rr $rrs { log "DNS Response rr: $rr" if {[DNS::type $rr] == "A"}{ if {[class match [DNS::rdata $rr] equals private_net]}{ set privateresponse 1 DNS::answer remove $rr } log "DNS RR data: [DNS::rdata $rr]" } } if {$privateresponse}{ log "DNS response contains private addresses" } } Tested this on version: 13.0499Views0likes1CommentLTM 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 <!-- .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: #FFFFFF; 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. " }459Views0likes0CommentsDNS Flood Protection v3
Problem this snippet solves: This iRule may provide basic idea to protect against dns flood protection per source ip address. The "maxquery" is number of query allowed per second. The "holdtime" is the period that bad client will be blocked. Different in this version of the rule is the use of the static namespace for the variables in the RULE_INIT to prevent demotion, and the use of the table command to make the rule cleaner and simpler. DNS Flood Protection V3.1, which adds the ability to limit amount of memory used by blacklist and tracking table, is also available. Code : when RULE_INIT { set static::maxquery 100 set static::holdtime 600 } when CLIENT_DATA { set srcip [IP::remote_addr] # If there is a match, drop the request and exit the event if { [table lookup -subtable "blacklist" $srcip] != "" } { drop return } # set key to the sourceIP and current time set curtime [clock second] set key "count:$srcip:$curtime" # Keep a count of the entries in the table for this IP in the current second (ie 12 set count [table incr $key] # Time significance is 1s, so expire any entries after 2s (fudge factor) to conserve memory table lifetime $key 2 if { $count > $static::maxquery } { # Add IP to the blacklist and set the lifetime to the holdtime variable # so entry will automatically expire when desired. The lifetime is used # instead of the timeout because the first thing the iRule does is lookup # the IP in the blacklist table, which would keep the timeout from expiring # the blacklist entry. table add -subtable "blacklist" $srcip "blocked" indef $static::holdtime # Since IP is on blacklist now, the count doesn't matter. Delete to clean up. table delete $key drop return } }439Views0likes0CommentsDestination Snat Using DNS
Problem this snippet solves: This iRule, selects a snatpool based on which virtual called the iRule, and will select the member servers to use based on DNS resolution. Code : when RULE_INIT { # The hostname to resolve to an IP address set ::myhostname "resource.partner.com" # The number of requests to use the cached DNS answer for set ::max 100 # Force a DNS lookup on the first request to get a current answer set ::count 100 } when CLIENT_ACCEPTED { # Increment the count of requests incr ::count # Only look up the address every 100 resolutions # Modify this as needed by changing $::max in RULE_INIT if { $::count >= $::max } { set ::count 0 NAME::lookup $::myhostname } # Set the selected node to the current resolved IP address and the port the client requested. # The port could be hard coded to any value. node $::server_ip [TCP::local_port] # You might consider a switch statement or hash lookup # for more flexibility or performance if { [IP::addr [IP::local_addr] equals 10.0.0.35] } { snatpool partner_snat_a } else { snatpool partner_snat_b } } when NAME_RESOLVED { log local0. "NAME_RESOLVED: [NAME::response]" # can we just use [NAME::response 0], is the response a list? set ::server_ip [lindex [split [NAME::response] " "] 0] }421Views0likes0Comments