20lol
20 Topics20 Lines or Less #73: VIPs, SMTP Blocking and Responses
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. This week in what I believe to be 20LoL #73 (Lost track…but we’ll go with it) we've got a few more prime examples of iRules doing what iRules do best: solving problems. Whether you're trying to do some fancy footwork when it comes to traffic routing to multiple VIPs, or dealing with some SMTP requests you'd rather not have to, you'll find something handy in this week's 20 Lines or Less. Many thanks to the fine contributors of said examples, both F5ers and otherwise. VIP redirect to another VIP https://devcentral.f5.com/s/questions/vip-redirect-to-another-vip A question that comes in fairly often is how to bounce traffic from one location to another. A very specific version of that question is "How do I get traffic from one of my VIPs to another?". This has been addressed in the Q&A section more than once, but I wanted to put it here in the 20LoL as well, as it seems to be a common theme. As Kevin Stewart nicely put, there are basically two ways to do this. First is with a simple redirect. This is done either via the HTTP::redirect command or by responding with a 301. This will tell the client to seek the resource they're requesting from a different host, all you have to do is supply the address of the VIP you want to bounce them to. The other, more direct fashion is to use the VIP targeting VIP function within LTM to make the destination an internal VIP. This looks a bit different, and behaves a bit different, but the client will never see the redirect, which can be handy at times. I've included Kevin's examples of each option here: when HTTP_REQUEST { if { ...some condition... } { HTTP::redirect "https://somewhere.else.com" } } when HTTP_REQUEST { if { ...some condition... } { HTTP::respond 301 Location "https://somewhere.else.com" } } when HTTP_REQUEST { if { ...some condition... } { virtual internal-vs } } Block SMTP connections based on EHLO https://devcentral.f5.com/s/questions/need-help-blocking-smtp-connections-based-off-ehlo-name Pesky SMTP attackers getting you down? Coming from multiple different IP addresses? Looking for a way to stop them based on their connection strings? Well look no further, Cory's got your back. He shows us a simple way to check the EHLO info in an SMTP handshake to block unwanted bad guys from doing…bad guy things. Simple and clever and useful, very 20LoL-ish. Check it out. when CLIENT_ACCEPTED { TCP::respond "220\r\n" TCP::collect } when CLIENT_DATA { set clientpayload [string tolower[TCP::payload]] if { $clientpayload contains "ehlo abcd-pc" } { reject } } No HTTP Response Fired? https://devcentral.f5.com/s/questions/when-is-http_response-not-fired This one is less a trick in code, but a lesson in understanding how iRules play with other modules loaded on the LTM. A user was having some troubles with APM multi-domain and an iRule they wanted to use that fired on HTTP_RESPONSE. As Kevin so clearly explains, "The HTTP_RESPONSE is triggered for egress HTTP traffic through the box. The logon VIP in an APM multi-domain configuration doesn't trigger the HTTP_RESPONSE event because it handles all responses locally. Your best bet here, unfortunately, is to layer the APM logon VIP behind an LTM VIP that can see the HTTP response traffic from the APM VIP. You'd use a very simple iRule on the LTM VIP". And here is said iRule, for all those that might run into a similar situation. when HTTP_REQUEST { virtual [name of APM VIP] } when HTTP_RESPONSE { HTTP::header insert Strict-Transport-Security "max-age=31708800" }364Views0likes3Comments20 Lines or Less #19
What could you do with your code in 20 Lines or Less? That's the question I ask (almost) 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 has been fantastic here in DCLand. I've been sequestered in a room with the awesome minds of the DevCentral team for most of the week brainstorming, collaborating, sharing, and thinking up generally cool new stuff! It's always a good time when the team gets together and there are almost always some hawesome things that come out of it, so keep an eye open for those. In the meantime there have been a load of cool iRules being written with a couple of prime choices for this week's 20LoL. One was even submitted directly via email, a 20LoL first, which is absolutely killer and I'd love to see more of it, so thanks Aidan, and don't be shy all you iRulers, get your ideas in! Many thanks and much credit to the always amazing hoolio and one of our awesome F5 engineers Aidan for the iRules in this edition. With that, I bring you this week's 20 Lines or Less: Log Every x Seconds There are thousands of reasons to log info in an iRule, but I think this one is built with the concept in mind of using the iRule of a type of advanced warning system. Logging info about things that could potentially cause problems later is great, unless you're flooding your log with that info and causing a problem NOW instead of later. So why not only log every x seconds if that condition is still valid? when RULE_INIT { # Initialize a variable to track the last time a log message was made set ::last_log_timestamp [clock seconds] # Shortest interval (in seconds) to log a message set ::min_log_interval 60 } when CLIENT_ACCEPTED { # Check if there are two or less active members in the default pool if {[active_members [LB::server pool]] < 3 and [expr {[clock seconds] - $::last_log_timestamp}] > $min_log_interval}{ log local0. "[virtual name], [LB::server pool]: [active_members [LB::server pool]] members available!" } } More on obfuscating your server and app type There have been many posts and examples of how to help mask what kind of app server and os you're running. Many of them are listed by hoolio in this post. This is one more great example of trying to mask an app type by getting rid of some key headers, including looping through to remove all the "x-" headers, which is a new take on this concept. Cool stuff. when HTTP_RESPONSE { # Remove server header HTTP::header remove "Server" # Remove Date header HTTP::header remove "Date" # Remove any header which starts with "X-" for {set i 0} {$i < [HTTP::header count]} {incr i} { # Check if the current header name starts with X- if {[string tolower [HTTP::header at $i]] starts_with "x-"}{ # Remove the header HTTP::header remove [HTTP::header at $i] } } } Simulating a WAN environment with iRules Sometimes there's a need to simulate a delay in traffic, as if sending info across a WAN environment. Trouble is, that's actually pretty tough to accomplish without proper WAN simulation gear. Well, here's an iRule that can do just that! It just barely squeaks in under the 20 lines requirement, if you remove the log lines, but I'm showing it here in its full format because I think the logs could be useful. Yet another awesome example of the power of iRules in just 20 Lines or Less. NOTE: This iRule is NOT designed for production use. It is very high load, and will GREATLY slow down traffic on your entire system if applied in a high traffic environment. That is, after all, kind of the point. It is intended for testing use and PoC type deployments in a safe, controlled dev/test environment where no production traffic will be harmed in the wild. Thanks ;) when CLIENT_ACCEPTED { log local0. "Client Packet accepted" TCP::collect } when CLIENT_DATA { log local0. "Generating Client Lag" set y1 [clock clicks -milliseconds] for { set x 0 } { $x < 175000 } { incr x } { #do nothing } set time1 [expr [clock clicks -milliseconds] - $y1] log local0. "Client for loop time is $time1 milliseconds" log local0. "Client packet released" TCP::release TCP::collect } when SERVER_CONNECTED { log local0. "Server Packet accepted" TCP::collect } when SERVER_DATA { log local0. "Generating Server Lag" set j1 [clock clicks -milliseconds] for { set z 0 } { $z < 175000 } { incr z } { #do nothing } set time1 [expr [clock clicks -milliseconds] - $j1] log local0. "Server for loop time is $time1 milliseconds" log local0. "Server packet released" TCP::release TCP::collect } There's your dose of iRules goodness in 20 Lines or Less for this week. Stay tuned for future editions and be sure to get your submissions in if you want to see your iRule featured. Thanks much for reading and as always, all feedback is welcome so don't be shy. #Colin311Views0likes0Comments20 Lines or Less #28
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. Nearing the thirty mark with the 20LoL it occurs to me that I’m having a harder and harder time with something. No, it’s not finding interesting ideas to feature. The community has been absolutely stellar with that part. There are always plenty of iRules for me to grab either directly or with some modification (which is half the fun). No the issue is that I’m having a tough time remembering if I’ve covered a topic too similar to the current one already. Forgive me if I end up double dipping at some point. At the very least it will be a new slant on the idea. I’m pretty sure this week these are all original concepts. I bring to you examples of SSL and Non SSL traffic sharing a vip in harmony, making use of the scan command to dissect URIs, and some more persistence trickery. SSL and plaintext living together http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=61869&view=topic There was a need to serve SSL traffic for all but only a few URIs, and the desire was to use an iRule to do so. Fortunately for the original poster someone was quick to seek out some of hoolio’s earlier work via the search function. In this example you can see how to selectively disable encryption for a particular URI. This could work in the inverse just as easily (selectively enable for only a few secure URIs). when HTTP_REQUEST { # Check if request matches the criteria to disable server-side SSL if { [HTTP::uri] starts_with "/clear"}{ # disable SSL on the serverside context SSL::disable serverside # select the http pool pool http_pool } else { # default is to use server-side SSL and the https pool pool https_pool } } Multiple Persistence timeouts based on URI http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=61948&view=topic In a very cool juggling act, hoolio puts on yet another seminar on how to use iRules to meet your tricky and extremely specific needs. He shows here how you can manage a single type of persistence (source address in this case) with multiple timeouts based on the URI that’s requested. The additional trick here is to have the longer timeout not overwritten by the shorter timeout the next time that user requests a URI not in the “extended timeout” list. I like it. when HTTP_REQUEST { # Check requested path switch -glob [HTTP::path] { "/apps/aml/*" { # Persist client for 10 hours persist source_addr 36000 } default { # Persist client for 1 hour persist source_addr 3600 } } } Scanning URIs http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=61774&view=topic The need from the user was to alter multiple variables in a URI. This was complicated further by the structure of the URI and the type of replacement that needed to be done. Aaron (hoolio) though, swift as ever, managed to whip up a tidy solution to the problem making use of the powerful scan command. This one is definitely cool and shows off this under-used command. when HTTP_REQUEST { log local0. "[IP::client_addr]:[TCP::client_port]: New HTTP request to [HTTP::uri]" if { [HTTP::uri] contains "adserver/impression" }{ log local0. "[IP::client_addr]:[TCP::client_port]: Matched URI check" # Scan the URI looking for the pid, oid and rand values if { [scan [HTTP::uri] {/adserver/impression/pid=%[^/]/oid=%[^/]/rand=%[^/]} pid oid rand] == 3 } { log local0. "[IP::client_addr]:[TCP::client_port]: Scanned three values: pid = $pid, oid = $oid, rand = $rand" HTTP::uri [string map "adserver/impression/pid=$pid/oid=$oid/rand=$rand/?click ad.imp?pid=$pid&oid=$oid&rand=$rand/?pclk" [HTTP::uri]] } } } when HTTP_REQUEST priority 501 { log local0. "[IP::client_addr]:[TCP::client_port]: 501: Updated URI: [HTTP::uri]" } There are your three examples for the week in an aggregate 60 lines or less (see what I did there?). Hopefully you’re continuing to find these interesting to read. I’m definitely still enjoying putting them together and want to give yet another massive thanks to the amazing community as a whole and specifically Hoolio for the continued contributions. #Colin303Views0likes0Comments20 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. #Colin299Views0likes0Comments20 Lines or Less #29
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. 29 editions later and still going strong. The 20LoL is a testament to just how many different things can be done with iRules in just a few lines of code. Just imagine the possibilities if this were the 30LoL. This week I’ve got three more examples, all from the forums. Today we’ll cover dealing with port numbers in HTTP requests, checking pool status from within an iRule, and more fun with nested switching. The community keeps putting out fantastic examples so I just keep on writing about them. Keep it up. Removing HTTP request port numbers http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=62227&view=topic Hoolio came up with a trio if examples of how to deal with port numbers in your HTTP requests. All of them are good, depending on your situation, but I’m only going to highlight one here. Go check out the forum post above to see the other two and get the context of the thread. when HTTP_REQUEST { # Check if Host contains a colon if {[HTTP::host] contains ":"}{ # Redirect client to requested host minus the port and preserve the original URI HTTP::redirect "https://[getfield [HTTP::host] ":" 1][HTTP::uri]" } } Checking pool member status http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=62093&view=topic User cmbhatt, another one of our power-users, came up with a very cool example of using the LB::select command and HTTP::respond to show the status of a selected pool member. It even has a built in meta-refresh so you can continually monitor the status. Pretty neat stuff. when HTTP_REQUEST { if {[HTTP::uri] eq "/status" } { scan [LB::select] %s%s%s%s%d command current_pool command2 current_member current_port eval [LB::select] set response " $current_pool Pool Status - [clock format [clock seconds]]http://[HTTP::host]/status'>" if { [active_members $current_pool] < 1 } { append response "POOL NAME:$current_pool CURRENT MEMBER:$current_member:$current_port STATUS: DOWN " } else { append response "POOL NAME:$current_pool CURRENT MEMBER:$current_member:$current_port STATUS: UP " } } HTTP::respond 200 content $response "Content-Type" "text/html" } More nested switching and pool selection vs. redirection http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&view=topic&postid=62162 This rule stemmed from cmbhatt, once again, then I went in and made some tweaks where I think it made sense, as you can see in the thread. The idea is that the user is looking to do some inspection of first the host, then in some cases, depending on what the host is, the URI as well. Based on what’s found either a load balancing decision is made or a redirect is issued. This is yet another awesome example of how iRules can turn something that would be ridiculously tricky or even impossible elsewhere into something pretty straight-forward. when HTTP_REQUEST { switch [HTTP::host] { "www.mydomain.eu" { switch [HTTP::uri] { "/" { HTTP::respond 301 Location "http://www.mydomain.eu/zz/index.html" } default { pool mydomain_eu_pool } } } "www.mydomain.be" { switch [HTTP::uri] { "/" { HTTP::respond 301 Location "http://www.mydomain.eu/be/zz/index.jsp" } default { pool mydomain_be_pool } } } "www.mydomain.nl" { HTTP::respond 301 Location "http://www.mydomain.eu/nl/zz/index.jsp" } "www.mydomain.fr" - "mydomain.fr" { HTTP::respond 301 Location "http://www.mydomain.eu/fr/zz/index.jsp } "www.mydomain.lu" { HTTP::respond 301 Location "http://www.mydomain.eu/lu/zz" } } } There you have it, three more iRules to get you on your way in less than 21 lines of code. Feel free to submit ideas, suggestions of feedback, as always. #Colin291Views0likes0Comments20 Lines or Less #74: ASP Session Persistence, Radius Auth, and Fancy 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. This week’s examples deal with things ranging from session persistence (And NOT for JSESSION!) to RADIUS authentication and beyond. Ask and the community shall provide, as is so often the case, adn this week was no different. Let’s see what we came up with in this week’s 20LoL: ASPSESSIONID Persistence https://devcentral.f5.com/s/questions/irule-required-to-persist-client-connections-that-get-proxied-from-a-single-client We’ve seen the JSESSIONID version enough times that it should be committed nearly to memory by now, I would think. This take, however, is a bit newer. It is of course the exact same concept, but rather than dealing with Java, user Nathan Andrews was looking for a way to persist data from Blackberries accessing an application. Source address wasn’t working since they were bouncing through a proxy inherent in such deployments. Fortunately he was able to identify a common attribute and persist based off of that. Enter ASPSESSIONID and handy, likely familiar chunk of code. when HTTP_RESPONSE { if { [HTTP::cookie exists "ASPSESSIONID"] } { persist add uie [HTTP::cookie "ASPSESSIONID"] } } when HTTP_REQUEST { if { [HTTP::cookie exists "ASPSESSIONID"] } { persist uie [HTTP::cookie "ASPSESSIONID"] } } Radius and WebApp Authentication https://devcentral.f5.com/s/questions/radius-and-webapp-authentication DC user Don Benson was looking to collect three bits of data to perform Radius Auth for a web app, using their BIG-IP to collect and pass through the required data. They were looking for username, password and a hardware token. The trouble in their testing came when the web app was expecting a POST and they were sending GETs (not sure quite what they were doing since they didn’t post their original iRule). Fortunately another helpful DC member chimed in with a suggestion that, if my math is correct…carry the one…should get them where they need to go. when ACCESS_POLICY_COMPLETED { set username [ACCESS::session data get "session.logon.last.username"] set content " < script type=text/javascript language=javascript> \ function s(){ document.f.submit(); } \ \ " ACCESS::respond 200 content $content } URI Queries and Fancy Footwork https://devcentral.f5.com/s/questions/how-to-destroy-and-replace-a-uri-query-value- While the original thread’s title was about destroying and replacing URIs, I thought this more appropriate. Nitass steps in with some handy dandy URI query shaping logic to make what sounded like a somewhat complex set of deliverables a snap. Looking to replace a query parameter with a specific value, or ensure said query param is in place if its missing? Well here you go. when HTTP_REQUEST { if { [HTTP::host] eq "red.x.com" } { set q [URI::query [HTTP::uri] code] if { $q ne "" } { HTTP::uri [string map "$q red" [HTTP::uri]] } else { HTTP::uri "[HTTP::uri]&code=red" } } }282Views0likes0Comments20 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. #Colin281Views0likes0Comments20 Lines or Less #70
What could you do with your code in 20 Lines or Less? That's the question we like to ask from, for, and of (feel free to insert your favorite preposition here) the DevCentral community, and every time we do, we go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. Thus was born the 20LoL (20 Lines or Less) series many moons ago. Over the years we've highlighted hundreds of iRules examples, all of which were doing downright cool things in less than 21 lines of code. In this edition, I step in for Colin the Magnificent to bring you some iRules goodness in short form. New capabilities and a few cool iRules await you, so let's get going! Make Me a Sandwich! iRules Style... Flying well under the radar in the 11.4.1 TMOS release is a new iRules-capable layer in the BIG-IP Advance Firewall Manager module. With the introduction of the FLOW_INIT event and the ACL::action command, you can now sandwich some iRules logic goodness in between the packet filters at the front door and the beginning of the BIG-IP AFM processing. This gives you the capabilities of overriding ACL action, controlling bandwidth and QoS on client and/or server flows, and routing/blocking traffic. Sweet! New toys! Anyway, this first example is not so much eye-opening in complexity, just an example of reaching a new layer in the stack with which to control. when FLOW_INIT { set ipaddr [IP::client_addr] set locale [whereis $ipaddr country] log local0. "IP Address/Counry $ipaddr/$locale" switch $locale { "US" - "CA" { return } "GB" { ACL::action drop } default { ACL::action reset } } } It's Not Me, It's You(r Old Domain) Redirection is well covered in Q&A, with just a thousand (give or take a few hundred) or so different angles on the topic. Community member Martin Thomas asked how to send a permanent redirection from the requested old domain to a new domain, but keeping parts of it. That's pretty easy to manually, but if you have a lot of domains to do this for, it becomes not only tedious in writing the iRule, but, if using if/else statements, could be inefficient as well. Thankfully, IheartF5 came to the rescue, with not one, but yes, you read this correctly, two fine solutions! Solution 1 This solution uses the getfield command, which is a custom iRules command that essentially performs an lindex-split operation from the native Tcl library. when HTTP_REQUEST { if {[HTTP::host] ends_with ".olddomain.com"} { HTTP::respond 301 Location "https://[getfield [HTTP::host] . 1].newdomain.com[HTTP::uri]" } } Solution 2 This other solution is a little more efficient that then other, using the old faithful string map command. Nice work, IheartF5! when HTTP_REQUEST { if {[HTTP::host] ends_with ".olddomain.com"} { HTTP::respond 301 Location "https://[string map {olddomain newdomain} [HTTP::host]][HTTP::uri]" } } Me Want Cookie...Not So Much Winning this blog's "shortest iRule of the post" contest is also from IheartF5, answering a question on how to expire a cookie from member Abhishek. Short. Sweet. Powerful. I've used this one myself from time to time. Note that the path information should probably be adjusted accordingly to your app's needs. when HTTP_RESPONSE { HTTP::header insert Set-Cookie "mycookie=xx; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; HttpOnly" } Technorati Tags: iRules,20 lines or less,20LoL275Views0likes2Comments20 Lines or Less #30
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. Well we made it to 30 editions of the 20LoL. Soon we’ll break 100 iRule examples that are under 21 lines of code each. Pretty neat stuff, if you ask me. This week is the hoolio show, it seems. The guy is just a monster in the forums, what can I say? I sure am glad he’s on our side. I’ve got three examples that I randomly pulled from the forums because I thought they were cool. Only later did I realize that he had penned them all. So big thanks yet again to Aaron and all his hard work to better the community. Pre-loaded searches based on host name http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=86016&view=topic This cool little example is a neat spin on a simple HTTP redirect. The basic idea is to redirect to a given search site and set the search parameter to be the original host name of the request. So I could request bobschickenshack.com and be redirected to a search for bobschickenshack on the search page of my choosing. Very cool idea, and darn easy to implement. when HTTP_REQUEST { # Rewrite the host header to www.yahoo.com and the # uri to /search?q=$host where $host is the originally requested hostname HTTP::header replace "www.yahoo.com" HTTP::uri "/search?q=[HTTP::host]" } More fun with nested switch http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=85807&view=topic I know we’ve covered switch before, but this is yet another good use of it and I really like the idea of selecting snatpools based on which server the request is going to end up going to. I trimmed this one down a little but only by removing a few of the possible snatpool options, all logic is the same, even though it’s just an excerpt of the overall solution provided. when LB_SELECTED { switch [LB::server addr] { 222.35.42.126 { switch [IP::client_addr] { 192.168.3.11 { snatpool snat_crt_test2 } default { snatpool snat_crt_pool } } } 221.218.248.155 { switch [IP::client_addr] { 192.168.3.11 { snatpool snat_uni_test2 } default { snatpool snat_uni_pool } } } default { snat automap } } } Updating referrers http://devcentral.f5.com/s/Default.aspx?tabid=53&forumid=5&postid=85807&view=topic Hoolio does a good job of not only pointing out the inherent problem with trying to replace referrer headers with hostnames from requests, but giving an option that works as desired even if it’s a little bit different direction than the OP was headed. This is a good example of in-line string replacement with string map, too, which is an often under used command that’s worth a look. when HTTP_REQUEST { log local0. "[IP::client_addr]:[TCP::client_port]: New [HTTP::method] request to [HTTP::host][HTTP::uri]\ with Referer [HTTP::header Referer]" if {[HTTP::header exists "MyHeader"]} { log local0. "[IP::client_addr]:[TCP::client_port]: Updating Referer to\ [string map -nocase {http:// https://} [HTTP::header Referer]" HTTP::header replace Referer "[string map -nocase {http:// https://} [HTTP::header Referer]" } } when HTTP_REQUEST priority 501 { log local0. "[IP::client_addr]:[TCP::client_port] (501): Current Referer [HTTP::header Referer]" } There you have it, 3 more iRules to show off just how much you can do in only 20 lines of code. Next time we’ll break past the 100 examples mark. See ya then. #Colin265Views0likes0Comments20 Lines or Less #36 – Strip, parse, & change
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 announcement of the BIG-IP LTM VE this week, the iRules world just got a little more interesting. Between the new commands and features that have come out in the past several months, and now the ability to build and test iRules from your laptop, without having to connect to the internet/network at all, the possibilities just keep expanding. I’m excited to see what kinds of things people come up with and the scenarios I hear about with VEs running all sorts of wacky iRules that people didn’t dare try out on their systems before. Amidst the amazing news of the BIG-IP LTM VE release and the ensuing rush of content, comments and questions surrounding it, the iRules world moves along just as it does every week. As such, I’ve got some more cool examples of iRules goodness exemplifying the brevity I’ve come to seek out. Strip HTTP Server Looking for a simple way to remove all headers containing a given string? Perhaps you don’t want to use the sanitize command because you’re leaving in more headers than you’re taking out, but you want to remove some specific headers? Well here you go. A simple little loop that’ll go through all your headers and remove those that match whatever criteria you lay out. In this case it’s removing all headers that begin with x-. when HTTP_RESPONSE { # Remove all instances of the Server header HTTP::header remove Server # Remove all headers starting with x- foreach header_name [HTTP::header names] { if {[string match -nocase x-* $header_name]}{ HTTP::header remove $header_name } } } Change Content Disposition I’m pretty certain I’ve posted a way to do this here before, or maybe that was a tech tip..they all blur together. This is a very quick, elegant way to do so however, so I wanted to share (even if it’s sharing the same concept again). when HTTP_REQUEST { set querystring URI::query } when HTTP_RESPONSE { if { $querystring contains "attachment=1" } { HTTP::header replace Content-Disposition [string map -nocase "inline attachment" [HTTP::header Content-Disposition]] } } Particularly Tricky Path Parsing Someone was looking to parse the first two letters of the HTTP path, and came up with a very neat way of doing just that. They’re performing structured matches based on character sets in a glob style match with switch. Very inventive and it looks quite efficient & functional. Nicely played. when HTTP_REQUEST { # Parse the first then second character in the path switch -glob [string tolower [HTTP::path]] { "/a[a-l]*" { pool reward-uat5.123.com_AA2AL } "/a[m-z]*" - "/b[a-l]*" { pool reward-uat5.123.com_AM2BL } "/b[m-z]*" - "/c[a-d]*" { pool reward-uat5.123.com_BM2CD } default { # Requested URI was a leading forward slash only pool reward-uat5.123.com_AA2AL } } } There’s your 20LoL for the week. Thanks for keeping up with the awesome examples guys. See you next week for three more. #Colin262Views0likes0Comments