in AppExpert, Customization, NetScaler, NetScaler Gateway

Citrix GW – One GW, multiple customers with different logos


Having all your customers on one CGW for simplicity is superb, but if you need customization you will quickly see it would be nice to have one customer pr GW. Unfortunately you are not allowed to have multiple CGW’s behind a Content Switch, which means each of your CGW’s has to have their own IP.

And that’s kinda what we were trying to avoid.

The design I went: CSVS that took the initial request for logon.customer.com and redirects to logon.cspsite.com.

So I needed a solution that would read the referer, and somehow pass that information onwards to the loading of logon.cspsite.com and show the logos for each individual customer.

A quick analysis of tmindex.html show that i needed to replace https://logon.cspsite.com/vpn/media/citrixgateway_logo_white.png pr. customer.

First i went with the Referer header in the HTTP request. However, that was not a good choice, since that’s only on the initial request to logon.cspsite.com, when the tmindex.html loads all the links, its not showing the referer header in the subsequent request.

Then i went with setting a cookie on the first request to logon.cspsite.com when you request with a referer header and saving the value in a cookie. This didn’t work either, properly for the same reason as above, and I came to the conclusion was that my understanding on how HTTP works were lacking.

Anyways lack of knowledge just means you need to put more gas in the tank to get the same distance.

So a bit of analysis on the URL in question gave me insights on where it was being requested from, which turns out to be: https://logon.cspsite.comk/logon/LogonPoint/receiver/css/ctxs.large-ui.min.css

I needed a way to forward a parameter to that CSS request that then would be able to set a Referer on the picture(citrixgateway_logo_white.png)  request which i then would be able to match in a rewrite policy and serve the logo for logon.customer.com

Tmindex.htm requests this css with this html code:

   <script type=”text/html” id=”large-ui-styles”>

       <!– #start-concat-css ctxs.large-ui.min.css –>

<link href=”receiver/css/ctxs.large-ui.min.css” rel=”stylesheet” />

<link href=”/logon/themes/Default/css/theme.css” rel=”stylesheet” id=”gatewaycustomStyle” />

       <!– #end-concat-css –>

   </script>

First I needed a parameter that i would be able to parse somehow, and I ended with a GET parameter on the tmindex.html?fromfqdn=logon.customer.com, this part was easy.

Then I needed a way to call the CSS with the parameter i transfer from the original request to logon.customer.com

Javscript for the rescue! Adding the code following to tmindx.html did the trick.

<script type=”text/javascript”>

           if (window.location.search.includes(“fromfqdn”)) {

               var newlink = ‘<link rel=”stylesheet” id=”large-ui-styles” href=”receiver/css/ctxs.large-ui.min.css’ + window.location.search + ‘”/>’;

           } else {

               var newlink = ‘<link rel=”stylesheet” id=”large-ui-styles” href=”receiver/css/ctxs.large-ui.min.css”/>’;

           }

           document.write(newlink);

       </script>

Next, adding this to tmindex.html from a policy, else it would properly vanish in an upgrade.

Just before the css is being referenced, there is this section:

       <noscript>

           <link href=”receiver/css/ctxs.no-js-ui.min.css” rel=”stylesheet”/>

       </noscript>

Replacing the </noscript> with </noscript> + the javascript code was the task at hand, and that was also fairly easy.

Here is what i ended up with:

A responder policy on the CSVS and would redirect to https://logon.cspsite.com/logon/LogonPoint/tmindex.html?fromfqdn=logon.customer.com

A rewrite (responder) that adds javascript to tmindex.html

A rewrite (request) that modify the request citrixgateway_logo_white.png

Logo for logon.customer.com uploaded to /var/netscaler/logon/LogonPoint/custom/logon.customer.com.logo.png

In NetScaler (ADC) Conf:

On the VPNVS:

add rewrite action RWACT_logo_url replace HTTP.REQ.URL “\”/logon/LogonPoint/custom/\” +   HTTP.REQ.HEADER(\”Referer\”).TO_LOWER.AFTER_STR(\”fromfqdn=\”) + \”.logo.png\””

add rewrite action RWACT_replace_logo_js2 replace_all “HTTP.RES.BODY(99999)” q|”</noscript><script type=\”text/javascript\”> if (window.location.search.includes(\”fromfqdn\”)) {  var newlink = ‘<link rel=\”stylesheet\” id=\”large-ui-styles\” href=\”receiver/css/ctxs.large-ui.min.css’ + window.location.search + ‘\”/>’; } else { var newlink = ‘<link rel=\”stylesheet\” id=\”large-ui-styles\” href=\”receiver/css/ctxs.large-ui.min.css\”/>’;}  document.write(newlink);</script>”| -search “text(\”</noscript>\”)”

add rewrite policy RWPOL_logo “HTTP.REQ.URL.TO_LOWER.EQ(\”/vpn/media/citrixgateway_logo_white.png\”)” RWACT_logo_url

add rewrite policy RWPOL_inject_js “HTTP.REQ.URL.CONTAINS(\”/logon/LogonPoint/tmindex.html\”)” RWACT_replace_logo_js2

bind vpn vserver VPNVS_logon -policy RWPOL_logo -priority 100 -gotoPriorityExpression END -type REQUEST

bind vpn vserver VPNVS_logon -policy RWPOL_inject_js -priority 100 -gotoPriorityExpression END -type RESPONSE

On the CSVS:

add responder action RSACT_to_logon redirect “\”https://logon.cspsite.com/logon/LogonPoint/tmindex.html?fromfqdn=\” + HTTP.REQ.HOSTNA    ME” -responseStatusCode 302

add responder policy RSPOL_to_logon true RSACT_to_logon

bind cs vserver CSVS_entry_portal -policyName RSPOL_to_logon -priority 100 -gotoPriorityExpression END -type REQUEST

Wish for christmas:

Make the themes more flexible in their binding. Or some lightweight method to do customizations (just replace pictures based on the incoming request)

What do you think?

Comment