Forum Discussion
AndOs
Cirrostratus
Dec 03, 2012Keep 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
- Andreas,
F5 solution takes security to the next level - since we proxy all the connections through the APM, customers expressed desire to have an enhanced level of control where existing ICA sessions for the user terminate when the APM session for that user terminates. That said, in your case, there is a very easy solution to your problem.
Our default iApp setting is to tie in Web Interface Logout action to the termination of the APM session. That is accompished by the iRule that is created by the iApp. All you have to do is uncheck "Strict" updates from the Application Service you deployed, and then remote that iRule from the Virtual server- and your applications will now stay active after you log off WI, since APM session will not be terminated. - AndOs
Cirrostratus
Thanks for your quick reply!
Didn't think of looking at the iRules :)
Thanks!
I've done a few tests now, with logging off web interface, logged off and then closed browser, closed browser directly. And all work fine. Applications stays active.
The only thing is that the users will get the Citrix web interface logon page (which looks different) after logging off. They won't come back to APM logon.
Is there a way to fix that?
I looked at the iRule and it did "ACCESS::session remove"
Is it possible to change that and create a new session instead of removing the old? Would that send the user back to the APM logon?
Or would that cause other problems with old sessions filling up?
/Andreas - Andreas,
Are you asking of it's possible for the SSO to kick back in if the APM session is still in progress and the user wants to go back to Web Interface? That should be possible - try to go to SSO config and check "Successfull Logon Detection Match" option to None, and see if SSO works after user logs off WI and then goes back in.
Or are you asking to have users authenticated by the APM again after they log out? That might be more challenging - you can try to use an iRule, but you can't remove the session because it will kill all the associated ICA sessions. You can try to remove MRHSession cookie in the HTTP_RESPONSE event(something like HTTP::cookie remove MRHSession) or better yet, set the MRHSession cookie to a date in the past so that it would expire on the browser side. This way browser would be forced to start a new APM session when they try to go back into WI - and user will end up having mutliple different APM sessions. - Andreas,
Are you asking of it's possible for the SSO to kick back in if the APM session is still in progress and the user wants to go back to Web Interface? That should be possible - try to go to SSO config and check "Successfull Logon Detection Match" option to None, and see if SSO works after user logs off WI and then goes back in.
Or are you asking to have users authenticated by the APM again after they log out? That might be more challenging - you can try to use an iRule, but you can't remove the session because it will kill all the associated ICA sessions. You can try to remove MRHSession cookie in the HTTP_RESPONSE event(something like HTTP::cookie remove MRHSession) or better yet, set the MRHSession cookie to a date in the past so that it would expire on the browser side. This way browser would be forced to start a new APM session when they try to go back into WI - and user will end up having mutliple different APM sessions. - AndOs
Cirrostratus
It would be great if the users could get back to the APM logon, and basically log back on if they wanted to.
I was looking at the reference for ACCESS:: and there is an ACCESS::session create
So I was thinking of just replacing ACCESS::session remove with ACCESS::session create in the iRule.
The MRHSession cookie, is that something APM-internal for the current session?
Is the details of MRHSession documented somewhere?
I found some info in Configuration_Guide_for_BIG-IP_Access_Policy_Manager.pdf
Thanks!
/Andreas - MRHSession cookie contains the sessionid that is read by APM. If the session indicated in the cookie exists, user will be allowed. ACCESS:session create will create a new session, but it will NOT insert the coookie automatically in the response.
So, best advice I can give you is play with the iRule to change the expiration date on the MRHSession cookie to something in the past so that it would be expired on the browser, but the APM session will still be active, so existing ICA sessions willl continue. - AndOs
Cirrostratus
Ah ok.
Thanks for the info.
I'll take a closer look at the iRule/MRHSession and see if I can get it to work.
/andreas - AndOs
Cirrostratus
After a lot of trial and error, I managed to piece together an iRule from various sources here on devcentral.
Turned out to be a bit trickier than I thought, because there may be several tcp connections open from the browser to the web interface, and all those
are authenticated in APM. So simply expiring the APM session cookies and redirecting back to the logon page did not work.
The browser would in that case use another, already establised, connection to request logon page, and (from what I can understand) APM would just send
the request through and the user ended up beeing logged on to the web interface again.
So to get around that I store the session id in a table and check subsequent requests if they are for a logged out session.
Any comments or suggestions greatly appreciated :)
when RULE_INIT {
set ::debug 0
set ::logonpage "https://logon.company.com/"
set ::logoffURI "/auth/loggedout.aspx"
}
when ACCESS_ACL_ALLOWED {
if {$::debug > 1 } { log local1. "uri=[HTTP::uri] | session=[ACCESS::session sid] | client=[IP::client_addr]:[TCP::client_port]" }
Has the user logged off?
if {[HTTP::uri] contains $::logoffURI } {
if {$::debug} { log local1. "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 -subtable "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 {$::debug} { log local1. "MRHSession=$MRHSession" }
}
if {[HTTP::cookie exists "LastMRH_Session"]} {
set LastMRH_Session [HTTP::cookie LastMRH_Session]
if {$::debug} { log local1. "LastMRH_Session =$LastMRH_Session " }
}
}
}
when HTTP_RESPONSE {
set sessionstatus [table lookup -subtable "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 {$::debug} { log local1. "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 {$::debug} { log local1. "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 {$::debug} { log local1. "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 {$::debug} { log local1. "looping cookies..." }
foreach orgCookieName [HTTP::cookie names] {
if {$::debug} { log local1. "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 {$::debug} { log local1. "Custom cookies: $cookieheaders" }
Send a redirect response to the client. With Connection: Close!
if { $cookieheaders != "" } {
HTTP::respond 302 Location "$::logonpage" "Set-Cookie" $cookieheaders "X-OLL-CTX-LOGOUT" "1" "Connection" "Close"
} else {
HTTP::respond 302 Location "$::logonpage" "X-OLL-CTX-LOGOUT" "1" "Connection" "Close"
}
}
} - hoolio
Cirrostratus
Nice work in figuring this out.
Make sure to use static variables in RULE_INIT to preserve CMP:
https://devcentral.f5.com/wiki/iRules.CMPCompatibility.ashx
Also, generally you should only use a subtable if you need to count the entries. You can use a prefix on the key names instead to prevent key name collisions.when RULE_INIT { set static::access_debug 0 set static::logonpage "https://logon.company.com/" set static::logoffURI "/auth/loggedout.aspx" } when ACCESS_ACL_ALLOWED { if {$static::access_debug > 1 } { log local1. "uri=[HTTP::uri] | session=[ACCESS::session sid] | client=[IP::client_addr]:[TCP::client_port]" } Has the user logged off? if {[string tolower [HTTP::path]] eq $static::logoffURI } { if {$static::access_debug} { log local1. "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 local1. "MRHSession=$MRHSession" } } if {[HTTP::cookie exists "LastMRH_Session"]} { set LastMRH_Session [HTTP::cookie LastMRH_Session] if {$static::access_debug} { log local1. "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 local1. "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 local1. "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 local1. "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 local1. "looping cookies..." } foreach orgCookieName [HTTP::cookie names] { if {$static::access_debug} { log local1. "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 local1. "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" } } }
Aaron - AndOs
Cirrostratus
Thanks!
/Andreas
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)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
