Forum Discussion
uni
Altocumulus
Apr 11, 2012Persistent SNAT address based on session cookie
I have a client whose application is sensitive to the client IP address
changing within a session. In their environment, there is some selective
SNATting (internal clients are SNATted, public IPs are not).
Because the snatpool allows the client IP to change unpredictably, I have come up with the following rule. It tracks the value of a server-set session cookie, and saves the SNAT address used. When a client connects with the same cookie value, the SNAT address is retrieved and used.
Can someone give me some feedback about whether this is a feasible approach?
rule stg-test-rule {
when RULE_INIT {
set static::stgcookie "stgCOOKIE"
set static::stgtimeout 3600
}
when HTTP_RESPONSE {
if { [HTTP::cookie exists $static::stgcookie] } {
if { not ([serverside {IP::local_addr}] equals [clientside {IP::remote_addr}]) } {
table add [HTTP::cookie value $static::stgcookie] [serverside {IP::local_addr}] $static::stgtimeout
}
}
}
when HTTP_REQUEST {
if { [HTTP::cookie exists $static::stgcookie] } {
set snatip [table lookup [HTTP::cookie value $static::stgcookie]]
if { not ( $snatip equals "" ) } {
snat $snatip
}
}
}
}
6 Replies
- Michael_Yates
Nimbostratus
Hi Stephen,
You said that your Client's Application does not handle the Client IP Address changing within a session. Will the application work with an X-Forwarded-For Header? If so, then the application can pull the client IP Address out of the header and log/utilize it. You can see where to enable the X-Forwarded-For Header in this post.
If not, then you could create a SNAT Pool with a single IP Address in it and SNAT to it (depending on the number of concurrent users your application will have you may need more than one. SNAT IP Addresses do have a connection limit per IP Address. See SOL7820: Overview of SNAT features for additional details). This would make your SNAT IP Address constant if nothing else (but you may need to engage a OneConnect Profile to keep the TCP Sessions load balanced properly).
Hope this helps. - uni
Altocumulus
Thanks Michael. I don't know if the app respects the x-forwardrd-for header, and we don't have access to change it. We can't usea single address in the snatpool as the app does it's own source ip based load balancing.
I wonder if instead you could comment on the feasibility of my proposed solution and rule? I know an alternative mythos is to insert my own cookie with the snat address, which has the advantage of avoiding using a table, and is independent of the app's cookie, but the principle idea is the same. - hoolio
Cirrostratus
Hi Stephen,
I think the iRule looks great for your scenario. Another option for ensuring the SNAT IP is consistent across connections is to use a hash. It's slightly more complicated but supports non-HTTP protocols and doesn't require storing any records on LTM or the client.
https://devcentral.f5.com/wiki/iRules.snat_pool_persistence.ashx
Aaron - hoolio
Cirrostratus
By the way, if you'd like to see SNAT pool member persistence supported in default config, you can open a case with F5 Support and reference BZ384117.
Thanks, Aaron - uni
Altocumulus
Thanks Hoolio. I decided to go with the cookie insert method. It means my rule remains independent of the application and avoids the session table updates. It also remains independent of the actual snatpool, unlike the hashing method.
This is the code I ended up with:rule snat-cookie-persistence-rule { timing on when RULE_INIT { set static::stgcookie "STGSESSION" set static::aes_key "AES 128 0123456789abcdef0123456789abcdef" } when HTTP_REQUEST { set cookieexists [HTTP::cookie exists $static::stgcookie] if { $cookieexists } { if {not ([catch {AES::decrypt $static::aes_key [b64decode [HTTP::cookie value $static::stgcookie]]} snatip])}{ log local0. "setting snat address $snatip" snat $snatip } } } when HTTP_RESPONSE { if { not $cookieexists } { if { [serverside {IP::local_addr}] ne [clientside {IP::remote_addr}] } { log local0. "inserting cookie value [serverside {IP::local_addr}]" HTTP::cookie insert name $static::stgcookie value [b64encode [AES::encrypt $static::aes_key [serverside {IP::local_addr}]]] } } } } - hoolio
Cirrostratus
That makes sense. I also submitted an RFE for getting the SNAT pool members from an iRule:
BZ381099 - ability to enumerate the list of members of a snatpool from an iRule
If you want to see either this or default SNAT pool persistence you could open a case with F5 Support referencing these BZ IDs.
Aaron
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
