Home


Hot Topics


Download


Tutorials


Multimedia


Community

Login | Register




1st Place Partner Winner
iRule Developer:
Sake Blok

F5 Partner:
ion-ip

iRule Name:
"iRule_Persist_On_HTTP_Data"

iRule Description:
"This iRule provides persistency based on information in the data-part of the http requests and http responses. It picks up a (custom) tag from the http-response-data to use for persistency. When another request contains this tag in the http-request-data, the request will be sent to the node that first had this tag in it's response."

Key Challenges:
"In a SOAP-based authentication-sceme all requests were spread across a pool of authentication-servers. These servers authenticated the requests by LDAP in the backend and cached the result locally for optimalisation. However, since the requests were loadbalanced to the whole pool, every authentication-server was building a cache for all session-id's. This did not scale well and demanded the use of heavier servers to be able to keep up the work. This iRule is a simplified version of the one that actually runs in production."

Alternatives:
"An alternative was to replace the servers by bigger ones."

Reduced Costs:
"This solution did save a lot of money for the end-customer. I do not have an estimate on the amount though."

How it works:
"The iRule collects the data-part from a http-request. It then parses this data to see whether a session-id-tag is present. If it is present, it will look up the session-id in the tag in the persistency-table. It then forwards the request to the server that originally created this session-id. If the session-id-tag is not present, a flag will be set to search for a new session-id in the http-response. If a session-id-tag is found in the http-response, then a new session-id will be added to the persistency-table that links the session-id to the server that created the session-id."

Judge Comments:
- "High business value." , Zeus Kerravala

- "Persistence is always a tricky issue. In a SOAP/XML and Web services world, it can be a significant challenge. This rule does a nice job of not only addressing the challenge in one centralized location, it does it elegantly. Not only does it reduce management complexity, it also reduces captical expense costs which is a nice bonus!" , Jeff Browning

- "I really like the way logging is utilized...only when it's necessary, and turned on/off by a single variable, very elegant! The extent to which traffic can be persisted is really shown off here, nice work!" , Jason Rahm

- "This is one of the more sophisticated iRules, and shows a subtle understanding of HTTP." , Jason Bloomberg
- "Very nice. Persistence seems to get re-hashed constantly, and this is one more cool permutation." , Colin Walker

- "I like the extensive conditional debugging. Debugging is one of the biggest issues for new iRule writers and this one shows how to build multiple levels of debugging and turn them on or off with a configuration variable. Plus, any iRule that reduces the need for more servers is good in my book." , Joe Pruitt



when RULE_INIT {
# Debug off (0), Errors-only(1), On(2) or Verbose(3)
set ::debug 3
}

when CLIENT_ACCEPTED {
if { $::debug>=1 } { set cip "[IP::client_addr]:[TCP::client_port]" }
}

when HTTP_REQUEST {
# Do not search the http-response for a new session-id unless a session-id tag was not found in the http-request
set add_persist 0

# look for the content-length header, we need to parse the http-request data
if { [HTTP::header exists "Content-Length"] } {
if { $::debug>=3 } { log local0. "$cip : Collecting [HTTP::header "Content-Length"] bytes of http-request-data" }
# Now collect the HTTP-payload and process it in the http-request-data event
HTTP::collect [HTTP::header "Content-Length"]
} else {
# We should never enter this block!
if { $::debug>=2 } { log local0. "$cip : No Content-Length header in http-request" }
}
}

when HTTP_REQUEST_DATA {
# Look for session-id tag
set sid [findstr [HTTP::payload] "" 9 ""]
if { $sid eq "" } {
# No session-id-tag found, we need to parse the http-response-data for a new session-id
if { $::debug>=3 } { log local0. "$cip : Session-id-tag was not found in http-request!" }
set add_persist 1
} else {
if { $::debug>=2 } {
if { $::debug>=3 } { log local0. "$cip : Found session-id $sid in http-request" }
set p [persist lookup uie $sid ]
if { $p ne ""} {
log local0. "$cip : Sid $sid found in persistency-table ([lindex $p 0] [lindex $p 1] [lindex $p 2])"
} else {
log local0. "$cip : Sid $sid has timed out, adding again!"
}
}
persist uie $sid
}

# Proceed with normal http-parsing
HTTP::release
}

when HTTP_RESPONSE {
# Only parse response if there was no session-id in the request
if { $add_persist == 1 } {
if { [HTTP::header exists "Content-Length"] } {
set len [HTTP::header "Content-Length"]
} else {
set len 4294967295
}
if { $::debug>=3 } { log local0. "$cip : Collecting $len bytes of http-response-data" }
HTTP::collect $len
} else {
if { $::debug>=3 } { log local0. "$cip : No need to parse http-response" }
}
}

