Forum Discussion
Colin_Walker_12
Apr 08, 2009Historic F5 Account
v.10 Command Interoperability
While performing internal testing on some advanced iRules on the newly released v10 platform, we discovered a couple possible scenarios that users should be aware of. Making use of certain commands: (session, persist , after) inside one of a few specific constructs: (switch, foreach, eval, catch) can result in an error condition, causing serious repercussions to the performance and stability of your device. Because of this, they need to be avoided when upgrading to or installing v10, at least temporarily. It's important to note here that while these temporary workarounds are important for immediate upgrades to v10, our rock-star PD crew is well aware of this and will have a fix out very soon.
These situations in code are thankfully relatively painless to work around, in many cases. To help facilitate this, we've distilled down a couple of simple, possible scenarios that you might run into, in hopes of showing you an alternate method of achieving the same functionality with your code. These examples are straight-forward, but the concepts carry over into more complex iRules. Understand that this is in no way a comprehensive list of examples, just a visual guide to show what we're talking about, in code.
First, here's an example of a session lookup inside of a switch statement. This should work properly in v9.x, and variations on this type of structure are quite possible.
when HTTP_REQUEST {
session add uie 12345 "this is a session" 200
switch [HTTP::path] {
"/foo.html" {
session lookup uie 12345
log local0. "done with all session requests"
}
default {
log local0. "default path, no request made"
}
}
}
Please note that the above code will not function in v10, and it will need to be re-written. A possible solution for how to do so is to make use of if-else, instead of switch, if you're going to be using one of the commands listed above (session, persist , after). The same logic without the switch statement would look something like this in v10.
when HTTP_REQUEST {
session add uie 12345 "this is a session" 200
if { [HTTP::path] eq "/foo.html" } {
session lookup uie 12345
log local0. "done with all session requests"
} else {
log local0. "default path, no request made"
}
}
You'll notice that we're achieving the same goal but without causing the combination of commands that were discovered to be a problem, at least temporarily. This allows your iRules to continue giving you the functionality you need while this issue is resolved.
Next is an example of a persist lookup being executed from within a foreach loop, working in v9.x.
when HTTP_REQUEST {
foreach client $::myIPs {
set val [persist lookup uie "$client any pool"]
if {[string length $val] < 7 } {
persist add uie $client
}
}
}
Again, this combination of commands should be temporarily avoided in v10. Instead, the below example is a possible solution that not only achieves the same functionality, but shows off some of the features of the amazingly powerful new class command. This code isn't the simplest way to produce this result, but I wanted to take the opportunity to showcase the awesome new command and some of the things that it can do.
when HTTP_REQUEST {
set n [class size myIPs]
set id [class startsearch myIPs]
for {set x 0} {$x < $n} {incr x} {
set client [class nextelement -value myIPs $id]
set val [persist lookup uie $client]
if {[string length $val] < 7 } {
persist add uie $client
}
}
class donesearch myIPs $id
}
So there are a couple of examples of what we were seeing. I know that having to modify your code isn't always ideal, hopefully this has helped to clarify a couple of ways around the problem that was uncovered. The good part of this though, is that our amazing PD team is already completely on top of this and are already working towards getting this resolved in the very near future. I don't have an exact date for you, but I can assure you it's a top priority, and that I expect to see something very soon. Until then, hopefully this helps get you pointed in the right direction.
11 Replies
- hoolio
Cirrostratus
Hi Colin,
Is there a CR for this issue? It seems like a fairly significant set of limitations. Are there plans to address this in a hotfix?
(Edit: It looks like it's CR101506)
Thanks,
Aaron - spark_86682Historic F5 Account
Is there a CR for this issue? (Edit: It looks like it's CR101506)
No, CR101506 is a specific limitation with the new SSL data events. This issue is CR118979, and can be found in the v10.0.0 release notes.Are there plans to address this in a hotfix?
At this time, we are still working on fixing the issue in an upcoming release (expected to be relatively soon). Once we have a complete fix, we could evaluate if it is possible to deliver in a hotfix. - Colin_Walker_12Historic F5 AccountThis has been fixed in v10.0.1.
Colin - Sake_Blok
Nimbostratus
Posted By Colin Walker on 06/04/2009 9:33 AM
This has been fixed in v10.0.1.
Colin
I'm running into a similar issue when upgrading a box to v10.1.0 with an iRule that uses the session table, but none of the listed commands are used. The following is the skeleton of the iRule that I use:when CLIENTSSL_CLIENTCERT { set sslcert [SSL::cert 0] ... log local0. "[IP::client_addr], [X509::subject $sslcert] -> [IP::local_addr]" if { ... } { log local0. "...error..." reject } else { set ssl_cache_timeout [PROFILE::clientssl "cache_timeout"] session add ssl [SSL::sessionid] $sslcert $ssl_cache_timeout } } when HTTP_REQUEST { set sslcert [session lookup ssl [SSL::sessionid]] if { $sslcert ne "" } { HTTP::header remove X-Client-Cert HTTP::header insert X-Client-Cert [X509::whole $sslcert] } else { log local0. "No client certificate in the session table for [IP::client_addr] (SSLid: [SSL::sessionid])" } }
There is proper logging of the first log command, no error logging of the second log command so the certificate gets added to the session DB. As there is no logging that there is no Client Certificate in the session table (hence $sslcert is not ""), however, the command "[X509::whole $sslcert]" results in a TCL error.
Is this a known issue with iRules in v10.1.0? Is there a workaround?
Cheers,
Sake - hoolio
Cirrostratus
Hi Sake,
What's the TCL error from [X509::whole $sslcert]?
As a guess, can you try URL or base64 encoding the cert before adding it to the session table:
session add ssl [SSL::sessionid] [b64encode $sslcert] $ssl_cache_timeout
and then log the session value in HTTP_REQUEST?
Thanks,
Aaron - Rodney_80133
Nimbostratus
If I may barge in (I asked for Sake's help with this particular problem), this is the TCL error:
Mar 2 17:51:30 local/tmm err tmm[4873]: 01220001:3: TCL error: rule_client_incoming - while executing "X509::whole $sslcert"
I've added both suggestions, will need to wait for user-traffic...
Thanks! - Rodney_80133
Nimbostratus
I just ran into something else, switching a profile seemed to work fine in 9.4.5 but it no longer seems to work in 10.1.0, llike in this example:
http://devcentral.f5.com/wiki/default.aspx/iRules/SSL__profile.html
Default SSL-profile on virtual-server is 'server_ssl_test'. I want to select a server_ssl profile based on the source:
when SERVER_CONNECTED {
as simple as possible, no switch, just trying to set a different profile:
SSL::profile server_ssl_acc
log local0.debug "Found: $source. [PROFILE::serverssl name]"
}
Apr 1 15:57:33 local/tmm debug tmm[4955]: Rule rule_outgoing : Found: 192.168.26.90. server_ssl_test - hoolio
Cirrostratus
Hi Rodney,
Is that with the full or virtual LTM edition?
Thanks, Aaron - mrintzler
Nimbostratus
I am running into an iRule compatibility issue between 9.4.5/10.0.1HF3 and 10.1.0. I have an array that I am running through with a foreach loop. I'm trying to set two variables to the array index and element for each array row. However, both variables are being set to the index for the first run through, and then the element on the second iteration, etc. It worked fine under 9.4.5 and 10.0.1. Here's the applicable code from the iRule:
Original concept by Deb Allen, F5 Networks
April 2006
when RULE_INIT {
set ::maxRate 3
set ::windowSecs 10
set ::refreshint 1000
set ::totalBMS 0
init array if non-existent
array set ::getHistory ""
wipe array if already existent
log local0. "Array initialized"
array unset ::getHistory
}
when HTTP_REQUEST {
if { [HTTP::method] eq "GET" } {
if { not ([HTTP::cookie exists "_sn"]) } {
Extract clients IP address
set client_ip [IP::remote_addr]
initialize the myMaxRate with global setting
set myMaxRate $::maxRate
set currentTime [clock seconds]
we need to count requests in last $windowSecs seconds, so mark the cutoff time
set windowStart [expr {$currentTime - $::windowSecs}]
if { $::totalBMS > $::refreshint } {
array unset ::getHistory
log local0. "$::refreshint hits reached. Resetting array"
set ::totalBMS 0
}
find GETs for this userID
set getCount 0
count GETs within the window, delete those that are older
foreach { sbrequestID requestTime } [array get ::getHistory ${client_ip}*] {
log local0. "Checking $sbrequestID for time $requestTime"
count GETs with start time > $windowStart, delete the rest
if { $requestTime > $windowStart } {
incr getCount 1
} else {
unset ::getHistory($sbrequestID)
}
}
if { $getCount < $myMaxRate } {
Allow request and add new record to array w/myUserID.rand + currentTime
set sbrequestID "${client_ip}_[expr { int(10000000 * rand()) }]"
log local0. "Setting getHistory with $sbrequestID and $currentTime"
set ::getHistory($sbrequestID) $currentTime
log local0. "Arrary set with [array get ::getHistory]"
} else {
Reject request with 501 server error
log local0. "Possible Abuse - User $client_ip"
HTTP::respond 501
return
}
}
}
} - mrintzler
Nimbostratus
Here's the log output of the above iRule when run on the two different versions:
Output of log when running through iRule on 10.1.0 3900 LTM:
Rule connection-limit-rule : Setting getHistory with 10.1.210.253_7039861 and 1271206346
Rule connection-limit-rule : Arrary set with 10.1.210.253_7039861 1271206346
Rule connection-limit-rule : Checking 10.1.210.253_7039861 for time 10.1.210.253_7039861
Rule connection-limit-rule : Setting getHistory with 10.1.210.253_8958191 and 1271206346
Rule connection-limit-rule : Arrary set with 10.1.210.253_8958191 1271206346 10.1.210.253_7039861 1271206346
Rule connection-limit-rule : Checking 10.1.210.253_8958191 for time 10.1.210.253_8958191
Rule connection-limit-rule : Checking 1271206346 for time 1271206346
01220001:3: TCL error: siebel-connection-limit-rule - can't unset "::getHistory(1271206346)": no such element in array while executing "unset ::getHistory($sbrequestID)" ("foreach" body line 7) invoked from within "foreach { sbrequestID requestTime } [array get ::getHistory ${client_ip}*] { log local0. "Checking $sbrequestID for time $requestTime" ..."
Output of log when running through same iRule on 10.0.1 3400
Rule connection-limit-rule : Setting getHistory with 10.1.102.108_924115 and 1271206504
Rule connection-limit-rule : Arrary set with 10.1.102.108_924115 1271206504
Rule connection-limit-rule : Checking 10.1.102.108_924115 for time 1271206504
Rule connection-limit-rule : Setting getHistory with 10.1.102.108_1614654 and 1271206506
Rule connection-limit-rule : Arrary set with 10.1.102.108_924115 1271206504 10.1.102.108_1614654 1271206506
Rule connection-limit-rule : Checking 10.1.102.108_924115 for time 1271206504
Rule connection-limit-rule : Checking 10.1.102.108_1614654 for time 1271206506
Rule connection-limit-rule : Setting getHistory with 10.1.102.108_7492669 and 1271206506
Rule connection-limit-rule : Arrary set with 10.1.102.108_924115 1271206504 10.1.102.108_7492669 1271206506 10.1.102.108_1614654 1271206506
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects
