Forum Discussion
JRahm
Mar 01, 2005Admin
Terminal Server Persistence
I have msrdp persistence working without a rule, but only within a single vip. Globally, I don't have persistence to the client, so a client could potentially be assigned to the wrong vip, and even though session directory sends the client the routing token, and the client sends this routing token to the BigIP, it is being ignored if the client hits the wrong vip. Here's what the cookie looks like in hex and ascii:
0040 00 43 6f 6f 6b 69 65 3a 20 6d 73 74 73 3d 38 31 .Cookie: msts=81
0050 33 39 36 34 30 34 32 2e 31 35 36 32 39 2e 30 30 3964042.15629.00
0060 30 30 0d 0a 00..
The 813964042 is the server IP (dec->hex(reverse pairs)->dec(by octet)) and the 15629 is the tcp port (dec->hex(reverse pairs)->dec)
If I can't persist across virtuals with the msrdp cookie with the gui, then I'd like to build a rule that will persist across virtuals. I don't want only one vip because I will have aprox. 750 servers, and I'd like to pool these by rack.
Is there a command within iRules to return a node from the msrdp cookie? I saw in the config guide that there is one for BEA WebLogic and I didn't know if there was one for MS Terminal Services since the BigIP has the ability to do this already. Thanks.
- unRuleY_95363Historic F5 AccountHmm, I'm not quite sure I fully understand your vip issue. When MSRDP persistence is configured on a vip, it searches for the embedded cookie. Upon finding it, it will then use that node as long as it is a valid node within the current pool.
- JRahmAdminFor clarity,
- unRuleY_95363Historic F5 AccountOk, two things:
rule msrdp_sessdir_uie { when CLIENT_ACCEPTED { TCP::collect } when CLIENT_DATA { if { [TCP::payload length] < 25 } { TCP::collect return } binary scan [TCP::payload] x11a* msrdp if { [string equal -nocase -length 12 $msrdp "cookie: msts"] } { set msrdp [string range $msrdp 12 end] set len [string first "\n" $msrdp] if { $len == -1 } { Didnt get whole cookie collect more TCP::collect return } if { $msrdp starts_with "=" } { Session directory - extract node/port if { [scan $msrdp "=%u.%u" node port] != 2] } Did not find node/port, get more TCP::collect return } set node [ntohl $node] set port [ntohs $port] log "DEBUG: overriding to $node:$port" Note: the node command does not check the pool node $node $port } elseif { $msrdp starts_with "hash=" } { No session directory - username used instead if { $len > 5 } { incr len -1 set record [string range $msrdp 5 $len] log "adding persistence record - $record" persist uie $record 300 } else { log "No username - not persisting" } } } else { log "Cookie not found" } TCP::release } }
- JRahmAdminWow, iRules are much more powerful that I anticipated. Concerning the options:
- JRahmAdminI corrected some syntax so that the rule would be accepted, but I'm not sure if I broke the rule in doing so. I don't get any connection when I don't send user credentials (thus preventing the mstshash= but I can login once I do supply the username. Also, the correct syntax from the documentation is [TCP::payload_length], but this gives me an error:
- rapmaster_c_127Historic F5 AccountTry TCP::offset instead?
- rapmaster_c_127Historic F5 AccountOr actually, come to think of it, you want to collect at least 25 bytes, right? In that case TCP::collect 25 ought to do it for you. TCP::offset should give you the amount currently collected, but there should be no need for this if you specify the length to collect.
- JRahmAdminOK, I commented out the if statement with TCP::payload_length and used TCP::collect 25 instead. This is working, and I see the log entries.
- unRuleY_95363Historic F5 AccountOoops, sorry. I forgot to format the $node variable into an IP address that is compatible with the node command. You should be seeing an error in /var/log/ltm.
binary scan [binary format I $node] c1c1c1c1 ip1 ip2 ip3 ip4 set ip1 [expr { ($ip1 + 0x100) % 0x100 }] set ip2 [expr { ($ip2 + 0x100) % 0x100 }] set ip3 [expr { ($ip3 + 0x100) % 0x100 }] set ip4 [expr { ($ip4 + 0x100) % 0x100 }] set node [format "%u.%u.%u.%u" $ip1 $ip2 $ip3 $ip4]
when RULE_INIT { array set ::my_nodes { 169575472 10.27.132.48 813964042 48.132.27.10 } } when CLIENT_DATA { ... if { not [info exists $::my_nodes($node)] } { log "Unrecognized Terminal Server Node: $node" reject return } use node $::my_nodes($node) $port ... }
- JRahmAdminConcerning performance, this rule will only fire on session initialization, correct? Thanks.
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