when HTTP_RESPONSE_DATA {
# Only parse response if there was no session-id in the request
if { $add_persist == 1 } {
if { $::debug>=3 } { log local0. "$cip : Searching for session-id-tag in http-response-data" }
set sid [findstr [HTTP::payload] "" 9 ""]
if { $sid ne "" } {
if { $::debug>=3 } { log local0. "$cip : Found session-id $sid in http-response" }
set p [persist lookup uie $sid ]
if { $p eq ""} {
persist add uie $sid
if { $::debug>=2 } { log local0. "$cip : Sid $sid added to persistency-table" }
} else {
if { $::debug>=1 } { log local0. "$cip : Sid $sid already in persistency-table ([lindex $p 0] [lindex $p 1] [lindex $p 2])" }
}
} else {
if { $::debug>=2 } { log local0. "$cip : Session-id-tag was not found in http-request nor http-response!" }
}
} else {
if { $::debug>=3 } { log local0. "$cip : No need to parse http-repsonse-data" }
}
HTTP::release
}

when LB_FAILED {
if { $::debug>=1 } { log local0. "$cip : LB failed for sid $sid ([lindex $p 0] [lindex $p 1] [lindex $p 2])" }
# Delete old persistency-entry, otherwise reselect will return the node from the persistency-table again
persist delete uie $sid
LB::reselect pool [lindex $p 0]
}

2nd Place Partner Winner
iRule Developer:
Nuno Paulino

F5 Partner:
Telindus-Portugal

iRule Name:
w3c_iRule

iRule Description:
"My iRules implements web logs in W3C format with host header validation and interaction with ASM."

Key Challenges:
"Challenge I: W3C Log Implementation. Challenge II: Using a floating point value with 3 decimals units."

Alternatives:
"There was other alternatives."

Reduced Costs:
"This customer ... had a legacy solution using "App Shield" which implements logs in W3C format and this was a requisite for the new solution. In this project were involved 3 BigIp 6400 and one BigIP 1500 plus ASM..."

How it works:
"Some information is gathered after client request and some information is gathered after server response. In this system i also had implemented ASM so there are some tricks in information to be correct in the final result. The host_headers_class contains the allowed host headers to the website... I had to treat a floating point as a string to implement a conversion from milliseconds to seconds."

Judge Comments:
- "I always give a high cool factor when someone finds a unique solution to an issue in one of our products (support for floating point numbers in iRules). The support for w3c based logging on BIG-IP has been asked for on and off for years. This could be a good value to the community." , Joe Pruitt

- "Great business value, support function x or lose a customer... Nice use of the string command to workaround the TCL bug." , Jason Rahm




