Category: NetScaler

Choosing ”HTML5 Receiver” vs ”Native Receiver” dynamically through Netscaler Rewrite Policies

After a user has authenticated on a NSGW vServer, the user will either be prompted to select which Receiver Type (HTML5 vs Native) he/she wants to use, or a choice will be made automatically depending on how well the user’s web browser manages to detect a local Citrix Receiver install. See below picture for an example of the prompt I’m referring to.

You can however get rid of below prompt, and at the same also have a mechanism that selects which Receiver Type that should be for a particular user or scenario. This is achieved through Netscaler Rewrite policies.

How does it work?

In a normal scenario, after the Receiver Type has been selected (either automatically or by user), then the cookie ‘CtxsClientDetectionDone=true’ will be created in the user’s web browser. If Native Receiver has been chosen, then the cookie ‘CtxsUserPreferredClient=Native’ will also be created. By using Rewrite Policies we can create these two cookies by ourselves for the user, and therefore suppress the prompt for the user and automatically choose which Receiver Type to use.

If HTML5 should be used, then we only want to apply the Rerwite policy ”RWP-RES-DISABLE-RECEIVER-CHECK” to suppress the prompt. When Netscaler sees that the cookie ‘CtxsUserPreferredClient’ Cookie is missing, it will default to HTML5 Receiver (this is dependent on your Storefront configuration – see further down). If we want to force the Native Receiver, we also apply the rewrite policy RWP-RES-SET-NATIVE-RECEIVER” to create the cookie ‘CtxsUserPreferredClient=Native’.

In below scenario, I have defined an Expression for my Rewrite Policy ‘RWP-RES-SET-NATIVE-RECEIVER’ to only apply if the user is connecting from IP subnet 10.240.5.0/24. You can also use ”HTTP.REQ.HEADER(\”User-Agent\”).CONTAINS(\”Chrome\”)” to only apply it to Chrome Users, or use most other type of Expressions. I tried to use HTTP.REQ.USER.ATTRIBUTE(1) and HTTP.REQ.USER.IS_MEMBEROF(\”GroupName\”) expressions, but it seems that these expressions will always evaluate to false for a Rewrite Policy bound to a VPN vServer, so they don’t work, which is a shame.

 

 

For the choice between Native Receiver and HTML5 Receiver to work, you will need to configure your Storefront so that both HTML5 and Native Receivers are possible, like below picture. If you configure ”Always use Receiver for HTML5” instead of ”Use Receiver for HTML5 if local Receiver is unavailable”, then it doesn’t matter that the cookie ‘CtxsUserPreferredClient=Native’ exists. Similarly, if you configure ”Install locally” instead of ”Use Receiver for HTML5 if local Receiver is unavailable”, then Native Receiver will always be used.

If you want want the dynamic choice between HTML5 and Native Receiver, then don’t use ”Use Receiver for HTML5 if local Receiver is unavailable” and only create the ‘CtxsClientDetectionDone’ cookie to suppress the unnecessary prompt for the user.

Feel free to email me at rasmus.kindberg@xenit.se if you have any suggestions or questions related to this blog post.



Netscaler: ADFS protected by AAA – How to handle SAML POST requests

A limitation with Netscaler AAA is that it cannot handle FormData sent in a POST request to a Netscaler LB vServer that is protected by a AAA vServer. What happens is that the Form data in the POST will not be included when the user is redirected back to the LB vServer after AAA authentication. This becomes relevant in scenarios where you have a SAML ServiceProvider (SP) that is configured to do a login POST to an SAML IdentityProvider (IDP) and that IDP is protected by Netscaler AAA.

Below is the process flow:
1. User browses to the SAML SP address https://app1.somedomain.com/saml/login, which in this scenario is the URL that initiates the SAML logon process
2. The SP gives the user a SAML request and the user’s browser performs a POST against the IDP URL https://adfs.mycompany.com/adfs/ls/ with this SAML Request as the Form data.
3. The address https://adfs.mycompany.com points to a Netscaler LB vServer which is protected by AAA, so when Netscaler sees the incoming GET request above it will redirect the user to https://aaa.mycompany.com for AAA authentication (we assume the user has not authenticated against this AAA vServer this web session).
4. User performs AAA authentication, and is afterwards redirected back to the original URL https://adfs.mycompany.com/adfs/ls. HOWEVER, the SAML Request Form data is now missing.
5. User will land on https://adfs.mycompany.com/adfs/ls and receive an error message, because the ADFS server doesn’t know how to handle a request that doesn’t have any SAML form data.

 

