Forum Discussion
SNAT persistency
i want to achieve the following:
1) I want the F5 to choose an IP in round-robin manner from a SNAT pool and to persist using the same IP from the SNAT pool in case an HTTP header called "Username" value is the same.
2) Every HTTP request which will come in less than 5 minutes with the same "username" header value should receive the same SNAT IP from the pool. additionally that SNAT IP must be marked as "used" so that no other "username" will get this SNAT IP (unless 5 minutes has passed with no HTTP request with the same username value. after the 5 minutes that SNAT IP can be available again in the pool).
3) I want the F5 to chop off the username header before forwarding the HTTP request using the SNAT IP.
4) I want the F5 to log every NAT action it does to some syslog server (like: = )
Example:
SNAT pool is 192.118.0.0/16 and the Username possible values can be any string.
HTTP request arrives from source IP 172.16.1.1 with header “Username: aaa”
F5 will replace the source IP 172.16.1.1 to be 192.118.0.1
After less than 5 minutes another HTTP request arrives from source IP 172.16.1.1 with header “Username: aaa”
F5 will replace the source IP 172.16.1.1 to be 192.118.0.1
After less than 5 minutes HTTP request arrives from source IP 172.16.1.1 with header “Username: bbb”
F5 must not replace the source IP to be 192.118.0.1 as it is taken by username aaa.
After more than 5 minutes another HTTP request arrives from source IP 172.16.1.1 with header “Username: aaa”
F5 can replace the source IP 172.16.1.1 to be other than 192.118.0.1 (for example: 192.118.0.2)
Hope it is clear enough, if not please comment.
Thanks in advance,
Yaniv
11 Replies
- Steve_Brown_882Historic F5 AccountThis is a fairly large list of requirements and unless I am missing something m,ay be fairly complex to implement. I will try to address as many of the pieces as I can here.
First assigning a specific member to a snatpool should be pretty straight forward. The command do this is "snatpool [member ". So an example would be "snatpool mysnatpool member 10.1.2.3". In reality you will probably use a variable for the member so
"snatpool mysnatpool member $some_variable"
Now the harder part is how are you going to assign the variable. You could create a class containing all of the IPs that are in the snat pool and loop through it using next element. This would take care of getting the list of members but next you would need a way to keep track of them so I am thinking you would need to use the table command.
So the flow would be check an incoming request to see if it has and existing snat assigned, if it doesn't you would loop through the class file checking each element against the table until you find a snat member that is not in use.
I am not certain exactly how efficient this would be but I think you could make it work. I am sure others will chime in with there thoughts. It is also entirely possible that I am over complicating this a bit. - Steve_Brown_882Historic F5 AccountAlright, I decided to give this a try. I am sure this irule probably needs some work yet, and it may not be the most efficient, but I think it comes close do doing what you are looking for.
when HTTP_REQUEST { Set var with username header set uname [HTTP::header "username"] set clname "snatpool_class" set searchID [class startsearch "snatpool_example" ] Check to see if the uname already has a snat if { [table lookup -subtable "snat_table" $uname] ne "" } { set snatpool_member [table lookup -subtable "snattable" $uname] } else { while { [class anymore $clname $searchID] } { look up an ip from the class set snatpool_member [class nextelement -value $clname $searchID] check to see if the IP has been assigned yet if { [table lookup -subtable "snat_table" -notouch $snatpool_meember] eq "" } { add snat assignement to tables table set -subtable "snat_table" $snatpool_member $uname 300 table set -subtable "snat_table" $uname $snatpool_member 300 local log entry this should be changed to a highspeed log off box. log local0.info "Snat assignment of $snatpool_member made to $uname" } } } snatpool mysnatpool member $snatpool_member HTTP::header remove "username" } - Yaniv_99962
Nimbostratus
Thank you so much Steve!
I need some assistance understanding your iRule.
1) I need to create a 'data group list' called snatpool_example which will contain all the available IPs to choose from for doing the SNAT.
In addition I need to create a 'snatpool' called mysnatpool which will contain the exact same members as snatpool_example data group list?
2) snatpool_class and snatpool_example are the same? (so its a typo and I need to change them to be same?)
3) snat_table and snattable are the same? (so its a typo and I need to change them to be same?)
4) wouldn't it be more efficent to use different tables. one for uname as key and snatpool_member as value and the other table with snatpool_member as key and uname as value?
5) wouldn't the while go over the entire snatpool even if an available IP is found to be used (since there is no 'exit' or 'return')? can it be changed? - Steve_Brown_882Historic F5 AccountHi Yaniv,
Sorry about the typos, I got a bit rushed when I put this together yesterday. Here is an updated version and I changed most of the names to variables so you can call the snatpool and the class anything you like, just update the var. I also fixed the while loop I had something similar in there before but re did the rule before I posted it so I never put it back in. As for sepperate tables I am not sure which would be more efficient, maybe someone else can chime in. Also I have not had a chance to really test and debug this rule, so it may still need some work.
when HTTP_REQUEST {
Set var with username header
set uname [HTTP::header "username"]
The clname var contains the class name, if you want to call it something else change it here.
For the rule to work you will need to create a class matching this name that contains all of the snats.
set clname "snatpool_class"
The search id is used to search the class file.
set searchID [class startsearch $clname ]
The mysnatpool var contains the snatpool name, if you want to call it something else change it here.
set mysnatpool "snatpool_name"
The snattable var contains the snattable name, if you want to call it something else change it here.
set snattable "snat_table_name"
set counter 0
Check to see if the uname already has a snat
if { [table lookup -subtable $snattable $uname] ne "" } {
set snatpool_member [table lookup -subtable $snattable" $uname]
} else {
while { ([class anymore $clname $searchID]) and ($counter ne 999) } {
look up an ip from the class
set snatpool_member [class nextelement -value $clname $searchID]
check to see if the IP has been assigned yet
if { [table lookup -subtable $snattable -notouch $snatpool_member] eq "" } {
add snat assignement to tables
table set -subtable $snattable $snatpool_member $uname 300
table set -subtable $snattable $uname $snatpool_member 300
local log entry this should be changed to a highspeed log off box.
log local0.info "Snat assignment of $snatpool_member made to $uname"
Set counter var to 999 to end the loop
set counter 999
}
}
}
snatpool $mysnatpool member $snatpool_member
HTTP::header remove "username"
} - Yaniv_99962
Nimbostratus
Thanks Steve,
It doesn't seem to be working :(
There was one typo i fixed (the was a redundant " character in this line 'set snatpool_member [table lookup -subtable $snattable $uname] '
looking at the log it seems that the $snatpool_member value doesn't get populated for some reason:
Mar 23 08:18:28 local/tmm3 info tmm3[5253]: Rule Snat_Persist : Snat assignment of made to ccc
I created the snat pool and the data group list (class) with the exact same names as in the iRule.
Any idea what could it be? - Yaniv_99962
Nimbostratus
i added the 2nd line here for debugging:
set snatpool_member [class nextelement -value $clname $searchID]
log local0.info "clname:=$clname ; searchID=$searchID ; snatpool_member=$snatpool_member"
And indeed according to the log it seems that the snatpool_member var remains empty:
Mar 23 08:46:11 local/tmm2 info tmm2[5251]: Rule Snat_Persist : clname:=snatpool_example ; searchID=class_iter:snatpool_example1 ; snatpool_member=
(snatpool_example is the name I gave to the class i created)
I guess it's because the class doesnt contains values, only keys/names.So I changes "-value" to be "-name" and now the log looks better:
Mar 23 08:55:47 local/tmm2 info tmm2[5251]: Rule Snat_Persist : Snat assignment of 10.107.200.202/32 made to ccc
I'll keep looking into that...
Thanks
- Yaniv_99962
Nimbostratus
me again :)
ok, so the snat assignment itself doesnt seem to work because the following line expects an IP like 10.107.200.202 but I got 10.107.200.202/32
snatpool $mysnatpool member $snatpool_member
How can I get rid of the "/32"? - Steve_Brown_882Historic F5 AccountThe /32 is in your data group? If so I would suggest switching from an IP data group to a string and simply put a single IP without the mask on each line.
- Yaniv_99962
Nimbostratus
Awesome!
changing the data group to be string instead of IP fixed the problem
Thanks a million.
another question: how can I access the table for debugging? for example I want to see all concurrent assignments of SNAT IP to username and their timeout state? (is there some CLI 'b' command to do it?) - Steve_Brown_882Historic F5 AccountActually I just did some poking around and found this VERY COOL iRule that Joe wrote for manipulating the session table. It builds a page that allows you to view, edit, import, export the session table all inside of the iRule. He has a really good write up and a video demo.
http://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/1086401/Session-Table-Control-With-iRules.aspx
Recent Discussions
Related Content
* 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
