20 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.
#Colin