Forum Discussion
Keep applications active after web interface logoff
Hi!
I'm trying to make a configuration with Big-ip APM to replace two old Citrix Access Gateways for our Citrix farms.
I've made a setup using the iApp for XenApp using f5.citrix_xenapp_xendesktop.2012_06_27 which load balances and authenticates users to our XenApp 5.4 web interfaces.
We are using TMOS 11.2.0 and will not replace the web interface with webtop (basically do pass-through auth if I understand this correct)
One issue I immediately ran into was that the applications I start gets disconnected when I log off the web interface and my APM session closes.
The setting "Logoff behavior: Log off all sessions" is unchecked in Citrix web interface.
If I start applications directly from the web interface servers, without going through the APM, the appications remain active when I log off.
Is there any way to get the applications to remain active even when the APM session closes, so that it mimics the behavior of the old gateways?
I've looked through the iApp deployment guide and also the settings in APM, but haven't found anything that seems to control this.
Thanks!
/Andreas
21 Replies
- Mark_van_D
Cirrostratus
Perfect just what I was looking for.
Had to make one adjustment to the iRule (location of the last close bracket):
when HTTP_RESPONSE { set sessionstatus [table lookup "ctxloggedoutsessions_[ACCESS::session sid]"]
Mark
- bhs_114985Historic F5 Account
I just used this iRule to address this exact issue and it worked great. Thank you for the time and effort to put this together. Here is a copy of my Rule as it stands (tested and confirmed to be working). This was for a Xen6.5 SF2.1 on BIG-IP 11.5.0HF2.
when RULE_INIT { set static::access_debug 0 The logonpage and logoffURI must be entered in all lower case below so when the stringtolower command compares the real path with the static variables, they match correctly set static::logonpage "https://thisneedstobealllowercase.com/my.policy" set static::logoffURI "/this/needsto/beall/lowercase" } when ACCESS_ACL_ALLOWED { if {$static::access_debug = 1 } { log local0. "uri=[HTTP::uri] | session=[ACCESS::session sid] | client=[IP::client_addr]:[TCP::client_port]" } Has the user logged off? (Changed to http_uri instead of http_path 6-17-2014) if {[string tolower [HTTP::uri]] eq $static::logoffURI } { if {$static::access_debug = 1 } { log local0. "Detected logoff!" } need to track the sessionID because after the redirect has been sent, the browser may use an already established (access granted) tcp connection that will be allowed through ACCESS_ACL_ALLOED. table add "ctxloggedoutsessions_[ACCESS::session sid]" 1 60 90 store the APM session cookies from the request. if {[HTTP::cookie exists "MRHSession"]} { set MRHSession [HTTP::cookie MRHSession] if {$static::access_debug} { log local0. "MRHSession=$MRHSession" } } if {[HTTP::cookie exists "LastMRH_Session"]} { set LastMRH_Session [HTTP::cookie LastMRH_Session] if {$static::access_debug} { log local0. "LastMRH_Session =$LastMRH_Session " } } } } when HTTP_RESPONSE { set sessionstatus [table lookup "ctxloggedoutsessions_[ACCESS::session sid]"] check if this reponse is for a session that has been marked as logged off. if { $sessionstatus == 1 } { yes, user has logged off. if {$static::access_debug} { log local0. "Found session [ACCESS::session sid] in table" } set cookieheaders "" prepare the APM session cookies to be expired by setting the date to UNIX TS 0 if { [info exists MRHSession] } { set cookieheaders "MRHSession=$MRHSession;expires=Thu, 01-Jan-1970 00:00:00 GMT;path=/;" if {$static::access_debug} { log local0. "setting cookie, MRHSession" } unset MRHSession } if { [info exists LastMRH_Session] } { set cookieheaders "$cookieheaders\r\nSet-Cookie: LastMRH_Session=$LastMRH_Session;expires=Thu, 01-Jan-1970 00:00:00 GMT;path=/;" if {$static::access_debug} { log local0. "setting cookie, LastMRH_Session" } unset LastMRH_Session } Loop through all other cookies which are set in the repsonse, and expire those as well. This does not seem to be needed. if {$static::access_debug} { log local0. "looping cookies..." } foreach orgCookieName [HTTP::cookie names] { if {$static::access_debug} { log local0. "found cookie: $orgCookieName=[HTTP::cookie value $orgCookieName]" } set cookieheaders "$cookieheaders\r\nSet-Cookie: $orgCookieName=[HTTP::cookie value $orgCookieName];expires=Thu, 01-Jan-1970 00:00:00 GMT;[HTTP::cookie path $orgCookieName];" } if {$static::access_debug > 0 } { log local0. "Custom cookies: $cookieheaders" } Send a redirect response to the client. With Connection: Close! if { $cookieheaders != "" } { HTTP::respond 302 Location "$static::logonpage" "Set-Cookie" $cookieheaders "X-OLL-CTX-LOGOUT" "1" "Connection" "Close" } else { HTTP::respond 302 Location "$static::logonpage" "X-OLL-CTX-LOGOUT" "1" "Connection" "Close" } } }
BHS
- Stefan_Klotz
Cumulonimbus
Hi all,
we were first lucky to find this thread and solution, because we also have a requirement, that the application should still be active, after the user logs off from webinterface or closes the browser.
Redirecting back to the APM logon page is working fine with this iRule, but applications will be disconnected when hitting the logoff button.
:EDIT: It seems to be fine for the first time. But when I close the application and re-start it again, then it disconnects when I logoff from WI.
At the moment we have no further idea where to search for, below some technical details of what we are using.
- TMOS 11.4.1 HF4
- iApp f5.citrix_vdi.v1.1.0
- XenApp 6.5
- StoreFront 2.5
Thank you for any further hints or troubleshooting steps.
Ciao Stefan :)
- Stefan_Klotz
Cumulonimbus
I found out that the reason for disconnecting the application is that the APM session is killed/removed. But it seems to be not 100% reproducible, means once it gets disconnected I can re-logon, start the application and when hitting the logoff button it gets disconnected again. I performed this 3-5 times in a row and always the same behavior, but sometimes it stays connected. I verified the APM log and the difference between a disconnected session and a connected one is as follows.
Connected one ends with this entry:
474a67ec: SSO disabled for '' using config '/Common/Kae-Citrix-iApp.app/Kae-Citrix-iApp_apm_sso_form_based', pass through request
Disconnected one ends with these entries:
88d66e1d: SSO disabled for '' using config '/Common/Kae-Citrix-iApp.app/Kae-Citrix-iApp_apm_sso_form_based', pass through request 88d66e1dW: Session deleted due to user logout request. 88d66e1d: Session stats update failed
So why is the logoff process from WI processed into APM and why not always? Any idea to which configuration this is related to?
Thank you!
Ciao Stefan 🙂
- bhs_114985Historic F5 Account
Here is a slightly modified iRule that is confirmed working as of 11.6HF1
when RULE_INIT { set static::access_debug 0 set static::logonpage "https://CTX.COMPANY.COM/YOUR_CITRIX_XENAPP/" set static::logoff_timeout "/YOUR_CITRIX_XENAPP/site/logout.aspx?ctx_timeout" set static::logoff_user "/YOUR_CITRIX_XENAPP/site/logout.aspx" } when HTTP_REQUEST { log "[string tolower [HTTP::path]]" if {$static::access_debug > 1 } { log "uri=[HTTP::uri] | session=[ACCESS::session sid] | client=[IP::client_addr]:[TCP::client_port]" } Has the user logged off? if {[string tolower [HTTP::uri]] starts_with $static::logoff_timeout} { set ctx_timeout 1 if {$static::access_debug} { log "Detected logoff!" } need to track the sessionID because after the redirect has been sent, the browser may use an already established (access granted) tcp connection that will be allowed through ACCESS_ACL_ALLOED. table add "ctxloggedoutsessions_[ACCESS::session sid]" 1 60 90 store the APM session cookies from the request. if {[HTTP::cookie exists "MRHSession"]} { set MRHSession [HTTP::cookie MRHSession] if {$static::access_debug} { log "MRHSession=$MRHSession" } } if {[HTTP::cookie exists "LastMRH_Session"]} { set LastMRH_Session [HTTP::cookie LastMRH_Session] if {$static::access_debug} { log "LastMRH_Session =$LastMRH_Session " } } } if {([string tolower [HTTP::uri]] starts_with $static::logoff_user) && ![info exists ctx_timeout]} { after 2000 { ACCESS::session remove} log local0. "Session manually logging out" } } when HTTP_RESPONSE { set sessionstatus [table lookup "ctxloggedoutsessions_[ACCESS::session sid]"] check if this reponse is for a session that has been marked as logged off. if { $sessionstatus == 1 } { yes, user has logged off. if {$static::access_debug} { log "Found session [ACCESS::session sid] in table" } set cookieheaders "" prepare the APM session cookies to be expired by setting the date to UNIX TS 0 if { [info exists MRHSession] } { set cookieheaders "MRHSession=$MRHSession;expires=Thu, 01-Jan-1970 00:00:00 GMT;path=/;" if {$static::access_debug} { log "setting cookie, MRHSession" } unset MRHSession } if { [info exists LastMRH_Session] } { set cookieheaders "$cookieheaders\r\nSet-Cookie: LastMRH_Session=$LastMRH_Session;expires=Thu, 01-Jan-1970 00:00:00 GMT;path=/;" if {$static::access_debug} { log "setting cookie, LastMRH_Session" } unset LastMRH_Session } Loop through all other cookies which are set in the repsonse, and expire those as well. This does not seem to be needed. if {$static::access_debug} { log "looping cookies..." } foreach orgCookieName [HTTP::cookie names] { if {$static::access_debug} { log "found cookie: $orgCookieName=[HTTP::cookie value $orgCookieName]" } set cookieheaders "$cookieheaders\r\nSet-Cookie: $orgCookieName=[HTTP::cookie value $orgCookieName];expires=Thu, 01-Jan-1970 00:00:00 GMT;[HTTP::cookie path $orgCookieName];" } if {$static::access_debug} { log "Custom cookies: $cookieheaders" } Send a redirect response to the client. With Connection: Close! if { $cookieheaders != "" } { HTTP::respond 302 Location "$static::logonpage" "Set-Cookie" $cookieheaders "X-OLL-CTX-LOGOUT" "1" "Connection" "Close" } else { HTTP::respond 302 Location "$static::logonpage" "X-OLL-CTX-LOGOUT" "1" "Connection" "Close" } } }
- ipman_1988_5418
Nimbostratus
when ACCESS_ACL_ALLOWED { if {[string tolower [HTTP::uri]] eq "/citrix//authentication/logoff"} { table add "ctxloggedoutsessions_[ACCESS::session sid]" 1 28800 28800 } } when HTTP_REQUEST { set sessionstatus [table lookup "ctxloggedoutsessions_[ACCESS::session sid]"] if { $sessionstatus == 1 } { HTTP::respond 302 Location "https://www.yourcitrixapm.com/my.logout.php3" unset sessionstatus table delete "ctxloggedoutsessions_[ACCESS::session sid]" } }
- ipman_1988_5418
Nimbostratus
`
(function ($) { $.localization.customStringBundle('en', { YouAreLoggedOff: 'You have logged off successfully.' +'' }); })(jQuery);
`
- SLGizmo_219768
Nimbostratus
On version 12.0 I found I had to modify the following in order for it to work.
if {$static::access_debug = 1 } to be if {$static::access_debug == 1 }
However, after you click on the logoff it does not truly log me off the system as I click on the log back in button and it brings me back to my published application and does not bring me back to the F5 login page. Any ideas?
Gizmo
- iaine
Nacreous
I had to change this iRule slightly to get it to work for me as I was getting TCL errors for unset variables as well as not getting redirected to the APM login page. My tweaked code is...
when RULE_INIT { set static::access_debug 0 The logonpage and logoffURI must be entered in all lower case below so when the stringtolower command compares the real path with the static variables, they match correctly Do not set loginpage variable to my.policy, let the APM redirects occur set static::logonpage "https://myloginpage.com" set static::logoffURI "/citrix/remoteappsweb/authentication/logoff" } when CLIENT_ACCEPTED { Set this variable early on to avoid TCL errors set ctxloggedoutsessions 0 } when ACCESS_ACL_ALLOWED { if {$static::access_debug > 1 } { log local0. "uri=[HTTP::uri] | session=[ACCESS::session sid] | client=[IP::client_addr]:[TCP::client_port]" } Has the user logged off? (Changed to http_uri instead of http_path 6-17-2014) if {[string tolower [HTTP::uri]] eq $static::logoffURI } { if {$static::access_debug == 1 } { log local0. "Detected logoff!" } need to track the sessionID because after the redirect has been sent, the browser may use an already established (access granted) tcp connection that will be allowed through ACCESS_ACL_ALLOWED. set ctxloggedoutsessions ctxloggedoutsessions_[ACCESS::session sid] table add $ctxloggedoutsessions 1 60 90 store the APM session cookies from the request. if {[HTTP::cookie exists "MRHSession"]} { set MRHSession [HTTP::cookie MRHSession] if {$static::access_debug} { log local0. "MRHSession=$MRHSession" } } if {[HTTP::cookie exists "LastMRH_Session"]} { set LastMRH_Session [HTTP::cookie LastMRH_Session] if {$static::access_debug} { log local0. "LastMRH_Session =$LastMRH_Session " } } } } when HTTP_RESPONSE { set sessionstatus [table lookup $ctxloggedoutsessions] check if this reponse is for a session that has been marked as logged off. if {$sessionstatus == 1} { yes, user has logged off. if {$static::access_debug} { log local0. "Found session [ACCESS::session sid] in table" } set cookieheaders "" prepare the APM session cookies to be expired by setting the date to UNIX TS 0 if { [info exists MRHSession] } { set cookieheaders "MRHSession=$MRHSession;expires=Thu, 01-Jan-1970 00:00:00 GMT;path=/;" if {$static::access_debug} { log local0. "setting cookie, MRHSession" } unset MRHSession } if { [info exists LastMRH_Session] } { set cookieheaders "$cookieheaders\r\nSet-Cookie: LastMRH_Session=$LastMRH_Session;expires=Thu, 01-Jan-1970 00:00:00 GMT;path=/;" if {$static::access_debug} { log local0. "setting cookie, LastMRH_Session" } unset LastMRH_Session } Loop through all other cookies which are set in the repsonse, and expire those as well. This does not seem to be needed. if {$static::access_debug} { log local0. "looping cookies..." } foreach orgCookieName [HTTP::cookie names] { if {$static::access_debug} { log local0. "found cookie: $orgCookieName=[HTTP::cookie value $orgCookieName]" } set cookieheaders "$cookieheaders\r\nSet-Cookie: $orgCookieName=[HTTP::cookie value $orgCookieName];expires=Thu, 01-Jan-1970 00:00:00 GMT;[HTTP::cookie path $orgCookieName];" } if {$static::access_debug > 0 } { log local0. "Custom cookies: $cookieheaders" } Send a redirect response to the client. With Connection: Close! if { $cookieheaders != "" } { HTTP::respond 302 noserver Location "$static::logonpage" "Set-Cookie" $cookieheaders "X-OLL-CTX-LOGOUT" "1" "Connection" "Close" TCP::close } else { HTTP::respond 302 noserver Location "$static::logonpage" "X-OLL-CTX-LOGOUT" "1" "Connection" "Close" TCP::close } } }
- Tiwan_Nicholson
Nimbostratus
Looks like this is a very popular question in F5 land...a quick Google search turned up at least a half-dozen forum posts asking for this very solution. Well count me in as someone who needs to solve this problem. I noticed that there are multiple iRule scripting approaches outlined in the comments of this post, so I'd like to know a) which of these scripts is the "most correct" for me to use, or b) if at this point (APM v12.1.1 with iApp v2.3.0) BigIP has come up with a simpler, non-scripted way of doing it. And before you ask, I did try the "Should the iApp remove the APM session when users log out of the Web Interface or StoreFront servers?" option in the iApp, and it still did not work.
My requirements are very much like those that "bhs" described on 10/17/2014:
-
If a user manually clicks "logoff" from StoreFront, all open ICA sessions are terminated.
-
If the StoreFront page times out (not deliberate user logoff), the ICA sessions remain open.
-
If the user (still with existing ICA sessions open) logs into F5/SF again, they can launch new apps alongside those in the existing open ICA session.
-
When a user logs off from StoreFront, they are redirected back to the F5 signin page.
We were able to accomplish 4 using an iRule documented in the Citrix VDI iApp Deployment Guide v2.5. But we're still facing the first 3 requirements.
As a first-time F5 implementer with no iRule scripting experience, I'd appreciate any guidance any of you are willing to provide.
-
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