Important notes:

  • Form Data passed along with a POST to a LB vServer, such as ADFS, that is protected by AAA will be ‘dropped’ when the user is redirected back to the LB vServer after successful AAA authentication. This only applies if the user has not authenticated against the AAA in the current web session (ie the user does not have a NSC_TMAS cookie). We will make use of this later on.
  • Query values included in a POST are not ‘dropped’, so this flaw is limited to Form data only.

 

Solution/work-around:
The easiest solution is to simply ask the SAML SP to use Redirect instead of POST for the SAML authentication process, but if that is not an option (the SAML SP’s backend code or configuration doesn’t support SAML Redirect) then below is a work-around I’ve been using. Basically what you do is that you store the original SP URL, https://app1.somedomain.com/saml/login, in a cookie in the user’s browser and in step 5 the user will be redirected back to this URL again.

Below is the process flow with a work-around implemented for POST:
1. User browses to https://app1.somedomain.com/saml/login, which in this scenario is the url that initiates the SAML logon process
2. The SP gives the user a SAML request and the user’s browser performs a POST against the IDP URL https://adfs.mycompany.com/adfs/ls/ with this SAML Request as the Form data.
3. The address adfs.mycompany.com points to a Netscaler LB vServer which is protected by AAA, so when Netscaler sees the incoming GET request above it will redirect the user to https://aaa.mycompany.com for AAA authentication.
3b. NEW: When the user is redirected to https://aaa.mycompany.com now, a Rewrite policy will trigger that will create a cookie ”ADFSPostCookieURL” for the user, and this cookie will contain the value ”https://app1.somedomain.com/saml/login”.
4. User performs AAA authentication, and is afterwards redirected back to the original URL https://adfs.mycompany.com/adfs/ls.
5. NEW: We have a Responder policy on our ADFS LB vServer that checks if the path is ”/adfs/ls” and if the cookie ”ADFSPostCookieURL” exists, and if both are true then we read the value in cookie ”ADFSPostCookieURL” and Redirects the user to that URL.
6. User is redirected back to https://app1.somedomain.com/saml/login, which will restart the SAML logon process
7. The SP gives the user a new SAML request and the user’s browser again performs a POST against the IDP URL https://adfs.mycompany.com/adfs/ls/ with this SAML Request as the Form data.
8. A key difference now is that the user already has done AAA authentication this web session and thus has a valid AAA cookie, and won’t be redirected to https://aaa.mycompany.com for authentication. The POST against https://adfs.mycompany.com/adfs/ls/ will therefore happen successfully and the ADFS backend server will see the SAML Form data since that has not been dropped by AAA redirect.
9. Assuming the SAML Request ticket is valid, the ADFS server will give the user a SAML Response ticket and redirect the user to https://app1.somedomain.com/myApp and the user is now logged on to this 3rd party site successfully.

 

