Forum Discussion
APM SSO breaks RDP persistence
- Mar 14, 2021
There is a good news 🙂
We solved it and provided the solution to F5 TAC to maybe enhance it a little bit or publish it to help others after examining it.
But it works fine in our environment and solved the persistence problem.
We used some of your irule and enhance it a little to use LTM load balance.
So, we have an iRule that is doing OTP SMS authentication and it is called from the VPE to send the OTP code to the end user. So we inserted at the top on the iRule a process to pick an available pool member using round robin method:
proc pickOneAvailable { } { set poolNameEnc TWFydmFblablablaBTg== pool [b64decode $poolNameEnc] if {[active_members [b64decode $poolNameEnc]] < 1}{ set mypick "NULL" } else { LB::mode rr set mypick [LB::select] #log local0. "my pick is $mypick" eval $mypick set retVal [getfield [LB::server addr] % 1] #log local0. "my retVal is $retVal" } }
And added this section ""PopulateDestIP"" at the very end of "when ACCESS_POLICY_AGENT_EVENT { " section
"PopulateDestIP" { set uName [ACCESS::session data get session.logon.last.username] set sessionSID [ACCESS::session sid]; log local0. "DEBUG ACCESS SID = $sessionSID" set nextNode [call pickOneAvailable ] if { $nextNode == "NULL" } { #log local0. "Sorry, No Member could pick from pool." } else { ACCESS::session data set "session.logon.rdp.dest" $nextNode #log local0. "This user $uName has picked this server: $nextNode" } unset uName unset sessionSID }
The " PopulateDestIP " will run/call the process " pickOneAvailable " and get the available node and put it into a variable named " $nextNode "
Then it will put this variable into a APM variable named " session.logon.rdp.dest "
After then I take the "session.logon.rdp.dest" variable and use it in the APM RDP configuration [access > connectivity/VPN > VDI/RDP > in the RDP destination I choose type "hostname" and put this variable there " %{session.logon.rdp.dest} " ].
Now, in the VPE, before doing the LDAP query for group membership, I put a Custom iRule Event Agent to call the " PopulateDestIP " )
That’s it. Now when the user login, he will get at the first beginning the IP address of the RDP server using the LTM pool and method round robin.
Now, even if the user got disconnected from the RDP session for any reason or logged out from the RDP server but did not got disconnected from the APM session (he didn't logout entirely from the APM) he will always get the same RDP server because it is written "coded" in the native RDP file he downloads.
So the strategy is :
- To get the available RDP server IP from the LTM pool
- To put the IP as a variable in LTM
- To put that variable into APM variable
- To populate that variable to the end-user
Hi again,
Is there any good or bad news ?
There is a good news 🙂
We solved it and provided the solution to F5 TAC to maybe enhance it a little bit or publish it to help others after examining it.
But it works fine in our environment and solved the persistence problem.
We used some of your irule and enhance it a little to use LTM load balance.
So, we have an iRule that is doing OTP SMS authentication and it is called from the VPE to send the OTP code to the end user. So we inserted at the top on the iRule a process to pick an available pool member using round robin method:
proc pickOneAvailable { } {
set poolNameEnc TWFydmFblablablaBTg==
pool [b64decode $poolNameEnc]
if {[active_members [b64decode $poolNameEnc]] < 1}{
set mypick "NULL"
} else {
LB::mode rr
set mypick [LB::select]
#log local0. "my pick is $mypick"
eval $mypick
set retVal [getfield [LB::server addr] % 1]
#log local0. "my retVal is $retVal"
}
}
And added this section ""PopulateDestIP"" at the very end of "when ACCESS_POLICY_AGENT_EVENT { " section
"PopulateDestIP" {
set uName [ACCESS::session data get session.logon.last.username]
set sessionSID [ACCESS::session sid]; log local0. "DEBUG ACCESS SID = $sessionSID"
set nextNode [call pickOneAvailable ]
if { $nextNode == "NULL" } {
#log local0. "Sorry, No Member could pick from pool."
} else {
ACCESS::session data set "session.logon.rdp.dest" $nextNode
#log local0. "This user $uName has picked this server: $nextNode"
}
unset uName
unset sessionSID
}
The " PopulateDestIP " will run/call the process " pickOneAvailable " and get the available node and put it into a variable named " $nextNode "
Then it will put this variable into a APM variable named " session.logon.rdp.dest "
After then I take the "session.logon.rdp.dest" variable and use it in the APM RDP configuration [access > connectivity/VPN > VDI/RDP > in the RDP destination I choose type "hostname" and put this variable there " %{session.logon.rdp.dest} " ].
Now, in the VPE, before doing the LDAP query for group membership, I put a Custom iRule Event Agent to call the " PopulateDestIP " )
That’s it. Now when the user login, he will get at the first beginning the IP address of the RDP server using the LTM pool and method round robin.
Now, even if the user got disconnected from the RDP session for any reason or logged out from the RDP server but did not got disconnected from the APM session (he didn't logout entirely from the APM) he will always get the same RDP server because it is written "coded" in the native RDP file he downloads.
So the strategy is :
- To get the available RDP server IP from the LTM pool
- To put the IP as a variable in LTM
- To put that variable into APM variable
- To populate that variable to the end-user
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