20 Lines or Less #1
Yesterday I got an idea for what I think will be a cool new series that I wanted to bring to the community via my blog. I call it "20 lines or less". My thought is to pose a simple question: "What can you do via an iRule in 20 lines or less?". Each week I'll find some cool examples of iRules doing fun things in less than 21 lines of code, not counting white spaces or comments, round them up, and post them here. Not only will this give the community lots of cool examples of what iRules can do with relative ease, but I'm hoping it will continue to show just how flexible and light-weight this technology is - not to mention just plain cool. I invite you to follow along, learn what you can and please, if you have suggestions, contributions, or feedback of any kind, don't hesitate to comment, email, IM, whatever. You know how to get a hold of me...please do. ;) I'd love to have a member contributed version of this once a month or quarter or ... whatever if you guys start feeding me your cool, short iRules. Ok, so without further adieu, here we go. The inaugural edition of 20 Lines or Less. For this first edition I wanted to highlight some of the things that have already been contributed by the awesome community here at DevCentral. So I pulled up the Code Share and started reading. I was quite happy to see that I couldn't even get halfway through the list of awesome iRule contributions before I found 5 entries that were neat, and under 20 lines (These are actually almost all under 10 lines of code - wow!) Kudos to the contributors. I'll grab another bunch next week to keep highlighting what we've got already! Cipher Strength Pool Selection Ever want to check the type of encryption your users are using before allowing them into your most secure content? Here's your solution. when HTTP_REQUEST { log local0. "[IP::remote_addr]: SSL cipher strength is [SSL::cipher bits]" if { [SSL::cipher bits] < 128 }{ pool weak_encryption_pool } else { pool strong_encryption_pool } } Clone Pool Based On URI Need to clone some of your traffic to a second pool, based on the incoming URI? Here you go... when HTTP_REQUEST { if { [HTTP::uri] starts_with "/clone_me" } { pool real_pool clone pool clone_pool } else { pool real_pool } } Cache No POST Have you been looking for a way to avoid sending those POST responses to your RAMCache module? You're welcome. when HTTP_REQUEST { if { [HTTP::method] equals "POST" } { CACHE::disable } else { CACHE::enable } } Access Control Based on IP Here's a great example of blocking unwelcome IP addresses from accessing your network and only allowing those Client-IPs that you have deemed trusted. when CLIENT_ACCEPTED { if { [matchclass [IP::client_addr] equals $::trustedAddresses] }{ #Uncomment the line below to turn on logging. #log local0. "Valid client IP: [IP::client_addr] - forwarding traffic" forward } else { #Uncomment the line below to turn on logging. #log local0. "Invalid client IP: [IP::client_addr] - discarding" discard } } Content Type Tracking If you're looking to keep track of the different types of content you're serving, this iRule can help in a big way. # First, create statistics profile named "ContentType" with following entries: # HTML # Images # Scripts # Documents # Stylesheets # Other # Now associate this Statistics Profile to the virtual server. Then apply the following iRule. # To view the results, go to Statistics -> Profiles - Statistics when HTTP_RESPONSE { switch -glob [HTTP::header "Content-type"] { image/* { STATS::incr "ContentType" "Images" } text/html { STATS::incr "ContentType" "HTML" } text/css { STATS::incr "ContentType" "Stylesheets" } *javascript { STATS::incr "ContentType" "Scripts" } text/vbscript { STATS::incr "ContentType" "Scripts" } application/pdf { STATS::incr "ContentType" "Documents" } application/msword { STATS::incr "ContentType" "Documents" } application/*powerpoint { STATS::incr "ContentType" "Documents" } application/*excel { STATS::incr "ContentType" "Documents" } default { STATS::incr "ContentType" "Other" } } } There you have it, the first edition of "20 Lines or Less"! I hope you enjoyed it...I sure did. If you've got feedback or examples to be featured in future editions, let me know. #Colin4.5KViews1like1Comment20 Lines or Less #64: VIP to VIP redirection, URL separation and Redirect Rewriting
What could you do with your code in 20 Lines or Less? That's the question I like to ask for the DevCentral community, and every time I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. If there's one thing I learned on the road recently, traipsing around to some awesome user groups, it's that there's nearly no end to the uses for iRules in the real world. I've seen things ranging from the simplest redirect rules all the way up to some pretty gnarly complexity implementations, and everything in between. It's awesome to see iRules of many incarnations doing their thing, and it continues to remind me just how many ways people are using this technology in a myriad of ways. To that end this week brings another set of iRules examples showcasing a few more ways in which the community is putting iRules to work. Thanks to the wicked community doing that thing that you all do, we've got Virtual to Virtual redirection, rewriting mid redirection, as well as separation of URL/URI content. Not only that, but this week examples in less than 20 lines wasn't enough of a challenge. Instead I'm delivering 3 examples in less than 10 lines of code each. It's the super minified version of the 20LoL, for those efficiency minded folks. Let's dig in: Using an iRule to redirect traffic to different Virtual Servers Using an iRule to redirect traffic to different Virtual Servers iRules and redirection is a match that has been made time and time again for years. A new twist on this ability, however, came about with the capability for iRules to direct traffic from one Virtual Server to another. This is often referred to as VIP targeting VIP. This can be useful for many reasons, not the least of which is toggling profiles based on request info which is something I've had a bit of experience with lately for some Web Accelerator testing…but more about that later. User wbbigdave posed this question about directing traffic from on VS to another to create the ultimate VIP to rule them all. Fortunately for his VIP ruling needs this is completely possible, and Richard gave a simple example of how. 1: when CLIENT_ACCEPTED { 2: if {[TCP::remote_port] == 80} { 3: virtual HTTP_virtual 4: } 5: } Yet another redirect question Yet another redirect question User drizzle is looking for a way to do some URI rewriting of a URI in the midst of a redirection. The situation is that they need to respond to a user with the requested URI modified to replace a given portion of the URI with a separate string. This is easy to do in an iRule, of course, and Michael Yates was kind enough to provide a great example of exactly how this works. 1: when HTTP_REQUEST { 2: switch -glob [string tolower [HTTP::host][HTTP::uri]] { 3: "some.host.com/singleuri*" { 4: HTTP::respond 301 Location "https://some.other.host.com[string map {"/singleuri" "/anotheruri"} [HTTP::uri]]" 5: } 6: } 7: } Looking to separate URL from URI Looking to separate out URL from URI In this final example user Snowman (yeah…awesome name, right?) was looking for a way to split up and examine different portions of an HTTP URI. There are a few options to go about this depending on whether or not you want to inspect the query string or just the HTTP path, etc. After a bit of tweaking it seems that they were able to come up with a solution that worked for them using linden and split to effectively tokenize the HTTP::path variable, and then make decisions based on that list. Very handy stuff to keep around as this is broadly useful logic. 1: when HTTP_REQUEST { 2: set host [HTTP::host] 3: set uri_list [split [string tolower [HTTP::path]] /] 4: if { [lindex $uri_list 2] equals "admin"} { 5: HTTP::respond 302 Location "https://$host/user" 6: } 7: }1.3KViews0likes0Comments20 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 #75: URIs, URIs and more URIs
What could you do with your code in 20 Lines or Less? That's the question I like to ask for the DevCentral community, and every time I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. One of the most common things manipulated by iRules out in the wild is the Host or URI HTTP header values. This is done for a myriad of reasons ranging from routing to obfuscating portions of an application to… you name it. Given that it’s so common amongst iRulers worldwide it’s noshock that I managed to track down three recent examples of people doing URI-ish things with iRules. So in the first of what I hope to be several“themed” 20 Lines or Less installments, here are three ways that people are using iRules to handle their URI needs. Lowercase URI https://devcentral.f5.com/s/questions/lowercase-uri Ensuring that comparisons are done in a single case is one of those basic but super important things that we all do when we’re writing code. As such precisely no one is surprised that it’s also extremely common, and important, in iRules. The string command has a tolower function that takes care of this for us in TCL. Making sure we’re only using it when and how we want, however, sometimes takes inspection of the URI. In this case the OP was looking for a way to only modify the URI for any incoming “.aspx” requests. The below iRule should was the solution posted by a helpful community member that should get them there. Note the handy "Only re-write if the URI contains uppercase characters" logic with string match to prevent recursion! Tasty. when HTTP_REQUEST { if { ([string match {[A-Z]} [HTTP::uri]] and [[HTTP::path] ends_with ".aspx"])} { set hostname [string tolower [HTTP::host]] set uriname [string tolower [HTTP::uri]] log local0. "Request is $hostname$uriname" HTTP::redirect "http://$hostname$uriname" } } Append Text to a URI https://devcentral.f5.com/s/questions/append-text-to-a-uri Apart from inspecting the URI and modifying case, modifying the actual contents of the URI is the next most common action on my completely unofficial or scientific list of “Things User do with URIs”. As such, here’s a simple example of a user conditionally appending a slash to the inbound URI. when HTTP_REQUEST { if {!([HTTP::path] ends_with "/")} { HTTP::path "[HTTP::path]/" HTTP::redirect [HTTP::uri] } } Switch on HTTP::host and HTTP::uri https://devcentral.f5.com/s/questions/how-to-use-an-irule-switch-to-match-httphost-and-httpuri Sliding ever so slightly higher on the “How scary can URIs actually be?” scale (Hint: the answer is generally ‘not very scary…mostly’) we have a user looking to perform a switch on a Host/URI combo. Still not tough, but super handy and worth seeing in case you’re new or rusty, this switch will give you the full host/uri/path of the inbound request and let you take separate actions on any particular match. when HTTP_REQUEST { switch -glob [string tolower [getfield [HTTP::host] ":" 1][HTTP::uri]] { "www.liveapp.customer.co.uk/app2easypath_" { HTTP::path [string map { /app2easypath /realpath } [HTTP::path]] }; SSL::disable serverside; pool CUST1-WEB-PROD-APP2-Pool; } "www.testapp.customer.co.uk/app2easypath_" { HTTP::path [string map { /app2easypath /realpath } [HTTP::path]] }; SSL::disable serverside; pool CUST1-WEB-PROD-APP2-test-Pool; } default { HTTP::redirect http://www.google.com} } } }880Views0likes5Comments20 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. #Colin529Views0likes0Comments