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 #12
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. Here we go again, three more examples of the powerful and interesting things you can do with iRules in less than 21 lines. Dipping again into the forums, with a few tweaks here and there (don't worry, I stayed honest to the rule, just took out comments and extra case comparisons, that kind of thing), we've got an action packed 20LoL this week. Here we go: SSL iRule on a non-SSL VIP http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=26299&view=topic This is a great example of using a single iRule for both HTTP and HTTPS traffic. In the forum post Deb shows a cool trick to allow us to sneak SSL commands past the iRule interpreter so that they are there when we need them, if a cert is found, but aren't used when the connection turns out to be straight HTTP. Pretty cool stuff. when HTTP_REQUEST { HTTP::header replace ClientIP [IP::remote_addr] if {[PROFILE::exists clientssl] == 1} { set cname "SSL::cipher name" set cbits "SSL::cipher bits" set cver "SSL::cipher version" HTTP::header replace SSLCipher [eval $cname]:[eval $cbits]-[eval $cver] if { [SSL::cert count] > 0} { HTTP::header replace SSLSubject [b64encode [X509::subject [SSL::cert 0]]] HTTP::header replace SSLClientCert [b64encode [SSL::cert 0]] HTTP::header replace WebProtocol "HTTPS-auth" } else { HTTP::header replace WebProtocol "HTTPS" } } else { HTTP::header replace WebProtocol "HTTP" } } Extracting DHCP Info http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=25727&view=topic This example for extracting DHCP info is very specific. It's looking for option 82 (Support for Routed Bridge Encapsulation) which may not be particularly useful to everyone out there, but the example stands as a great display of how iRules can help you tear into almost any kind of data, even DHCP data, and make intelligent decisions or actions based on that. Sure, it might take some re-working for your purposes, but what a cool example to get started with! when CLIENT_DATA { binary scan [UDP::payload] x240H* dhcp_option_payload set option 0 set option_length [expr {([UDP::payload length] -240) * 2 }] for {set i 0} {$option != 52 && $i < $option_length} {incr i [expr { $length * 2 +2 }]} { binary scan $dhcp_option_payload x[expr $i]a2 option incr i 2 binary scan $dhcp_option_payload x[expr $i]a2 length_hex set length [expr 0x$length_hex] } if { $i < $option_length } { incr i -[expr { $length * 2 -2 }] binary scan $dhcp_option_payload x[expr $i]a2 length_hex set length [expr 0x$length_hex] incr i 2 binary scan $dhcp_option_payload x[expr $i]a[expr { $length * 2 }] circuit_id } else { drop } } URI re-writing based on Load Balancing decision http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=25791&view=topic Talk about a chicken and egg demonstration. Hearing the title, you might think I have it backwards. When making this kind of decision in an iRule, the URI is often used to help make the load balancing decision. In this case, it's just the opposite. In this example we're letting the BIG-IP make a load balancing decision, then going back and updating the URI based on that decision, before the request is sent to the servers. Very cool stuff! when HTTP_REQUEST_SEND { set uri [string tolower [clientside {HTTP::uri}]] log local0. "[IP::client_addr]:[TCP::client_port]: selected server details: [LB::server] - \$uri: $uri" if {[IP::addr [LB::server addr] equals 10.207.225.101] or [IP::addr [LB::server addr] equals 10.207.225.102] or [IP::addr [LB::server addr] equals 10.207.225.103] }{ log local0. "[IP::client_addr]:[TCP::client_port]: matched server check for .3 or .4" switch -glob [HTTP::uri] { "*/gsfo/gsfopub*" { clientside {HTTP::uri "/Async/CMReceive.ashx"} log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/CMReceive.ashx" } "*/era/erapub*" { clientside {HTTP::uri "/Async/ERAReceive.ashx"} log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/ERAReceive.ashx" } default { log local0. "[IP::client_addr]:[TCP::client_port]: didn't match URI checks" } } } } There you have it, the forums deliver yet again. I have to say I love checking out all these cool, new, compact examples of iRules goodness. Many thanks to the awesome DevCentral community for their continued contributions. I'll see you next week for another 20 Lines or Less. #Colin394Views0likes0Comments