20lines
40 Topics20 Lines or Less #2
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and I've got more examples for you that show just how powerful iRules can be in less than 21 lines. This week I'm still drawing from the CodeShare. My plan was to pull from the CodeShare for the first week or two until I'd depleted it of possible examples and then move on. For those of you that haven't checked how awesome the CodeShare is lately, let's just say it would take a lot more than two editions of 20LoL to burn through all of those awesome examples. As such, next week I'll be poking around in the forums for some examples and, who knows, maybe even writing some of my own. As always, send in your example code to become one of the famous to be featured here, and I'll make sure to get you posted. Weblogic JSessionID Persistence Here's a solution to a question that's been asked in the forums many a time. Dealing with JSessionID is nothing new, and something many people want to know how to do. Here you can do it in less than 20 lines. when HTTP_REQUEST { if { [HTTP::cookie exists "JSessionID"] } { persist uie [HTTP::cookie "JSessionID"] } else { set jsess [findstr [HTTP::uri] "JSessionID" 11 ";"] if { $jsess != "" } { persist uie $jsess } } } when HTTP_RESPONSE { if { [HTTP::cookie exists "JSessionID"] } { persist add uie [HTTP::cookie "JSessionID"] } } VPN Sorter For those of you that might run multiple VPN devices in your office, here's a great way to allow users to connect to a single IP address and be sent to the appropriate pool of servers based on the relevant IP/UDP info. Not using VPN? This looks like it'd be pretty easy to port to - well - pretty much anything else that you wanted to sort into multiple pools. when CLIENT_ACCEPTED { if {[IP::protocol] == 47 || [TCP::local_port] == 1723} { # GRE used by MS PPTP server, TCP control channel pool ms_pptp } elseif {[IP::protocol] == 50 || [IP::protocol] == 51 || [UDP::local_port] == 500} { # AH and ESP used by IPSec, IKE used by IPSec pool ipsec_pool } elseif {[IP::protocol] == 115} { pool l2tp_pool # L2TP Protocol server } } Validate String Characters in a Cookie So you're using cookies to store all that data that you're using for those awesome, powerful iRules, huh? You say you've also got a system with pretty stringent requirements that isn't very fault tolerant? Well, maybe you should think about validating the data that you're pulling in from those cookies, just to be sure you're not accepting any illegal characters. Here's an example in less than 20 lines. when RULE_INIT { set ::cookie_to_validate "my_cookie" set ::cookie_validation_debug 1 set ::allowed_chars_cookie_value {%[-a-zA-Z0-9_]} } when HTTP_REQUEST { if {[string length [HTTP::cookie value $::cookie_to_validate]]}{ if {[HTTP::cookie value $::cookie_to_validate] eq [scan [HTTP::cookie value $::cookie_to_validate] $::allowed_chars_cookie_value]}{ if {$::cookie_validation_debug} { log local0. "Received a request from [IP::client_addr] with legal cookie value: [HTTP::cookie value $::cookie_to_validate]"} } else { if {$::cookie_validation_debug}{ set len [string length [scan [HTTP::cookie value $::cookie_to_validate] $::allowed_chars_cookie_value]] log local0. "Received a request from [IP::client_addr] with illegal cookie value: [HTTP::cookie value $::cookie_to_validate], \ char: [string range [HTTP::cookie value $::cookie_to_validate] $len $len]"} } } } There you go, more examples of how great things truly can come in small packages. Next week: More iRules! #Colin1.3KViews0likes0Comments20 Lines or Less #3
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting complicated. We've got a couple of codeshare entries and an entry courtesy of Joe in the forums. I figure with all the ribbing he gives me for the 20LoL series it's only fair he contributes, knowingly or not. Then again it's in the true spirit of a programmer to steal ... err ... borrow code from all available sources to achieve your desired result. I wouldn't want to break tradition! Whether you're dealing with cookie ordering, path traversal or multi-comparisons, there's something here for you this week. Here's your weekly dose of 20LoL - my apologies for the distinct lack of kittehs this week. Reorder Http Cookies Whether your program is set to look for cookies in a certain order, or you're just a touch OCD and demand your cookies stay "clean" and organized, this iRule is for you. when HTTP_REQUEST { if { [HTTP::cookie exists "cookie-name"] } { set cookie_s [HTTP::cookie "cookie-name"] HTTP::cookie remove "cookie-name" set cookie_a [HTTP::header cookie] HTTP::header replace "cookie" "$cookie_a; WLSID=$cookie_s" }} Path Traversal Detection Path traversal is bad, mmkay? Path traversal is when someone tries to execute arbitrary commands on your system, and general act like bad users. Help stop them from getting access to system commands via your webserver with some simple iRules like this one. when RULE_INIT { set ::vDebug 1}when HTTP_REQUEST { if { [HTTP::query] matches_regex {^.*=(\.\.|/)[[A-Za-z0-9./]*]*.*$} } { if { $::vDebug } { log local0. "Triggered by IP [IP::client_addr] with URI [HTTP::uri]" } reject }} Multi-part Comparisons This forum post talks about doing a multi-part comparison to look for the first letter(s) of a URI and send users to different pools based on that information. This proved to be a little un-intuitive, but Joe came to the rescue with a great switch solution, even though hoolio's workable solution shouldn't be overlooked. Go-go glob matching ftw! when HTTP_REQUEST { # Parse the fist character in the path switch -glob [HTTP::path] { "/[a-cA-C]*" { pool test1 } "/[d-lD-L]*" { pool test2 } "/[m-rM-R]*" { pool test3 } "/[s-zS-Z]*" { pool test4 } default { # Requested URI was a leading forward slash only pool test5 } } }937Views0likes0Comments20 Lines or Less #4
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting complicated. Last week I was out on vacation, serenading the good people of Shelton, WA with some thick, groovy funk. As such, the 20LoL had to be put on hold You can consider this your special, super-elite, bonus edition of 20 Lines or Less though, since that sounds cooler. This edition is all about the forums. There are all sorts of awesome things going on in the forums every day.We're seeing a positively epic volume of posts these days from the rockin' community which, lucky for me, are ripe with all sorts of tasty iRule tidbits that fit into the 20LoL format just great. So here we are, this week's 20Lines or Less iRules, thanks to the forums and the awesome community behind them. Round robin redirect requests http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=23540&view=topic In this case the user needed to round robin select between a couple of different redirect statements to even out load on systems (presumably systems not behind the BIG-IP or in a pool). Here's a simple rule to get that handled, compliments of Joe. when RULE_INIT { set ::whichone 0 } when HTTP_REQUEST { switch $::whichone { 0 { HTTP::redirect "http://Server1/blah" set ::whichone 1 } default { HTTP::redirect "http://Server2/blah" set ::whichone 0 } } } Network based traffic routing http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=23714&view=topic Hoolio comes through in this 4.x to 9.x rule conversion thread, helping another member get where they need to go. Apparently where they needed to go was two different pools, based on which client network the connections were coming in from. Matchclass and IP matching to the rescue. when CLIENT_ACCEPTED { if { [matchclass [IP::remote_addr] equals $::my_networks_class] } { log local0. "[IP::client_addr]:[TCP::client_port] matched \$::my_networks_class: $::my_networks_class" pool Visionware_web28 } else { log local0. "[IP::client_addr]:[TCP::client_port] didn't match \$::my_networks_class: $::my_networks_class" pool Visionware_web27 } } URI Based URI rewriting http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=23691&view=topic In this thread I got to help out user stevehong by putting together an example that uses switch to determine when to rewrite the URI and when not, before passing the traffic to the default pool for the Virtual. Nothing fancy here, just a simple example of switch, URI replacement, and a little logging for flavor. when HTTP_REQUEST { switch [HTTP::uri] { "/app/DentegraPortal/TransEDI" - "/app/DeltaCarePortal/TransEDI" - "/app/B2BEnt/TransEDI" - "/app/B2BPMI/TransEDI" { log "Incoming uri - [HTTP::uri] being translated to /b2b/transportServlet/TransEDI" HTTP::uri "/b2b/transportServlet/TransEDI" } } } There you have it, another 20LoL in the books. What did we learn this time? Forums FTW. Hopefully you're finding these useful or at least interesting. If you are, be sure to pass them along to your friends, and maybe even let me know. And don't worry, no kittenz were harmed in the making of this post. #Colin725Views0likes0Comments20 Lines or Less #5
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting complicated. For the real 20LoL this week, we go back to pilfer the wonderful collection of raw brainpower that is the DevCentral forums. Digging through just a few forum posts gave me a couple of tasty little iRules to share with the class for this week. Not only is this stuff cool, easy to implement, and done in less than 21 lines of code, it's done by real world users that dig this stuff so much they share it with the rest of us. Now that's rockin'. So without further gilding the lily and with no more adieu, I give you this week's 20 Lines or Less, brought to you by the forums, where good brains come to get better, and kittahs everywhere enjoy their cheezeburgerz. HTTP to HTTPS redirects - in the Location header http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=23172&view=topic Ever have a need to ensure that all the redirects being sent by your servers were secure links? Well, if you've ever tried to offload SSL to your LTM with a system that has hard-coded links in it, you just might need to. Here's a great iRule that will help you dig through redirect responses and make sure they're pointing to those SSL pages in one easy shot. when HTTP_REQUEST { # Save the requested host header value for reference in the response set host [HTTP::host] } when HTTP_RESPONSE { # Check if this is a redirect (30x response status) if {[HTTP::is_redirect]}{ # Replace the http://host with https://host in the Location header HTTP::header replace Location [string map -nocase {http://$host https://$host} [HTTP::header value Location]] } } Multi-faceted selective compression http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=6745&view=topic Selective compression is nothing new in the world of the web. What is new is the ability to combine multiple pieces of data, and perform checks against different data points to decide whether or not compression should be turned on. Rather than just saying "Yes" or "no" based on a VIP or an incoming URI, why not check the URI, the extension, and the client's IP address? when HTTP_REQUEST { set nocompress 0 log local0. "comp enabled default " if {[matchclass [string tolower [HTTP::uri]] ends_with $::ok_extension] or [matchclass [string tolower [HTTP::uri]] contains $::compress_dir ] and not [matchclass [IP::remote_addr] equals $::no_compress_ip ] } { set nocompress 0 log local0. "setted 0 for ok_extension or compress_dir or ip [IP::remote_addr]" } elseif {[matchclass [string tolower [HTTP::uri]] ends_with $::no_extension] or [matchclass [string tolower [HTTP::uri]] contains $::no_compress_dir ] or [matchclass [IP::remote_addr] equals $::no_compress_ip ] } { set nocompress 1 log local0. "setted 1 for no_extension or no_compress_dir or your ip [IP::remote_addr]" } } Reversing a string without a reverse command http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=22344&view=topic Oh those pesky formatting requirements. In this example a member needed to reverse the order of a string, but couldn't make use of a simple command to do so, since it isn't included in the TCL version on LTM. Hoolio to the rescue, though, with some logic below that spins the data right round, round round. # Set a test cert string set client_cert_orig {CN=LN.FN.027060322604,OU=CONTRACTOR,OU=PKI,OU=PoP,O=T.Z. Corp,C=TZ} log local0. "\$client_cert_orig: $client_cert_orig" # Split the cert string into a list set client_cert_list [split $client_cert_orig ","] log local0. "\$client_cert_list: $client_cert_list" # Save the length of the list set i [llength $client_cert_list] # Reset the value of a new string to save the client cert set client_cert "" # Loop through the list while {$i > 0}{ # Append the current list item to the string with a forward slash as the delineator append client_cert /[lindex $client_cert_list [incr i -1]] log local0. "\$client_cert: $client_cert" } There you go, another 20LoL in the can, a few more examples ready for your perusal and re-structuring. Grab them, bend them to your whims, and use them for the greater good. Check in every week for more examples of the power of an iRule, in 20 Lines or Less. #Colin672Views0likes1Comment20 Lines or Less #6
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. Continuing to draw from the forums, this week's 20LoL is packed with user-contributed goodness. From massaging packets to avoid app-server maintenance, to setting up a customer persistence/re-selection mechanism, we've got it all. This week the iRules range from exactly 20 lines, down to a scant 7 lines of code. Don't be fooled though, even that tiny 7 lines is the framework for a solution that really packs a punch. This week marks the first time I made a modification to an iRule to get it in under the 20 line maximum. All I did was strip out some un-needed variables, things I would suggest to any user posting up an iRule anyway, so my conscious feels pretty clear. I think that's still fair game, don't you? Let me know and I'll go with the popular vote for next time. Anyway, hopefully you're still digging the series as much as I am. Let me know if you've got any questions, comments or suggestions and I'll get to them sharpish. Before the minute-rice gets over cooked, and before the throngs of ravenous kittayz are unleashed to force me to quit talking and just deliver the 20LoL, here's this week's 20 Lines or Less. 304 Status and Content Dropping http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=23747&view=topic iRules is all about application fluency, so when the need arose to help solve a problem that would otherwise have to be put into code on an otherwise stable application server, it was a natural choice to send iRules in to the rescue. By forcing RFC compliance into a situation where some rules were being ignored, we've kept the client system happy and chugging along with an action packed 20 line iRule. when HTTP_RESPONSE { if {[catch {HTTP::status} status] or $status == ""} { set status "-" HTTP::close } elseif {$status >= 400} { HTTP::close } elseif {$status == 304} { catch {unset hdrs} if [catch {HTTP::header names} headerNames] { lappend hdrs X-Error "noHeaderSent" } else { foreach hdr $headerNames { if { ! [catch "HTTP::header value $hdr" vals]} { lappend hdrs $hdr "$vals" } } } if [catch HTTP::respond 304 $hdrs err] { log local0. "RESPOND_304_ERROR: $ err" } } } Per-Service URI modification http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=23798&view=topic In this simple looking iRule slumbers the power to re-write a custom URI for every different service being offered by your site/portal/etc. No longer will your users need to remember those long winded URLs or keep lengthy bookmarks. Provide them simple to remember, easy to use, short URIs that get translated as necessary by this simple iRule. Note that once you pass 20 or 30 translations a class may be cleaner. when HTTP_REQUEST { switch -glob [string tolower [HTTP::uri] { "*service" { HTTP::uri "/myservice" } } } Disable Persistence + Reselect on LB Fail http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=23226&view=topic This awesome example of iRule foo allows the LTM to disable persistence and reselect a new member from an "outage pool" when the normal load balancing mechanism fails to assign a member from the default pool. I admit I had to massage this one a little to help get it in under the 20 Line max, but it's nothing I wouldn't normally recommend for a rule anyway, so I remain guilt-free. when HTTP_REQUEST { if { ([HTTP::cookie exists "JSESSIONID"]) and ([active_members [LB::server pool]] > 0) } { persist uie [HTTP::cookie "JSESSIONID"] } } when HTTP_RESPONSE { if { ([HTTP::cookie exists "JSESSIONID"]) and ([active_members [LB::server pool]] > 0) } { persist add uie [HTTP::cookie "JSESSIONID"] } } when LB_FAILED { if {[active_members [LB::server pool]] == 0 } { LB::detach LB::reselect pool "sorry" } } Five more days, three more iRules examples, one more edition of 20Lines or Less in the books. If any of you out there in user land want to see a solution to a problem, let me know. For that matter, if you just want to see if I can build a solution in less than 21 lines, toss up those suggestions too. Who knows, it could be fun. Thanks for reading, and hope to see you next week. #Colin614Views0likes0Comments20 Lines or Less #9
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. This week I've got a combination of entries from our awesome forum users, and a rule I wrote a while back to meet a certain need at the time. We're almost at 10 editions of the 20LoL, and I'm looking forward to many more. Hopefully you're still finding it interesting and useful. Shoot me a line and let me know what's good, what's bad, what can be better and what you want to hear about. In the meantime, here's this week's 20 Lines or Less Multi-Conditional Redirect http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=25219&view=topic Hoolio delivers this short and sweet iRules in the forums to show how you can use multiple pieces of data to decide when to perform a redirect. Not only does he make use of a normal string comparison, but also an IP::addr comparison against the client's IP address. So in one line you're getting two comparisons on two different pieces of data. This is a good example for someone looking to redirect only a small subset of people, based on multiple pieces of data. when HTTP_REQUEST { if { [string tolower [HTTP::path]] ends_with "/_grid/print/print_data.aspx" \ and (not ([IP::addr [IP::client_addr]/8 equals 10.0.0.0]))} { HTTP::redirect "http://google.com" } } Syslog Priority Rewriting This is a variation on some actual code I wrote a while back to translate the syslog priority numbers when needed. Depending on the different syslog configurations, these numbers may not line up. This can be a problem when you're trying to aggregate many syslog systems into one main log server. This iRule shows how you can catch these messages inline and modify them with whatever equation fits your environment. when CLIENT_DATA { set pri [regexp -inline {} [UDP::payload] ] set newPri [expr ( ($pri - (($pri / 6) * 8) ) ) ] regsub $pri [UDP::payload] $newPri newPayload UDP::payload replace 0 [UDP::payload length] $newPayload } Duplicate Cookie Definitions http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=25215&view=topic Going back to the forums, it seems that hoolio is at it again. In this cool example he shows a fellow community member how to check for and remove multiple Set-Cookie entries with the same name. This way they can ensure that there is only one cookie present, regardless of how many times different apps may have tried to set it. This one looks a little long, but remove the comments and some of the white space, and it's under 20 lines...I checked. when HTTP_RESPONSE { # Insert some test response headers HTTP::header insert Set-Cookie {SESSIONID=AAAAAAAA; domain=.domain.com; path=/path/1} HTTP::header insert Set-Cookie {keeper=don't delete; domain=.domain.com; path=/path/2} HTTP::header insert Set-Cookie {SESSIONID=BBBBBBBB; domain=.domain.com; path=/path/3} HTTP::header insert Set-Cookie {SESSIONID=CCCCCCCC; domain=.domain.com; path=/path/4} log local0. "Set-Cookie header values: [HTTP::header values Set-Cookie]" log local0. "First Set-Cookie header which starts with SESSIONID: \ [lsearch -glob -inline [HTTP::header values Set-Cookie] "SESSIONID*"]" log local0. "Last Set-Cookie header which starts with SESSIONID: \ [lsearch -glob -inline -start end [HTTP::header values Set-Cookie] "SESSIONID*"]" set set_cookie_header [lsearch -glob -inline -start end [HTTP::header values Set-Cookie] "SESSIONID*"] log local0. "\$set_cookie_header: $set_cookie_header" # Remove all SESSIONID cookies while {[HTTP::cookie exists SESSIONID]}{ HTTP::cookie remove SESSIONID } log local0. "Set-Cookie values: [HTTP::header values Set-Cookie]" # Re-insert the last SESSIONID Set-Cookie header HTTP::header insert Set-Cookie $set_cookie_header log local0. "SESSIONID cookie: [HTTP::cookie SESSIONID]" } There you have it, 3 more examples in under 60 lines of code. Keep checking back every week to see what cool things can be done in just a few keystrokes. Many thanks to the awesome community and the people posting these examples. You're truly making DC a great place to be. #Colin549Views0likes0Comments20 Lines or Less #7
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. This week we've got some more great examples from the community. I've had the chance to sit in with some fellow F5 iRulers the past couple of days and wow, is it ever inspiring to hear all the things they're doing/seeing with iRules, and the kind of stuff heading our way in the future. The 20 Lines or Less series is meant to show off the cool things you can do with just a simple iRule and that list just seems to go on forever. What's not to love about that? It seems more and more people are checking out the 20LoL each week, which is awesome, so keep on coming back to see what other cool things you can do with your iRule foo without breaking a sweat. Here's this weeks' dose: JSessionID Persistence http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&tpage=1&view=topic&postid=24165#24170 Like a childhood friend, this topic is one that I can always count on coming back to again and again. We laugh, we cry, we talk about "the way things were" ... it's beautiful, really. Honestly though, JSessionID persistence is a very common theme that repeats itself in the forums time and time again. The truth of the matter is there are only so many ways to address this problem, and F5's iRules offers one of the coolest, simplest ways of doing just that, so it's bound to be popular. Here's one example of just that courtesy of the forums. when HTTP_RESPONSE { if { [HTTP::header exists "jsessionid"] } { set jsess_resp [findstr [HTTP::header "jsessionid"] "!" 1 "!"] if { $jsess_resp != "" } { persist add uie $jsess_resp } } } Cookie Based Virus Scan Decisions http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&tpage=1&view=topic&postid=24045#24173 This cool example shows how a user is making use of a combination of information, including cookies and the HTTP URI, to determine whether or not incoming traffic needs to be passed through an AV gateway. The code itself is relatively straight-forward, but it's another great example of one of the many, many things you might use an iRule for that just doesn't have another clear, simple solution. Nice one. when HTTP_REQUEST { set ID [findstr [HTTP::cookie "CookieX"] "Cookie" 10 ";"] set my_uri [string tolower [HTTP::uri]] log local0.info "ID is $ID default pool is [LB::server pool] URI is $my_uri" if {($ID equals "")} { log local0.info "sending user to pool [LB::server pool]" pool [LB::server pool] } elseif { ($my_uri ends_with "/attachmentshare/upload.aspx") and not ($ID equals "")} { log local0.info "URI contains $my_uri sending user to pool AVPool$ID" pool AVG$ID snatpool SNAT$ID } else { log local0.info "Cookie found sending user to Pool Pool$ID" pool Pool$ID } } Multi-Pass HTTP Redirect http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&tpage=1&view=topic&postid=24124#24129 Power user hoolio is at it again! In his latest escapades he's helped dacrud come up with a solution that actually uses multiple passes through a single iRule to get the traffic sorted the way they want it. By first redirecting the request to change the hostname, then routing based on URI, this single iRule packs a 1-2 punch that's code-efficient, powerful, and inventive. when HTTP_REQUEST { if {not ([string tolower [HTTP::host]] eq "www.domain.com")}{ HTTP::redirect http://www.domain.com[HTTP::uri] } else { switch -glob [HTTP::path] { "/us*" { pool US_pool log local0. "[IP::client_addr]:[TCP::client_port]: using pool US_pool" } "/au*" { pool AU_pool log local0. "[IP::client_addr]:[TCP::client_port]: using pool AU_pool" } default { pool default_pool log local0. "[IP::client_addr]:[TCP::client_port]: using default pool" } } } } That's it for this week. Be sure to check back for more iRules under that magical 21 line mark next week. Until then, toss out some ideas or feedback and let me know what you're thinking. #Colin529Views0likes0Comments20 Lines or Less #8
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. For this week's 20LoL sampling I've dipped into my own private stash of iRule goodness. Some of these are oldies but goodies, one of them I actually just wrote yesterday as an example for Lori's Blog. As such the newly written example is the only one with a URI. The others will just have a description and the iRule source. I'm sure I'll be diving back into the Forums and CodeShare in the coming weeks as there just seems to be an endless stream of cool stuff to dig through out there, but I wanted to toss up a few of my own rules this week. Be gentle with comments, some of these are old as I said. ;) Content Scrubbing for Adobe Flash Exploit http://devcentral.f5.com/s/weblogs/macvittie/archive/2008/05/29/3309.aspx This iRule digs through the contents of the HTTP responses being sent out from your servers and looks for known exploit sites, then blocks those responses from going to your users. In this way it attempts to help protect them from the spread of the Adobe Flash exploit Lori's been talking about. when HTTP_RESPONSE { HTTP::collect } when HTTP_RESPONSE_DATA { switch -glob [string tolower [HTTP::payload]] { "*0novel.com*" - "*dota11.cn*" - "*wuqing17173.cn*" - "*woai117.cn*" - "*guccime.net*" - "*play0nlnie.com*" { HTTP::respond 200 content "The server is currently unable to serve the requested content. Please try again later." log local0. "Adobe Flash exploit infected Server IP: [IP::server_addr]." } } HTTP::release } IP Client Limiting via Array This iRule was written to deal with a very high-volume need for client limiting. By storing the IPs in an array and accessing them in the most optimized format I could come up with, this rule was able to stand up to some pretty impressive numbers. If memory serves it was somewhere near 200K connections per second with nearly 3 million concurrent connections. Not too shabby! when RULE_INIT { array set connections { } } when CLIENT_ACCEPTED { if { [info exists ::connections([IP::client_addr])] } { if { [incr ::connections([IP::client_addr])] > 1000 } { reject } } else { set ::connections([IP::client_addr]) 1 } } when CLIENT_CLOSED { if { [incr ::connections([IP::client_addr]) -1] unset ::connections([IP::client_addr]) } } Selective HTTPS Redirect This is a slight variant on a popular concept. This iRule does a selective redirect to HTTPS by checking a given class to see if the incoming URI is one that should be served via HTTPS. The neat part here is that it also does a port check and a preventative else statement, meaning this iRule should be able to be deployed on a global virtual, serving all ports, where most examples like this require the traffic to be broken up into two VIPS, port 80 and port 443, to avoid infinite looping. when HTTP_REQUEST { if { [TCP::local_port] == 80 } { log local0. "connecting on HTTP server" if { [matchclass [HTTP::uri] starts_with $::secure_uris] } { HTTP::redirect "http://[HTTP::host][HTTP::uri]" } } } So there you have it, another few examples of what can be done via iRules in less than 21 lines of code. This 20 LoL brought to you from my personal vault, so I hope you enjoy. As always, please let me know if you have any feedback, comments, questions, suggestions, musical recommendations or other pertinent information to share. See you next week. #Colin519Views0likes2Comments20 Lines or Less #10
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. With another three examples of cool iRules, this week's 20 Lines or Less shows even more things you can do in less than 21 lines of code. I still haven't heard much from you guys as to the kinds of things you want to see, so make sure to get those requests in. I can build all sorts of neat iRules if you just let me know what would be helpful or interesting. Otherwise I might just make iRules that make iRules. Scary. This week we've got a couple forum examples and a contribution to the codeshare. Here's your epic, 10th edition of the 20LoL: HTTP Headers in the HTTP Response http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=25423&view=topic Dealing with HTTP headers is one of the most common tasks we see in iRules. One of the things that I've seen floating about the forums and elsewhere lately is the question of how to access that information in the Response portion of the HTTP transaction. Some people have had a problem with this, as many of those headers no longer exist (like, say, the host). It's a simple solution though, as you can see below...just use a variable to get you there. when HTTP_REQUEST { # Save the URI set uri [HTTP::uri] } when HTTP_RESPONSE { if {([HTTP::header Cache-Control] eq "private, max-age=3600") and ($uri ends_with “.html”)} { HTTP::header replace Cache-Control "public, max-age=3600" } } Persistence equality in RDP sessions http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=25271&view=topic This example solves an issue with mixing Linux and Windows based RDP sessions across a persistence enabled virtual Apparently there's an issue with trying to persist based off of the user string as some clients include user@local.host and others just include the username. That's a bit of an issue. iRules to the rescue, as always. when CLIENT_ACCEPTED { TCP::collect } when CLIENT_DATA { TCP::collect 25 binary scan [TCP::payload] x11a* msrdp if { [string equal -nocase -length 17 $msrdp "cookie: mstshash="] } { set msrdp [string range $msrdp 17 end] set len [string first "\n" $msrdp] if { $len == -1 } { TCP::collect } if { $msrdp contains "@" } { if { $len > 5 } { incr len -1 persist uie [getfield $msrdp "@" 1] 10800 } } else { persist uie $msrdp 10800 } } TCP::release } Pool Selection based on File Extension http://devcentral.f5.com/s/wiki/default.aspx/iRules/PoolBasedOnExtension.html Taking a page from the codeshare, this iRule lets you build a correlation of file extensions and pools that serve those particular file types. This can be quite handy when dealing with large scale image servers, media systems, and especially systems that do things like dynamically generate watermarks on images and the like. Take a peek. when HTTP_REQUEST { switch -glob [HTTP::path] { "*.jpg" - "*.gif" - "*.png" { pool image_pool } "*.pdf" { pool pdf_pool } default { pool web_pool } } } There you have it; three more examples in less than 60 lines of code. I hope you're still finding this series helpful. As always, feel free to drop me a line for feedback or suggestions. Thanks! #Colin445Views0likes0Comments20 Lines or Less #13
What could you do with your code in 20 Lines or Less? That's the question I ask every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. After a couple of weeks out of the office, I'm back at it with your weekly dose of iRules goodness in under 20 lines. This week's 20LoL comes from the forums as well as the codeshare. We've got some great examples here, including one iRule that can be used to help augment an already existing LTM module and give it some extra functionality...cool stuff! Blocking Content with iRules This is a good example of a robust, logified way to block certain URI parameters from being allowed through to the back-end servers. Aaron's gone to the trouble to both document the code and the output heavily. That might not be the fastest possible solution in production, but it sure is nice for testing. when HTTP_REQUEST { # Log a debug message with client IP:port and the class contents log local0. "[IP::client_addr]:[TCP::client_port]: class \$::badStrings: $::badStrings" # Check if the client IP is part of the hosts datagroup if { [matchclass [IP::server_addr] equals $::Hosts]}{ # Log a debug message indicating the client IP matched the Hosts class log local0. "[IP::client_addr]:[TCP::client_port]: matched Hosts class \$::Hosts: $::Hosts" # Check if the requested URI contains any known bad strings if { [matchclass [string tolower [HTTP::uri]] contains $::badStrings]}{ # Log a debug message indicating the client matched the Host class and had a bad string in the URI log local0. "Matched server IP and found bad string in [HTTP::uri]: \ entry# [matchclass [string tolower [HTTP::uri]] contains $::badStrings]" # Drop the TCP connection drop } } } MSM Allowlisting https://devcentral.f5.com/s/articles/msm-bypass This codeshare entry shows how you can use an iRule to get even more out of MSM on your LTM. Oh how I love TLAs. By creating an allowlist of known good IP addresses in this iRule, you can skip MSM processing and wring even more performance out of your BIG-IP...nice! priority 1 when CLIENT_ACCEPTED { if { [matchclass [IP::client_addr] equals $::allow_list] } { log local0. "client: [IP::client_addr] found in allow_list directed to http_test_pool" pool http_test_pool event disable all } elseif { [matchclass [IP::client_addr] equals $::deny_list] } { log local0. " client: [IP::client_addr] found in deny_list directed to http_test_pool_2" pool http_test_pool_2 # or discard event disable all } } Search and Replace via iRule This example shows some of the things that can be done via the stream profile and selectively enabling replacements via iRules. The stream profile gives you plenty of ability to do data swapping in-line with even more speed than writing out the logic by hand in an iRule. Definitely good stuff. when HTTP_REQUEST { set replace_content 0 if {[HTTP::uri] contains "/atoz/"} { set replace_content 1 } } when HTTP_RESPONSE { if {$replace_content equals "1"} { # Disable the stream filter by default STREAM::disable # Check if response type is text if {[HTTP::header value Content-Type] contains "text" and [HTTP::header "User-Agent"] contains "***"}{ # Replace STREAM::expression "@123@xyz@ @456@xyz@" # Enable the stream filter for this response only STREAM::enable } } } There you have it, three more examples of iRules goodness in less than 20 lines each. See you next week. #Colin399Views0likes0Comments