rule w3c_iRule {

when HTTP_REQUEST {

# Information Gathering

set time_client_request [clock seconds]
set clicks_client_request [clock clicks -milliseconds]
set date_time_request [clock format $time_client_request -format {%Y-%m-%d %H:%M:%S} ]

set c_ip [IP::client_addr]
set cs_username [HTTP::username]
if {$cs_username eq ""} {
set cs_username "-"
}

set cs_uri_stem [HTTP::host][HTTP::uri]
set cs_method [HTTP::method]

set cs_uri_query [HTTP::query]
if {$cs_uri_query eq ""} {
set cs_uri_query "-"
}

set cs_bytes [HTTP::header Content-Length]
if {$cs_bytes eq ""} {
set cs_bytes "-"
}

set cs_UserAgent [string map {" " "+"} [HTTP::header "User-Agent"]]

set cs_Referer [HTTP::header "Referer"]
if {$cs_Referer eq ""} {
set cs_Referer "-"
}

set s_ip [IP::local_addr]
set s_port [TCP::local_port]
set host [HTTP::host]

if {[matchclass $host equals $::host_headers_class]} {
pool MYPOOL
} else {
set :ASM_DISABLE 1
discard
}

}

when HTTP_RESPONSE {

# Information Gathering

set clicks_server_response [clock clicks -milliseconds]
set sc_status [HTTP::status]

set sc_bytes [HTTP::header Content-Length]
if {$sc_bytes eq ""} {
set sc_bytes "-"
}

# Function due to TCL Bug with floating point values

set time_taken [expr $clicks_server_response - $clicks_client_request ]
if {$time_taken < 10} {
set final_time_taken [string range "0.00$time_taken" 0 4]
} elseif { $time_taken < 100 } {
set final_time_taken [string range "0.0$time_taken" 0 4]
} elseif { $time_taken < 1000} {
set final_time_taken [string range "0.$time_taken" 0 4]
} else {
set final_time_taken "[string index $time_taken 0].[string range $time_taken 1 3 ]"
}

# Prepare string for logging

set log_str "$date_time_request $c_ip $cs_username $s_ip $s_port $cs_method $cs_uri_stem $cs_uri_query $sc_status $sc_bytes $cs_bytes $final_time_taken $cs_UserAgent $cs_Referer"

# write to syslog
log local2.info $log_str

}
iRule Developer:
Nuno Paulino

F5 Partner:
Telindus-Portugal

iRule Name:
w3c_iRule

iRule Description:
"My iRules implements web logs in W3C format with host header validation and interaction with ASM."

Key Challenges:
"Challenge I: W3C Log Implementation. Challenge II: Using a floating point value with 3 decimals units."

Alternatives:
"There was other alternatives."

Reduced Costs:
"This customer ... had a legacy solution using "App Shield" which implements logs in W3C format and this was a requisite for the new solution. In this project were involved 3 BigIp 6400 and one BigIP 1500 plus ASM..."

How it works:
"Some information is gathered after client request and some information is gathered after server response. In this system i also had implemented ASM so there are some tricks in information to be correct in the final result. The host_headers_class contains the allowed host headers to the website... I had to treat a floating point as a string to implement a conversion from milliseconds to seconds."

Judge Comments:
- "I always give a high cool factor when someone finds a unique solution to an issue in one of our products (support for floating point numbers in iRules). The support for w3c based logging on BIG-IP has been asked for on and off for years. This could be a good value to the community." , Joe Pruitt

- "Great business value, support function x or lose a customer... Nice use of the string command to workaround the TCL bug." , Jason Rahm




rule w3c_iRule {

when HTTP_REQUEST {

# Information Gathering

set time_client_request [clock seconds]
set clicks_client_request [clock clicks -milliseconds]
set date_time_request [clock format $time_client_request -format {%Y-%m-%d %H:%M:%S} ]

set c_ip [IP::client_addr]
set cs_username [HTTP::username]
if {$cs_username eq ""} {
set cs_username "-"
}

set cs_uri_stem [HTTP::host][HTTP::uri]
set cs_method [HTTP::method]

set cs_uri_query [HTTP::query]
if {$cs_uri_query eq ""} {
set cs_uri_query "-"
}

set cs_bytes [HTTP::header Content-Length]
if {$cs_bytes eq ""} {
set cs_bytes "-"
}

set cs_UserAgent [string map {" " "+"} [HTTP::header "User-Agent"]]

set cs_Referer [HTTP::header "Referer"]
if {$cs_Referer eq ""} {
set cs_Referer "-"
}

set s_ip [IP::local_addr]
set s_port [TCP::local_port]
set host [HTTP::host]

if {[matchclass $host equals $::host_headers_class]} {
pool MYPOOL
} else {
set :ASM_DISABLE 1
discard
}

}

when HTTP_RESPONSE {

# Information Gathering

set clicks_server_response [clock clicks -milliseconds]
set sc_status [HTTP::status]

set sc_bytes [HTTP::header Content-Length]
if {$sc_bytes eq ""} {
set sc_bytes "-"
}

# Function due to TCL Bug with floating point values

set time_taken [expr $clicks_server_response - $clicks_client_request ]
if {$time_taken < 10} {
set final_time_taken [string range "0.00$time_taken" 0 4]
} elseif { $time_taken < 100 } {
set final_time_taken [string range "0.0$time_taken" 0 4]
} elseif { $time_taken < 1000} {
set final_time_taken [string range "0.$time_taken" 0 4]
} else {
set final_time_taken "[string index $time_taken 0].[string range $time_taken 1 3 ]"
}

# Prepare string for logging

set log_str "$date_time_request $c_ip $cs_username $s_ip $s_port $cs_method $cs_uri_stem $cs_uri_query $sc_status $sc_bytes $cs_bytes $final_time_taken $cs_UserAgent $cs_Referer"

# write to syslog
log local2.info $log_str

}

3rd Place Partner Winner
iRule Developer:
Eduardo Saito

F5 Partner:
Assistec Integracao

iRule Name:
irule_limit_num_connections_googlebot

iRule Description:
"This iRule will limit the number of simultaneous connections to the Virtual Server that GoogleBot can make. This will prevent GoogleBot from getting all server's resources."

Key Challenges:
"Prevent GoogleBot from getting all server's resources."

Alternatives:
"Before BIG-IP implementation and with LVS, servers actually stop responding."

Reduced Costs:
"By not taking the server down it save the client's image to the public. Users visiting the website have more performance since there's more server up to serve. This effort is hard to measure in monetary units."

How it works:
"This iRule count the number of connections that come from the same source IP and has googlebot as the User-Agent. There's a 10 simultaneous connections limit per source address."

Judge Comments:
- "Although there are ways to add in server maps to stop googlebot from slamming your servers, this is a way to offload that config and block the requests before getting to the servers. This has many applications with regards to limiting connections rates for abusive clients." , Joe Pruitt

"This is a slick way to ensure that the right users get the best performance which I really like. I could also see this ported to a number of other scenarios to keep crawlers and the like from stealing server cycles. Cool on it's own, this is a great foundation for an enhanced iRule or even dealing with different types of source IPs." , Jeff Browning

"This could be extneded to many other web servers." , Zeus Kerravala

"... googlebot... can certainly put additional strain on [servers] if you have many sites served off of one box all being crawled simultaneously. This is a nice workaround." , Colin Walker



when RULE_INIT {
array set ::active_clients { }
}

when CLIENT_ACCEPTED {
switch -glob [string tolower [HTTP::header "User-Agent"]] {
"*googlebot*" {
set client_ip [IP::remote_addr]
if { [info exists ::active_clients($client_ip)] } {
if {$::active_clients($client_ip) > 10 } {
reject
log local0. "Reject GOOGLEBOT IP $client_ip ($::active_clients($client_ip))"
return
} else {
incr ::active_clients($client_ip)
}
} else {
set ::active_clients($client_ip) 1
}
}
}
}

when CLIENT_CLOSED {
switch -glob [string tolower [HTTP::header "User-Agent"]] {
"*googlebot*" {
set client_ip [IP::remote_addr]
if { [info exists ::active_clients($client_ip)] } {
incr ::active_clients($client_ip) -1
if { $::active_clients($client_ip) <= 0 } {
unset ::active_clients($client_ip)
}
}
}
}
}
iRule Developer:
Eduardo Saito

F5 Partner:
Assistec Integracao

iRule Name:
irule_limit_num_connections_googlebot

iRule Description:
"This iRule will limit the number of simultaneous connections to the Virtual Server that GoogleBot can make. This will prevent GoogleBot from getting all server's resources."

Key Challenges:
"Prevent GoogleBot from getting all server's resources."

Alternatives:
"Before BIG-IP implementation and with LVS, servers actually stop responding."

Reduced Costs:
"By not taking the server down it save the client's image to the public. Users visiting the website have more performance since there's more server up to serve. This effort is hard to measure in monetary units."

How it works:
"This iRule count the number of connections that come from the same source IP and has googlebot as the User-Agent. There's a 10 simultaneous connections limit per source address."

Judge Comments:
- "Although there are ways to add in server maps to stop googlebot from slamming your servers, this is a way to offload that config and block the requests before getting to the servers. This has many applications with regards to limiting connections rates for abusive clients." , Joe Pruitt

"This is a slick way to ensure that the right users get the best performance which I really like. I could also see this ported to a number of other scenarios to keep crawlers and the like from stealing server cycles. Cool on it's own, this is a great foundation for an enhanced iRule or even dealing with different types of source IPs." , Jeff Browning

"This could be extneded to many other web servers." , Zeus Kerravala

"... googlebot... can certainly put additional strain on [servers] if you have many sites served off of one box all being crawled simultaneously. This is a nice workaround." , Colin Walker



when RULE_INIT {
array set ::active_clients { }
}

when CLIENT_ACCEPTED {
switch -glob [string tolower [HTTP::header "User-Agent"]] {
"*googlebot*" {
set client_ip [IP::remote_addr]
if { [info exists ::active_clients($client_ip)] } {
if {$::active_clients($client_ip) > 10 } {
reject
log local0. "Reject GOOGLEBOT IP $client_ip ($::active_clients($client_ip))"
return
} else {
incr ::active_clients($client_ip)
}
} else {
set ::active_clients($client_ip) 1
}
}
}
}

when CLIENT_CLOSED {
switch -glob [string tolower [HTTP::header "User-Agent"]] {
"*googlebot*" {
set client_ip [IP::remote_addr]
if { [info exists ::active_clients($client_ip)] } {
incr ::active_clients($client_ip) -1
if { $::active_clients($client_ip) <= 0 } {
unset ::active_clients($client_ip)
}
}
}
}
}

DC4
ASM       Best Practices       BIG-IP       cacti       class       cookie       data group       findclass       findstr       FirePass       foreach http_request       gtm       http redirect       HTTP::header       HTTP::uri       https       https redirect       iControl       irule       iRule Editor       iRules       LB_FAILED       ldap       log       matchclass       monitor       oneconnect       persist       persistence       pool       proxy       proxypass       radius       redirect       SNAT       snmp       SSL       switch       syslog       tcpdump       vmware       wiki       X-Forwarded-For