This is something I have been working on for quite some time… Fact it has been quite a pain in the ass to setup, but I think I finally managed to solve it properly. If anyone sees any issues or something that I haven’t adressed, please leave me a comment either below in the post or on twitter @msandbu
One of the issues with trying to setup Netscaler and Storefront in a multi-tenant are in some cases the:
- Amount of authentication policies needed to hit all the specific domains in a multi-tenant enviroment
- Theme customization, this is by default set at a vServer level, which means that we need a vServer pr customer if we want customization
- We could solve this with multiple Gateway vServers, but with Multiple vServers also means that we need many IP-addresses, which we might not have.
- Multiple customer domains
Now it is possible to bypass Netscaler authentication, and setup the Gateway vServer just act as a ICA-proxy, so authentication happens at the Storefront but this setup does not work for Receiver. Since in a Netscaler Gateway setup, the Receiver needs to authenticate against the Gateway first.
NOTE: This might not be a supported configuration from Citrix, but it works and it requires a regular Netscaler for it to function (Not Gateway VPX)
So from an overview, how does it work?
- We publish Storefront as a LB vServers behind the Netscaler (Meaning that Storefront is accessable from the external network)
- We configure an Gateway vServer, which will handle the ICA traffic.
- We use Responder, Rewrite policies to handle the redirect to the correct URLs.
- We configure Optimal Gateway Routing with direct access on Storefront (Which basically means that all ICA traffic regardless of beacons will be redirected using a Gateway. This feature is not new, but with Storefront 3.1 tech preview this is available in the GUI. We also define that Gateways are being used for HDX routing only, all other auth will happen on Storefront.
- We have one or multiple Storefront stores depending on the requirements for backend setup for instance if we have multiple isolated active directory, and we have defined password verification against DDCs instead of Active directory. This might vary from deployment to deployment but important to remember what are Store specific settings and what are Receiver for web specific settings.
- We can have multiple Gateway vServers to handle communication, but customers still need one URL for storefront setup.
So if we look at the screenshot below, this is a test deployment I did. So when a user starts receiver for the first time and tries to configure his Receiver it will be communicating directly with the Storefront endpoint and configures properly. Depending on what kind of Store the user is accessing this might be done using DDC validation or using Active Directory. Same goes if using Receiver for web, the user connects and my typing his customer name is redirected to the customer website on Storefront. When the user tries to start an application or desktop session, the session will generate an ICA file contaning the Optimal Gateway setting (Which means that even thou in theory it is labeled as inside because of setup) the session will be routed using the Gateway.
So how to set this up?
- First setup a load balanced vServer containing the Storefront servers, using HTTPS/443
- Now I can’t address all configurations on the Storefront with stores and such so I gonna setup a generic Storefront setup where we have the Storefront in a untrusted domain using XML based auth against the DDC, and one simple store and where we have two customer URLs (kunde2.msandbu.org and kunde1.msandbu.org)
First of the base URL should not contain any customer specific reference so in case it should be just an indicator of the service, this is not something the enduser will see unless he for instance opens the receiver configuraiton file.
In my case its just sf.msandbu.org (Setup a wildcard cert on the Storefront server or we can use a SAN or SNI based cert) in my case I have a wildcard cert for the domain msandbu.org
Create a Storefront Store with internal access only, leave everything at default as of now. Create the Receiver for web sites needed for the end customers.
NOTE: I did some changes on the different websites to show how this works from the end-user experience
Note: We can alter what we want for each website, portal customization can be done under the c:inetpubwwwrootcitrix(nameofwebsite) or using the Storefront GUI.
Next we define the Gateway that this store is going to use, this can be done by going into the Store settings –> Optimal HDX Routing
Specify HDX routing usage only and add the external FQDN of the Gateway. (And no the Storefront does not need to be able to communicate with the Gateway, since Auth is done completely at Storefront. After you have added the gateway, click for Direct Access and define which controllers should be used against the optimal gateway
So after this is setup, we need to add rewrite rules and URL transformation for each customer to their website on the Storefront.
Rewrite rules: these are pretty simple just replaces a URL prefix at the end
Then I have an expression that looks at the host name and specificies that the URL must be at the root to it continue
These policies needs to be added to the Storefront LB vServer. Next we also need to have URL transformation policies to define HTTP to HTTPS rules.
Simplest is to add a Netscaler URL transformation profile and add the different URLs
when creating the URL Transformation Profile, the simplest way is to use the HTTP.REQ.IS_VALID expression, since this policy is only being applied once to a storefront vServer, before the end users are being redirected to the HTTPS version
Setup a HTTP vServer Storefront on the same VIP as the SSL based vServer and add the transformation policy. This means that when a user logs inn to http://kunde2.msandbu.org (The HTTP vServer will respond and redirect the user to https://kunde2.msandbu.org and the rewrite will add the /Citrix/Website URL at the end.
After this is setup we can verify that Reciever for web is working
NOTE: (ill come back with how to make the URL much more pretty… )
Now that we can verify that this works we need to configure the Gateway which we described earlier. Go into Netscaler Gateway and setup a new vServer with a VIP which responds on the FQDN that we used in Storefront.
Now you need to define a ICA only vServer, with SSL certificate and STA server. No need for session policies. Now when we log into Storefront and try to start an ICA session we can see the following:
So we can see that the ICA files indicates that we are going using the Netscaler Gateway. Problem solved!
So what are we losing in this setup?
- All auth happens on Storefront, so if we need to have two-factor that has to be integrated with Storefront directly.
- We are using Netscaler Gateway only for routing purposes, which means that VPN goes away.
0 thoughts on “Multitenant guide setup for Storefront and Netscaler with ICA-proxy”
Thank you for the brilliant guide. An issue I’m facing with at the moment is how do I tell a Load Balancer which VDA server to forward the Web Proxy Connection to. I’m assuming you’re also using HTML5 with Websockets?
My understanding is that the controller will create a session on a specific VDA or Worker Agent and the client should then connect back into this server? I’ve no way to tell my Load Balancer how to forward this request to a specific server. Maybe I’m misunderstanding something?
thanks in advance 🙂
Hi Darren, the information to which backend VDA that the load balancer should route the traffic to is based upon information that it gets from Storefront and the DDC. When a user clicks on a desktop it creates an ICA file which contains which VDA session Citrix Reciver should be connected to
Thank you for the response. So when the clients clicks on the application an ICA file is generated and it should say which VDA server to connect to.
But because this is external the connection will of course be sent to the “ICA Vserver” the Vserver needs to know which backed VDA server to send the connection to. Do you know how it accomplishes this? My Web Socket connection doesn’t seem to contain any HTTP Headers to make this decision. Thanks again