Takeaways:

  • Our workaround revolves around storing the original url (https://app1.somedomain.com/saml/login) in some way so we can access it later, and requesting a SAML Request ticket twice from our SAML SP because in the second round we will not be bothered by AAA authentication.
  • Above solution is a bit hacky and involves requesting double SAML tickets from the SP, and there are a lot of Redirects involved, but it works well from an end-user perspective and it enables us to support SAML Post in conjunction with AAA.

 

If you have any questions regarding above solution, or ideas on how to handle above scenario in a better way, please contact me at rasmus.kindberg@xenit.se.

 

 

Below is the Netscaler configuration:



Using NetScaler as OpenID Connect SP with ADFS as IDP

How do you configure Citrix NetScaler OpenID Connect Service Provider with Microsoft ADFS as OpenID Connect Identity Provider? I’ve tried making it easy to understand and how you do it using CLI (NetScaler CLI and powershell).

Read this post for doing this with SAML.



Using NetScaler as SAML SP with ADFS as IDP

How do you configure Citrix NetScaler SAML Service Provider with Microsoft ADFS as SAML Identity Provider? I’ve tried making it easy to understand and how you do it using CLI (NetScaler CLI and powershell).

Before we begin, let us look at what we need to establish the federation:

  • NetScaler (with at least Enterprise license)
  • Active Directory domain and ADFS (read this post if you want to load balance and use NetScaler as ADFS Proxy)
  • Website (lb vserver) we want to protect with AAA (will be referred to as the service provider)
  • AAA vserver to bind SAML Service Provider policy

In my case, the following FQDNs are used:

  • LB vserver: webapp-test.domain.com / LB-WEBAPP-TEST
  • AAA vserver: sp.domain.com / AAA-SP-DOMAIN.COM (note: it will actually not be access by the web browser)
  • ADFS: adfs.domain.com

When installing ADFS two self signed certificates are issued for Token-signing and Token-decryption. When it comes to the NetScaler, we could always use whatever certificate for the signing and decryption – but I recommend using a certificate that isn’t used for web site communication. That’s why I create a self signed certificate that I use: (note: I do this on my computer, modify the variables to match your environment – and even though this certificate and key is self signed – keep them secure)

The certificate (not the key) needs to be copied to the ADFS server for when we create the Relying Party Trust, and we also need to copy the ADFS Token-signing certificate to the NetScaler (below called adfs.domain.com-signing).

Copy the newly created certificate and key to the NetScaler, as well as the ADFS Token-signing certificate:

Now we need to create the SAML Service Provider action and profile, as well as bind it to the AAA vserver:

(Note: As I stated before, this policy is bound to the AAA vserver but the expression is matching the hostname of the LB vserver – since the web browser actually never is redirected to the AAA vserver in this scenario)

As a last step, create (if it isn’t already) an authentication profile and bind it to the LB vserver:

Now configure ADFS (modify the variables to match your need):

 



NetScaler HA heartbeats in Azure

When using NetScaler with multiple NICs in Azure, heartbeats will not be seen on other interfaces other than the one NSIP is configured on.

To resolve this, disable heartbeats on the other interfaces (in my case, NSIP is on 0/1 and disabling on 1/1 and 1/2):

 



Updated: NetScaler Active/Passive HA in Azure with multiple NICs/IPs (DSR/Floating IP)

I wrote a blog post for NetScaler active/passive HA in Azure with multiple NICs two days ago, and I’ve been trying to figure out if this was the best way to do it. In the other post, I was using IPPattern in NetScaler to set the vServers to a /31 – which does work but that’s just because of how the underlying Azure infrastrucuture works (where machines outside of the VM – for example Azure LB – can only access the IP that has been assigned to the VM).

There is another way of doing this, which doesn’t require you to use a /31. The key is in configuring DSR (Direct Server Return) in Azure LB (also known as Floating IP). This will make it possible to use the same VIP on the NetScalers as the Frontend IP of the Azure LB – which saves IP-addresses and is easier to configure. This is the way Citrix has documented it and this is how their HA template does it.



NetScaler Active/Passive HA in Azure with multiple NICs/IPs

Update:

I’ve found out that there’s a much easier way of doing the below in Azure – take a look at the updated blog post:

Updated: NetScaler Active/Passive HA in Azure with multiple NICs/IPs (DSR/Floating IP)

——

There are a lot of information out there about setting up NetScaler HA in Azure. One way is using a single NIC and a single IP for all traffic – which allows for active/passive but causes other limitations. Another way is to use multiple NICs/IPs and use active/active. Both cases uses Azure LB to provide high availability.



Citrix changing default ICA Protocol from TCP to UDP Q4 2017

For XenApp/XenDesktop versions released in Q4 2017 or later (version 7.16 or newer), the default protocol for ICA traffic will be changed from ICA TCP to Enlightened Data Transport (EDT). EDT is a recently-developed protocol from Citrix and is UDP based, unlike traditional ICA which is is TCP based. One of the reasons Citrix developed EDT is because TCP protocols have some drawbacks related to Congestion Control, leading to sub par performance in certain scenarios.

Citrix realizes however that UDP traffic is not always allowed, or configured, in Citrix environments, so they added a new feature called ‘Adaptive Transport’ which will try EDT protocol (UDP) first, and if that does not work it will fallback to using regular ICA over TCP.



RfWebUI idle timeout

There seems to be an issue with the idle timeout in RfWebUI (verified in NetScaler version 12.0) and I’ve created a workaround until it is solved.

It is all based on a JavaScript that checks if the user is logged on, if logged on it starts a timer and when the timer is reached logs the user out.

Change the parameter at the top ”var timeout = xyz” where xyz is the time out in seconds. Because I wasn’t able to only insert this script when the user is logged in (always had to refresh) I chose to create a check that checks every five seconds for the cookie NSC_AAAC which is created upon logon and removed during logout. In this case, we reset the timer if the mouse is moved, a page is loaded or a key is pressed. This can be changed based on your requirements (for example removing document.onclick = resetTimer; if you don’t want a click to reset the idle timer).

When using it in Netscaler, add it like this:

If you are using the NetScaler Web UI to create the rewrite, the action expression will look like this:

 



Remove ”Password 2” from RfWebUI

Update:

Seems like the first method actually removes a password field when changing password. This shouldn’t do that:


Original post:

Have you had an issue with RfWebUI where you need to remove the ”Password 2”-field when for example using RADIUS as primary authentication source (challenge based) and LDAP as secondary?

As always, the great Sam Jacobs has the answer on Citrix Discussions.

If you don’t want to edit any files yourself or not create a a new theme you can use a rewrite to do this for you: (I’m editing style.css and not theme.css)

It should now look as expected: