20 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. #Colin522Views0likes2Comments20 Lines or Less # 42 – Secret list … OF DOOM
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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 bring to you two cool iRules from the forums and one from a secret squirrel internal mailing list OF DOOM!!!. Okay, maybe not of doom, but it’s a list with some wicked smart people on it and I’m lucky to get to harvest good stuff out of there sometimes. We’ll cover handling HTTP and HTTPS on a single VIP, stream matching TCP data, and HTTP rate limiting with the table command in yet another variation. TCP Payload Matching and Logging http://bit.ly/efMH9z User mattrm was kind enough to post back to this thread started a few months back to show us exactly how he got this stream match solution working in his environment. A very cool example of how to search and replace a string in-line. In this case he’s dealing with straight TCP traffic, but just about any non encrypted traffic (including traffic decoded on the LTM) would work. Using the stream profile: @Username.*Userpassword=\n@@ : when STREAM_MATCHED { # log each match found by the stream filter scan [STREAM::match] "Username=%s" user log local0. "Username [b64decode $user] had password replaced" STREAM::replace "Username=$user\nUserpassword=0000=\n" } when LB_SELECTED { set serverIP [LB::server addr] log local0. "LB Server IP $serverIP" } Selective HTTP redirection based on SSL http://bit.ly/g6bCbG In this interesting iRule user Dave Hatfield is looking to redirect traffic that is not using SSL to an HTTPS link, while dealing with non SSL traffic differently, but on the same virtual and in the same iRule. That poses an interesting problem of identifying SSL vs non SSL traffic in a single virtual / iRule. There are a couple of ways to go about this, and I think he chose a solid one. Simple and easy to follow, yet effective. Cool stuff. when CLIENT_ACCEPTED { # Set a variable to track whether this is an HTTPS request set https 0 } when CLIENTSSL_HANDSHAKE { # There was a client side SSL handshake, so update the variable set https 1 } when HTTP_REQUEST { # Check if referrer is eschool if {!([HTTP::header "Referer"] starts_with "https://eschool.mysite.org/webapps/")}{ # If there is no URI redirect to portal if {[HTTP::path] eq "/" }{ HTTP::redirect "https://portal.mysite.org/eschool" } } if {not ($https)}{ # If it's not an HTTPS connection, send a redirect HTTP::redirect https://[HTTP::host][HTTP::uri] } } HTTP Request limiting via tables One of the engineers here at F5, Christian Koenning spawned a cool example iRule showing off how to achieve a stable 3000 requests per second threshold by making use of the table command and some logic inside an iRule. The illustrious Kirk Bauer then tweaked it a bit and twisted it into an HTTP example, which is what I’m posting below. when HTTP_REQUEST timing on { set request_limit_reached [ table lookup "request_limit_reached" ] if { [expr [table incr "counter_all_requests"] % 15] == 0 } { if { $request_limit_reached < 2 } { set request_limit_reached [ table incr "request_limit_reached" ] table timeout "request_limit_reached" 1 table lifetime "request_limit_reached" 1 } } if { $request_limit_reached >= 2 } { HTTP::respond 500 } } There we go, another three killer iRules in less than 21 lines. Thanks as always to the community for doing that thing you do. Keep on rockin’, and posting those iRules. If you have any questions or comments, never hesitate to drop me a line. #Colin341Views0likes1Comment20 Lines or Less #46: DNS, RPC and Classes
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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 the long standing tradition, this week’s 20LoL brings to you DNS lookups with variable resolvers, avoiding RPC issues with ASM, and some advanced pool selection logic by way of class searching. Thanks go out to user Kent Perrier, mbamusa and ichalis for the examples or inspiration. Now let’s get to the code: Advanced Pool Selection http://devcentral.f5.com/s/Community/GroupDetails/tabid/1082223/asg/50/aft/1177260/showtab/groupforums/Default.aspx Kent was looking for a way to dynamically select the pool to which traffic would be directed by searching through a class, but didn’t have much experience dealing with classes. Since he’s running v10.2.1 he gets to make use of the awesome class command for searching/matching, and was able to piece together his own solution pretty quickly with a little care and feeding by way of link sharing from the community. His iRule checks for the class, compares the beginning of the incoming URI with the entries from the class, and selects a pool based on the results.Here’s what he ended up with. when RULE_INIT { # Log debug to /var/log/ltm? 1=yes, 0=no set static::debug 0 } when CLIENT_ACCEPTED { # Save the VS default pool name before it's changed set default_pool "defpool01" # set the data group name set clname "AppVersion[virtual name]" } when HTTP_REQUEST { # if there isn't a data group with the above name, set the pool to default and exit if {[class exists $clname]} { # Search the datagroup for a name that starts with the URI set pool_name [class search -value $clname starts_with [HTTP::uri]] if { $pool_name eq ""} { # we don't match the context roots in the data class if { $static::debug } { log local0. "fell through to the default pool" } pool $default_pool } else { if { $static::debug } { log local0. "Matched $app_pool" } pool $app_pool } } else { if { $static::debug } { log local0. "Data group $clame not found, using default_pool $default_pool" pool $default_pool } } RPC avoidance and ASM http://devcentral.f5.com/s/Community/GroupDetails/tabid/1082223/asg/50/aft/1178414/showtab/groupforums/Default.aspx User mbamusa deals with OWA, ActiveSync, and Outlook anywhere through a single VIP. When putting ASM in front of this VIP to protect these applications he needed a way to send RPC traffic elsewhere or disable ASM somehow. Fortunately he’s on version 10.2.1 so he’s able to use the ASM::disable/ASM::enable commands, which makes this trivial. Not a difficult iRule, but something good to keep in mind that can solve a major problem with a simple solution. when HTTP_CLASS_SELECTED { if { [string tolower [HTTP::uri]] starts_with "/rpc" } { ASM::disable } else { ASM::enable } } Selective DNS lookups via iRules http://devcentral.f5.com/s/Community/GroupDetails/tabid/1082223/asg/50/afpg/2/aft/8487/showtab/groupforums/Default.aspx We’ve covered doing DNS queries via iRule before. The difference this time is that the requirement is to check one of two different resolvers, based on which is available. This is a pretty common concept, backup resolvers, so I figured it was worth noting here. The solution is pretty straight-forward (until RESOLV::lookup interacts properly with a VIP as a target, then it' gets dead simple) with a couple of variables and an if statement doing the tiny amount of lifting necessary. Again, a simple iRule, but a problem that’s tough to resolve otherwise. set status1 [LB::status pool member ] set status2 [LB::status pool member ] if {$status1 eq "up"} { set ips [RESOLV::lookup @$static::DNS_RESOLVER $host] set _ipaddress [lindex $ips 0] } elseif {$status2 eq "up"}{ set ips [RESOLV::lookup @$static::DNS_RESOLVER_BACKUP $host] set _ipaddress [lindex $ips 0] } #Colin241Views0likes0Comments20 Lines or Less #44: Redirecting, Re-encrypting, and TCP fun
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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 some cool forum examples including Chris Miller’s awesome example of doing a redirect, but in an interesting way that includes an iRule generated HTML page with an in-line meta refresh, some cool SSL re-encryption logic, and a look at how you can use TCP and node commands to send TCP requests. HTTP Redirect with Holding Page http://bit.ly/h7Sq9Q Chris whipped up a cool example of HTTP redirection. The user wanted to be able to send users to a holding page for a given amount of time before redirecting them. Using HTTP::respond, this was pretty straight forward. A very cool example of controlling the user experience via iRules. And yes, I’m cheating slightly by doubling up braces to get this one down to 20 lines (I’m also counting the HTTP::respond as one line since it technically is, it’s just continued on multiple lines for readability). Sue me, it’s a cool rule. ;) when HTTP_REQUEST { if { [TCP::local_port] eq "80" } { persist source_addr 1800 HTTP::fallback http://support.com/ if { [HTTP::host] == "www.domain.co.uk" or "www.domain.com" or "www.domain.org" } { HTTP::respond 200 content \ " Apology pagehttp://www.domain.com/aba/>\ We are sorry, but the site you are looking for is temporarily out of service. " "Content-Type" "text/html" } else { pool Web_Farm_Front } } elseif { [TCP::local_port] eq "443" } { HTTP::header insert "BPL-SSL" "On" pool Web_Farm_Front } else { set srvr [findclass [TCP::local_port] $::Individual_Servers " "] if { $srvr ne "" } { node $srvr 80 } else { HTTP::redirect "http://www.domain.net/" } } } Selective SSL Re-encryption http://bit.ly/eyfxbV Another Chris Miller special, this iRule shows a good way to take HTTP traffic, decrypt it, analyze it, send it to the appropriate pool, and then re-encrypt only some of that traffic as needed. It’s not going to solve the user’s problem, unfortunately, but that’s because of specific app requirements. It’s still a pretty cool piece of code. when HTTP_REQUEST { set usessl 0 switch -glob [string tolower[HTTP::path]] { "/main*" { pool beta__pool set usessl 1 } default { pool alpha_pool set usessl 0 } } } when SERVER_CONNECTED { if { $usessl == 0 } { SSL::disable } } TCP Out of Band Send on Pool Down http://bit.ly/fMAp79 Thanks to some good ideas from Aaron, I put together what I think is a pretty interesting iRule that should (it’s untested) allow you to check for all pool members of a particular pool to be down, and if that’s the case, send a TCP request off to a node of your choosing with a custom message as sort of an alert to notify that the pool is down. Hopefully this solves the user’s issue, but regardless I like the concept and I’m now looking for a place to try it out. when CLIENT_ACCEPTED { if {[active_members yourpoolname] == 0 } { TCP::collect } } when CLIENT_DATA { TCP::payload replace 0 [TCP::payload length] "down" node 10.10.10.1 12000 TCP::release } There you are, another few iRules that can get some solid work done in less than 21 lines. #Colin282Views0likes0Comments20 Lines or Less #43 – Nesting, Rewriting Redirects and Auth
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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. In the first 20LoL of the new year I bring to you a diverse offering of iRule goodness ranging from HTTP Authentication via iRule, to nesting switch inside if and why it’s important not to use elseif when doing so, as well as re-writing partial URL strings for redirection. Nesting switch inside if http://devcentral.f5.com/s/Community/GroupDetails/tabid/1082223/asg/50/afv/topic/aft/1176698/aff/5/showtab/groupforums/Default.aspx It earns cool points, in my opinion, to use logic in cool ways like this. The big caveat to keep in mind though is something that user TMaCEvans ran into, elseif. If you’re adding a switch statement inside your if logic keep in mind that the switch statement itself isn’t a valid comparison for the elseif operator. This means you’ll need to use a simple else and put the switch inside there with whatever appropriate logic you need, as Chris Miller pointed out in his helpful response containing this example: when HTTP_REQUEST { if { [string tolower [HTTP::path]] starts_with "/xyz/" or [string tolower [HTTP::query]] contains "xy=9" } { if { [HTTP::method] eq "GET" and [HTTP::header "Upgrade"] contains "WebSocket" } { HTTP::disable pool pool3 } pool pool3 } else { switch -glob [string tolower [HTTP::uri]] { "/fr/app*" { pool pool2 } default { pool pool1 } } } } URI Re-writing for redirection http://devcentral.f5.com/s/Community/GroupDetails/tabid/1082223/asg/50/afv/topic/aft/1176697/aff/5/showtab/groupforums/Default.aspx#1201401 User ukitsysadmin has been asking about how to take a part (the end) of an existing URI and use that as the key for a class lookup to find the new URI he wants to redirect users to. This is very doable and Aaron knocked out the more complex string parsing logic. I came in to finish up with a little class search/findclass goodness. I’m listing the v10 version of the example, even though it turned out ukitsysadmin is on 9.4.7. I just think class match is sexier than findclass. when HTTP_REQUEST { set uri_token [string range [HTTP::path] [expr {[string last / [HTTP::path]] + 1}] end] } when HTTP_RESPONSE { if {[HTTP::status] == 404} { set red_uri [class match -value $uri_token equals class_name] HTTP::redirect $red_uri } } HTTP Basic Auth via iRules http://devcentral.f5.com/s/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/1086387/HTTP-Basic-Access-Authentication-iRule-Style.aspx While digging through the forums I came across this post which talks about HTTP auth via an iRule. As Jason was kind enough to point out, George wrote this up in a Tech Tip a while back that showed how to do this clearly and to great effect. I figured I’d link to the full article as well as the post for clarity. This is a very cool technique that I can’t remember if I’ve highlighted here or not (130+ 20LoL code examples later…things tend to blend together), so I’m adding it here because it’s slick and can potentially be very handy. when HTTP_REQUEST { binary scan [md5 [HTTP::password]] H* password if { [class lookup [HTTP::username] $::authorized_users] equals $password } { log local0. "User [HTTP::username] has been authorized to access virtual server [virtual name]" # Insert iRule-based application code here if necessary } else { if { [string length [HTTP::password]] != 0 } { log local0. "User [HTTP::username] has been denied access to virtual server [virtual name]" } HTTP::respond 401 WWW-Authenticate "Basic realm=\"Secured Area\"" } } There you have it, some more cool iRule examples to remind you just how powerful this stuff can be in less than 21 lines of code. Pass it one, send some feedback, make some requests to let me know what you’d like to see next time, and I’ll be back with more as always. #Colin239Views0likes0Comments20 Lines or Less #41 - When spark flies
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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’m happy to bring you some very cool iRules dealing with client access to admin sections of an application, strict RR Load Balancing, and client connection limiting. Moreover, I’m even more pleased that two of the examples in this episode are from spark himself, one of the core Developers responsible for making iRules do the magic that it does. It’s always fun getting to see what kind of kung fu he comes up with in the forums, and he certainly didn’t disappoint this week. Strict Round Robin LB http://bit.ly/bsNsPV In this first example, spark chimes in to help user AppleBee set up some strict round robin load balancing via iRules and the table command. This is a great example of how to build more rigid, precise controls when your application calls for them. In this manner, AppleBee is able to have exact control over where the requests are trying to go so that even if CMP is enabled the load balancing rotation doesn’t change. when CLIENT_ACCEPTED { set poolname "test-pool" if { [active_members $poolname] < 1 } { # No active pool members; reset client reject return } set count [members $poolname] set attempt 0 while { $attempt < $count } { set num [expr {[table incr "round-robin:$poolname"] % $count}] set mbr [lindex [members -list $poolname] $num] set mbr_ip [lindex $mbr 0] set mbr_port [lindex $mbr 1] if { [LB::status pool $poolname member $mbr_ip $mbr_port up] } { pool $poolname member $mbr_ip $mbr_port return } incr attempt } } Request filtering based on URL http://bit.ly/cGEaob Next, Chris Miller helps out another user by showing them a quick and easy way to restrict access to specific URLs by IP address. This is a simple way to make sure no unwanted guests are trying to visit the admin section of your site, viewing sensitive data, etc. when HTTP_REQUEST { if { [HTTP::host] eq "www.admin.mysite.com" and ![IP::addr [IP::client_addr]/24 eq 192.168.1.0] } { discard } } CMP Compatible Connection Limiting per Pool Member http://bit.ly/b3Lb0k Last but certainly not least is another sparkism (hmm, I think I just coined a new term) that shows off yet another use for the wonderfully powerful and handy table command. This time spark is wielding its power to show a way to limit the number of requests to each pool member. It’s surprisingly easy thanks to the table command and a little help from an after –periodic to help with matching the timer to the connection. Very cool stuff. when CLIENT_ACCEPTED { set key "[IP::client_addr]:[TCP::client_port]" } when LB_SELECTED { set tbl "connlimit:[LB::server]" table set -subtable $tbl $key "ignored" 180 if { [table keys -subtable $tbl -count] > 5 } { table delete -subtable $tbl $key event CLIENT_CLOSED disable reject } else { set timer [after 60000 -periodic { table lookup -subtable $tbl $key }] } } when CLIENT_CLOSED { after cancel $timer table delete -subtable $tbl $key } There we go, three more awesome iRules to put in your quiver that are less than 21 lines each. Thanks much to all those contributing in the forums, keep that goodness coming. #Colin227Views0likes0Comments20 Lines or Less #40 – SSL payload searching, user info and ACLs
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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 dive into parsing SSL encrypted payloads until a given string is found, logging user login info as it comes across the wire, and enforcing a subsite ACL. http://devcentral.f5.com/s/Community/GroupDetails/tabid/1082223/asg/50/afv/topic/aft/1172756/aff/5/showtab/groupforums/Default.aspx#1175124 In this first, rather cool, example from user mattrm we get a peek at how he’s dealing with logging user info as they log in by making use of the stream profile, STREAM::match command and regular expressions. when STREAM_MATCHED { # log each match found by the stream filter log local0. "Stream filter matched:[STREAM::match]" set myvar [STREAM::match] set 4 "blah" regexp {Username=(.+)\sUserpassword=(.+)\sUseremail=(.+)\sUserhomefolder=(.+)\s} $myvar matched sub1 sub2 sub3 log local0. "Username=[b64decode $sub1] Userpassword=[b64decode $sub2] Usermail=[b64decode $sub3]" } when LB_SELECTED { set serverIP [LB::server addr] log local0. "LB Server IP $serverIP" } http://devcentral.f5.com/s/Community/GroupDetails/tabid/1082223/asg/50/afv/topic/aft/1174268/aff/5/showtab/groupforums/Default.aspx Bhattman and Chris Miller tag team to answer a thread talking about creating a sub-site ACL and provides this cool little chunk of code. The idea is pretty simple, block access to a specific section of an app unless the client is coming from a specific list of IP addresses. The implementation is wonderfully simple, though, complete with an Access Denied-esque message straight from the iRule. when HTTP_REQUEST { if { [class match [string tolower [HTTP::uri]] contains subsite] and !([[string tolower [HTTP::uri]] contains "/admin/upload") and ![class match [IP::addr [IP::client_addr]] eq allow] } { HTTP::respond 200 content " Forbidden Redirect From Remote Server\Acess is forbidden" } } http://devcentral.f5.com/s/Community/GroupDetails/tabid/1082223/asg/50/afv/topic/aft/1174288/aff/5/showtab/groupforums/Default.aspx Last but never least, spark rolls up his sleeves and flexes an ounce of his iRuling muscle to show how easy it can be to collect SSL payload data until a given string is found. He even goes one step further to discuss the difference in functionality between the TCP::collect and SSL::collect commands and how the base functionality is similar but not identical. Definitely a cool one. when CLIENTSSL_DATA { if { [SSL::payload] contains "the query string" } { log local0. "I got the query!" SSL::release } else { SSL::collect } } There you have it, three more examples of iRules coolness in less than 21 lines of code each. See you soon for more iRuling goodness. #Colin298Views0likes0Comments20 Lines or Less #39 – Selective SSL, Port Stripping and Headers
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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 the onslaught of work required to get DC5 up and running it’s been a while since I’ve offered some cool iRule goodness to the community from the community. There have been plenty of examples cruising through the forums, that’s for sure, I just haven’t had the time to comb through all of them or write them up. Now that I can again see the light of day, allow me to share a some good ones with you. Disabling SSL to one backend pool We’ve looked at ways to selectively disable SSL before, but this example had an interesting twist that I thought was…well…interesting. The idea here is to selectively disable SSL only on the back end of the connection, not the entire thing. The client should always be encrypted but the server can, in some cases, be plain-text to try and cut down on overhead. Cool idea, and here’s a look at how to make it work, according to a good example by user Alok. when HTTP_REQUEST { set my_uri [string tolower [HTTP::uri]] if { $my_uri starts_with "/secure" } { pool ssl__pool } else { SSL::disable serverside pool static_pool } } Hash persistence based on true-client IP Here’s a user that’s trying to work around a limitation in the content distribution service they’re using. They want to use an iRule to perform hash based persistence based on a header supplied giving the client’s IP address. Hoolio, as is often the case, springs into action and whips up a nifty little example making use of lindex and active_members –list that gets the job done. # Check if the active_members command returns an entry which can be split on a space into two variables if {[active_members app_http_pool]}{ if {[scan [lindex [active_members –list app_http_pool] [expr {[md5 $tcip_header] % [active_members app_http_pool]}]] {%s %s} ip port] == 2}{ # Select the pool member IP and port pool app_http_pool member $ip $port # Exit from this event in this rule return } # Take some default action if the pool is down or scan didn't parse the output? } Removing port numbers from redirects If you’re looking to strip port locations from your redirects, then boy do I have the rule for you. Well, it’s not my rule, really, but I get to share more of Aaron’s work with you, which is a regular and enjoyable part of my jobs these days, it seems. The one man juggernaut has knocked out a quick little header replacement rule using string map and the fun HTTP::is_redirect command to get this job done. when HTTP_RESPONSE { if { [HTTP::is_redirect] } { if { [HTTP::header Location] contains "www.acme.com:10040" } { log local0. "Original Location value: [HTTP::header Location]" HTTP::header replace Location [string map -nocase {www.acme.com:10400 www.acme.com} [HTTP::header value Location]] } } } when HTTP_RESPONSE priority 501 { if { [HTTP::is_redirect] } { # Debug logging only. Remove this event once done testing log local0. "Updated Location value: [HTTP::header Location]" } } Check back next week for some more examples of awesome things you can do with iRules in only a few lines of code. #Colin208Views0likes0Comments20 Lines or Less #38 – Classes, Encryption Detection & Caching
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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 a couple awesome new examples from two of the community all-stars, and one dusty old example from my archives. They’re all cool and useful, so take a peek and see what you think. If you want a problem solved or to submit an example, feel free, I’m always looking for feedback or ideas for the 20LoL, just drop me a line. Class field parsing & updating Host info http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=1171133&view=topic Matt shows off why they call him L4L7 in this example of how to use some iRules fu to match class contents, parse it and then act on it. The requirement was updating the host header inline, while maintaining the mappings of what to change and what to change it to in a class, and that gets done in style. when HTTP_REQUEST { #find a match using host+uri against the class and #returns the whole string (field1 field2 field3)then #set it as newURI variable. set newURI "[findclass [HTTP::host][HTTP::uri] $::redlist]" if { $newURI ne "" } { # Parse the three fields in the matched datagroup line scan $newURI {%s %s %s} unused host uri #change host and uri if {$host ne ""}{ HTTP::header replace Host $host } if {$uri ne ""}{ HTTP::uri $uri } } } HTTP connections over 443 http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=1171154&view=topic For a look at how to gracefully handle non encrypted HTTP traffic over port 443 (you know, just in case) hoolio has you covered this week. Basically this inspects the traffic and if there was an SSL cipher used, redirects requests to “/” to the login page. If there is no cipher used, meaning the traffic is not encrypted but is still coming over port 443, any requested URI is redirected to the SSL enabled login page. Handy stuff. when HTTP_REQUEST { # Check if the client used an SSL cipher if {not ([catch {SSL::cipher version} result]) && $result ne "none"}{ # Client did use a cipher log local0. "\$result: $result. Allowing encrypted request." if {[HTTP::path] eq "/"}{ HTTP::redirect "https://[getfield [HTTP::host] : 1]/Login.jsp" } } else { # Client did not use a cipher log local0. "\$result: $result. Redirecting unencrypted request." HTTP::redirect "https://[getfield [HTTP::host] : 1]/Login.jsp" } } Selective browser caching Taking a trip in the way-back machine I decided to dig into my archives of cool iRule goodness for our third example this week. Here’s a little iRule that I acquired along the way somewhere (I’m not going to claim I wrote it, since I can’t remember if it was me or someone else) that was simple but useful. Create two classes of file extensions, one to be cached long term (jpgs, gifs, pngs, etc) and one to be cached for a much shorter duration (css, html, whatever) then easily tell the client’s browser how to handle each. when HTTP_REQUEST { set uri [HTTP::uri] } when HTTP_RESPONSE { if { [matchclass $uri ends_with $::cache_5min] } { HTTP::header replace "Cache-Control" "max-age=500" } elseif { [matchclass $uri ends_with $::cache_60min] } { HTTP::header replace "Cache-Control" "max-age=3600" } } That’s the 20LoL this week, thanks for playing. I’ll be back next week with more iRules goodness, so make sure to check back in. #Colin198Views0likes0Comments20 Lines or Less #37 - Hex, HTTPS, and SNATing
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week for the devcentral community, 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. I bring to you your weekly dose of short yet cool iRule goodness. Check out what these iRule gurus have crammed into less than 21 lines of code. This week we’ve got hex translation of HTTP payloads, intelligent redirection including port handling, and some snat intelligence in just a few lines of code. Dig it. Log binary HTTP payload in hex http://devcentral.f5.com/s/wiki/default.aspx/iRules/Log_binary_HTTP_payload_in_hex.html Here’s one that we touched on briefly in the podcast last week. Hoolio decided that it would be fun or handy or…something, to convert and log the entire HTTP payload in hex for every response. I couldn’t tell you when this would be needed, but it was a pretty darn cool thought, and I thought I’d share it. Maybe he’ll come tell us what it was for. ;) when HTTP_REQUEST { # Log debug? 1=yes, 0=no set debug 1 # Collect up to the first 1MB of POST data if {[HTTP::method] eq "POST"}{ set clength 0 # Check if there is a content-length header and the value is set to less than 1Mb if {[HTTP::header exists "Content-Length"] && [HTTP::header Content-Length] set clength [HTTP::header Content-Length] } else { set clength 1048576 } if {[info exists clength] && clength > 0} { if {$debug}{log local0. "[virtual name]: Collecting $clength bytes"} HTTP::collect $clength } } } when HTTP_REQUEST_DATA { # Log the payload converted to hex binary scan [HTTP::payload] H* payload_hex if {$debug}{log local0. "[virtual name]: $payload_hex: $payload_hex"} } SNAT based on incoming IP http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=1170490&view=topic Matt dished out a great little example of how to effectively control which snat address a connection is assigned based on the IP range the request is coming in from. It’s simple, it’s efficient, it’s effective, and it’s short. Those are a few of my favorite things in iRules, so here you go. when CLIENT_ACCEPTED { if { [IP::addr [IP::client_addr] equals 10.9.9.0/26] }{ snat 1.1.1.1 } elseif { [IP::addr [IP::client_addr] equals 10.9.9.65/26] }{ snat 2.2.2.2 } elseif { [IP::addr [IP::client_addr] equals 10.9.9.128/26] }{ snat 3.3.3.3 } else { forward } } Intelligent HTTP to HTTPS redirection…now with port handling! http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=1168453&view=topic This is a topic (HTTP to HTTPS redirection) that I’ve shown off at least a few times in the 20LoL, but that’s because it comes up so darn often in the forums and elsewhere. Here is yet another take on how to do it, and a darn good one at that. Note the use of string map, which I heart, and the fact that this one can actually handle requests that specifically have the port declared in the hostname. If you try to redirect to HTTPS but still have a :80 in your host, things might not go as swimmingly as you’d like. when HTTP_RESPONSE { # Check if server response is a redirect if { [HTTP::header is_redirect]} { # Log original and updated values log local0. "Original Location header value: [HTTP::header value Location],\ updated: [string map -nocase "http:// https:// :80/ /" [HTTP::header value Location]]" # Do the update, replacing http:// with https:// and :80/ with / HTTP::header replace Location \ [string map -nocase "http:// https:// :80/ /" [HTTP::header value Location]] } } There you go, 3 more examples of iRules goodness in 20 Lines or Less each. See ya next time. #Colin231Views0likes0Comments