Citrix ADC / NetScaler has three types of persistence that sound similar:
- Rule-Based Persistence (RULE)
- Custom Server ID (CUSTOMSERVERID)
- URL Passive (URLPASSIVE)
set lb vserver <servername> -persistenceType RULE -rule "<request-rule>" -resRule "<response-rule>" -cltTimeout <persistence timeout>
With rule-based persistence, we use the existing webserver session information. We have to extract it from a cookie. The session information is the key to persistence. The Citrix ADC / NetScaler will build up its persistence table, containing this information.
My screen-shot shows the persistence table of a Citrix ADC / NetScaler using rule-based persistence. As you can see, there is no source IP in the table (in fact, all three sessions had been established from the same source, but using different browsers).
To be able to base persistence on an existing session cookie, the Citrix ADC / NetScaler needs two rules, a rule in the response side to extract the session information from the server response cookie and store it into the persistence table. The second rule is needed on the request side, to extract the information from the request cookie so the Citrix ADC / NetScaler is able to look it up in the persistence table. If the cookie is missing in the table (so a new user is connecting), rule-based persistence will fail and normal load-balancing will take place.
Rule-based persistence is using persistence tables on the ADC, so it can be costly in terms of memory.
Creating the test environment on a Citrix ADC / NetScaler
I am using my test-website (red.wonderkitchen.network=188.8.131.52, blue.wonderkitchen.network=184.108.40.206, green.wonderkitchen.network=220.127.116.11), so I created three services:
add serviceGroup sg_colors HTTP
bind serviceGroup sg_colors srv_red 80 -CustomServerID 18.104.22.168
bind serviceGroup sg_colors srv_blue 80 -CustomServerID 22.214.171.124
bind serviceGroup sg_colors srv_green 80 -CustomServerID 126.96.36.199
add lb vserver lb_vs_colors_rulebased_pers HTTP 192.168.229.105 80
This is my base setup. My test-servers send a session cookie with them:
So you see, the name of the cookie is Session_ID and it contains a server name and a random number: The session ID. It’s unique per user.
Setting up rule based persistence
This is a solution that works fine with my environment. You can see, I selected RULE as the persistence type. The Time-out value is 2 minutes (which usually is not long enough in a real-world environment, but perfect for a test environment, as the session is timing out within the amount of time it takes me to grab myself another cup of coffee). And last, not least, there are the two rules, allowing the ADC to extract the information needed. I’ll discuss these in detail, as they are the “secret” of persistence type RULE.
Request side rule
The request side rule extracts everything behind the string Server_.
Response side rule
Dies sind einige der Cookie-Strings, die ich in meiner Umgebung gesehen habe:
So the name of the cookie of interest is Session_ID, it always starts with the name of the server and appends an underscore and the session number, which is unique per user.
So you see, the response side string is quite similar to the request side string. Unfortunately, there is no expression like
HTTP.RES.COOKIE. Cookies, seen from a technical perspective, are just headers, so I have to look for a header called Cookie and extract my data from there. Same logic: everything after Server_ is the information required.
I hope that helps to bring a little light to the secret of rule-based persistence 🙂 Like always: Every feedback would be highly welcome. Donations as well!