iRules
20597 TopicsTrigger js challenge/Captcha for ip reputation/ip intelligence categories
Problem solved by this Code Snippet Because some ISP or cloud providers do not monitor their users a lot of times client ip addresses are marked as "spam sources" or "windows exploits" and as the ip addresses are dynamic and after time a legitimate user can use this ip addresses the categories are often stopped in the IP intelligence profile or under the ASM/AWAF policy. To still make use of this categories the users coming from those ip addresses can be forced to solve captcha checks or at least to be checked for javascript support! How to use this Code Snippet Have AWAF/ASM and ip intelligence licensed Add AWAF/ASM policy with irule support option (by default not enabled under the policy) or/and Bot profile under the Virtual server Optionally add IP intelligence profile or enable the Ip intelligence under the WAF policy without the categories that cause a lot of false positives, Add the irule and if needed modify the categories for which it triggers Do not forget to first create the data group, used in the code or delete that part of the code and to uncomment the Bot part of the code, if you plan to do js check and not captcha and maybe comment the captcha part ! Code Snippet Meta Information Version: 17.1.3 Coding Language: TCL Code You can find the code and further documentation in my GitHub repository: reputation-javascript-captcha-challlenge/ at main · Nikoolayy1/reputation-javascript-captcha-challlenge when HTTP_REQUEST { # Take the ip address for ip reputation/intelligence check from the XFF header if it comes from the whitelisted source ip addresses in data group "client_ip_class" if { [HTTP::header exists "X-Forwarded-For"] && [class match [IP::client_addr] equals "/Common/client_ip_class"] } { set trueIP [HTTP::header "X-Forwarded-For"] } else { set trueIP [IP::client_addr] } # Check if IP reputation is triggered and it is containing "Spam Sources" if { ([llength [IP::reputation $trueIP]] != 0) && ([IP::reputation $trueIP] contains "Spam Sources") }{ log local0. "The category is [IP::reputation $trueIP] from [IP::client_addr]" # Set the variable 1 or bulean true as to trigger ASM captcha or bot defense javascript set js_ch 1 } else { set js_ch 0 } # Custom response page just for testing if there is no real backend origin server for testing if {!$js_ch} { HTTP::respond 200 content { <html> <head> <title>Apology Page</title> </head> <body> We are sorry, but the site you are looking for is temporarily out of service<br> If you feel you have reached this page in error, please try again. </body> </html> } } } # when BOTDEFENSE_ACTION { # Trigger bot defense action javascript check for Spam Sources # if {$js_ch && (not ([BOTDEFENSE::reason] starts_with "passed browser challenge")) && ([BOTDEFENSE::action] eq "allow") }{ # BOTDEFENSE::action browser_challenge # } # } when ASM_REQUEST_DONE { # Trigger ASM captcha check only for users comming from Spam sources that have not already passed the captcha check (don't have the captcha cookie) if {$js_ch && [ASM::captcha_status] ne "correct"} { set res [ASM::captcha] if {$res ne "ok"} { log local0. "Cannot send captcha_challenge: \"$res\"" } } } Extra References: BOTDEFENSE::action ASM::captcha ASM::captcha_status51Views1like1CommentWhich runs first iRULE or PolicyLTM(With ASM being applied)
Hello all Its well known by the K16590 that LTMPolicies will run before the irules using the same event, for example HTTP_REQUEST in an irule and "at request time" in LTMPolicy. But regardless the order, if the LTM Policy says to enable ASM policy the BIG-IP would still return and process the irule or the traffic would be sent to ASM policy for process leaving the irule whitout a match/process ? In my understanding the LTM Policy would be read first, after that the irule and then the traffic sent to ASM Policy. But i'm not having my irule redirects occuring. In this case of configuration: when HTTP_REQUEST { if {[HTTP::uri] starts_with "/region1/abc"} { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif {[HTTP::uri] starts_with "/region2/abc"} { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif {[HTTP::uri] starts_with "/region3/abc"} { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } elseif {[HTTP::uri] starts_with "/region4/abc"} { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] } else { # do nothing } } ltm policy LTM_POLICY_ASM_MYSITE { controls { asm } requires { http } rules { MYSITE { actions { 0 { asm enable policy /Common/ASM_MYSITEWAFPOLICY } } conditions { 0 { http-host values { www.mysiteexample.com.br mysiteexample.com.br } } } } default { actions { 0 { asm enable policy /Common/ASM_MYSITEWAFPOLICY_MISC } } conditions { 0 { http-uri contains values { miscelaneous } } } ordinal 1 } no_asm { actions { 0 { asm disable } } ordinal 2 } } status published strategy first-match }34Views0likes2CommentsCan i use shared objects as I do data groups, in iRules?
I need to write a few iRules for policy NATing and using Shared Objects, would make the task (and iRules) cleaner and less complex. For instance: when CLIENT_ACCEPTED { if {[matchclass[IP::remote_addr]] equals "international-sites_netgrp"} { pool "infoblox-report" # log local0 } } Where international-sites_netgrp is a shared object address list that contains 2 other address lists which are /16 networks. DaveSolved38Views0likes4CommentsPossible to combine multiple DataGroupLists for IP-Check?
Hello F5 Community, I am working on an irule to check on two datagroup-lists and country, but I am not sure if this is possible like I want to implement this. It should check if the IP is in the list1 or list2 or its part of FR and US and if true it should allow the traffic otherwise it should be dropped. My questions would be is it possible to check against two datagroup lists, like i did in the my irule example. Or should avoid this? when HTTP_REQUEST { set client_ip [getfield [IP::client_addr] "%" 1] set from_country [whereis $client_ip country] if { not (([class match $client_ip equals /Common/list1]) || ([class match $client_ip equals /Common/list2]) || ($from_country eq "FR") || ($from_country eq "US"))} { drop } switch -glob -- [string tolower [HTTP::path]] { default { pool /Common/pool1 } } } Thank you.3Views0likes0Commentsremove www from domain
Hello Everyone, Could you please assist for below query how it will be achieved. We have a query where the customer wants to remove the www from the request. for example requested comes to https://www.abc.com and they want to remove www and forward to only abc.com. i would like to know if this is applicable using local traffic policy and irules. if possible kindly share the example irule or local traffic policy example to achieve this. Please note: there are some policies configured with https://www.abc.com/etc and being redirected to https://www.abc.com/xyz . will there be any impact on these redirections rules if we remove the www? if yes then do we need to modify all these policies to abc.com and remove www from the redirection statements.? TIA.32Views0likes1CommentHey DeepSeek, can you write iRules?
Back in time... Two years ago I asked ChatGPT whether it could write iRules. My conclusion after giving several tasks to ChatGPT was, that it can help with simple tasks but it cannot write intermediate or complex iRules. A new AI enters the competition Two weeks ago DeepSeek entered the scene and thought it's a good idea to ask it about its capabilities to write iRules. Spoiler alert: It cannot. New AI, same challenges I asked DeepSeek the same questions I asked ChatGPT 2 years ago. Write me an iRule that redirects HTTP to HTTPS Can you write an iRule that rewrites the host header in HTTP Request and Response? Can you write an iRule that will make a loadbalancing decision based on the HTTP Host header? Can you write an iRule that will make a loadbalancing decision based on the HTTP URI header? Write me an iRule that shows different ASM blocking pages based on the host header. The response should include the support ID. I stopped DeepSeek asking after the 5th question, DeepSeek is clueless about iRules. The answer I got from DeepSeek to 1, 2, 4 and 5 was always the same: when HTTP_REQUEST { # Check if the request is coming to port 80 (HTTP) if { [TCP::local_port] equals 80 } { # Construct the HTTPS URL set host [HTTP::host] set uri [HTTP::uri] set redirect_url "https://${host}${uri}" # Perform the redirect HTTP::redirect $redirect_url } } While this is a solution to task 1, it is plain wrong for 2, 3, 4 and 5. And even for the first challenge this is not a good. Actually it hurts me reading this iRule... Here for example task 2, just wrong... For task 3 DeepSeeks answer was: ChatGPT in 2025 For completeness, I gave the same tasks from 2023 to ChatGPT again. Briefly said - ChatGPT was OK in solving tasks 1-4 in 2023 and still is. It improved it's solution for task 5, the ASM iRule challenge. In 2023 I had two more tasks related to rewriting and redirecting. ChatGPT still failed to provide a solid solution for those two tasks. Conclusion DeepSeek cannot write iRules and ChatGPT still isn't good at it. Write your own iRules or ask the friendly people here on devcentral to help you.296Views5likes4CommentsHow to add missing Content-Length header to an HTTP POST request?
Have tried to send an APM HTTP Auth POST request to external authentication server which requires Content-Length header. Seems to be that APM HTTP Auth does not calculate and add the Content-Length header when sending a custom POST. The POST content is small json data but its size varies. HTTP Auth sends the POST to a layered VS which converts the request to https, so can use iRules there. Tried to use HTTP::collect and then calculate the size from collected HTTP::payload and do HTTP::release. However it gets stuck.. Would be nice to be able to do it at the Layered VS. Alternatively thinking of using an iRule agent event in the VPE to form the json POST data and calculate the size into session variables prior the HTTP Auth box in the VPE and using them in the HTTP Auth custom POST definition. Any advice?279Views0likes1CommentHow to add missing Content-Length header to an HTTP POST request?
Have tried to send an APM HTTP Auth POST request to external authentication server which requires Content-Length header. Seems to be that APM HTTP Auth does not calculate and add the Content-Length header when sending a custom POST. The POST content is small json data but its size varies. HTTP Auth sends the POST to a layered VS which converts the request to https, so can use iRules there. Tried to use HTTP::collect and then calculate the size from collected HTTP::payload and do HTTP::release. However it gets stuck.. Would be nice to be able to do it at the Layered VS. Alternatively thinking of using an iRule agent event in the VPE to form the json POST data and calculate the size into session variables prior the HTTP Auth box in the VPE and using them in the HTTP Auth custom POST definition. Any advice?1.5KViews0likes3CommentsI rules for persistency
HI Guys I have a client who want to do distribution of client session on /20 (4096 ip treated as one for server assignment) but he realized that in this way the persistency (set at 960 sec = 16 minutes) never expires. Since there is a limit of 35K sessions, the side effects is "session starvation". So he would like to have distribution on /20 BUT having more granular persistency based on client IP. /32 so one record for each ip. Now my concern is the amount of records in the persistency table. could this be a problem ? how many records can an F5 manage until have CPU/Line card issues ? I already verified alternative methods to do persistency like cookies, but this doesn't apply because the communication is encrypted from client device to server with a TLS tunnel so i can't inject anything. this is the script. could it work of could i have usage issues ? the model is BIG-IP 17.1.1.3 Build 0.0.5 Point Release 3 the script is the following: thank you for your help B.R Mario when CLIENT_ACCEPTED { # Persistence over IP persist uie [IP::client_addr] # Load balacing on subnet /20 set client_ip [IP::client_addr] set subnet_ip [IP::addr $client_ip mask 255.255.240.0] # Get active pool member list set active_members [active_members -list pool <pool_name>] # If there are active members, pick one based on the hash of the masked IP if {[llength $active_members] > 0} { set member [lindex $active_members [expr {[crc32 $subnet_ip] % [llength $active_members]}]] pool <pool_name> member $member } }25Views0likes0Comments