I’m just setting up a Web Application Firewall on a Citrix NetScaler 11.1 for a costumer’s shop. My costumer mandated: most of the website has to be available via HTTP. However we don’t want to expose sensitive information to the internet, so we had to create a policy redirecting users to SSL when ever needed.
So how can we do this? First of all I had to find out: which information is sensitive? It takes some time, you have to explore the application (basically a web shop).
Next: how to redirect to SSL, and thereby preserve the URL?
The policy expression
The policy has to be flexible. I want to be able to redirect users from where ever to the same URL via https. So my policy has to be a responder policy. Subtype: redirect.
add responder action res_act_send2ssl redirect "\"https://\"+HTTP.REQ.HOSTNAME + HTTP.REQ.URL.HTTP_URL_SAFE" -responseStatusCode 302
What does it do? It redirects to
"https://", appends the server name specified (
HTTP.REQ.HOSTNAME). If there is just one host name you could rather do something like
"https://hostname.exampe.com". Next it appends the URL (
HTTP.REQ.URL). The parameter
HTTP_URL_SAFE is not needed. It converts all URLs into save URLs, so for examlpe
/logon Page is converted into
/logon%20Page. It’s good practice to do so.
Last not least: the HTML status code: I’m usually very exact about html status codes: 302 is a temporary redirect, while 301 is a permanent redirect. There is no difference from perspective of a browser: the browser will redirect. However crawlers, like Google™, will make a big difference: it will follow a 301 (and delete the previous content from it’s index), it might not follow a 302 (as it is only a temporary redirect and will be gone soon). In this case we didn’t want crawlers to follow, so we stayed with 302, the Citrix NetScaler default.
My policy had to be flexible. One of the requirements: We need to add URLs to it, when we come across a new URL. So I came up with the idea to use a Pattern Set.
I prefer string maps over
expression1 || expression2 || ... || expressionn constructions for several reasons: It’s more effective from perspective of NetScaler RAM and CPU (so it causes less load to NetScalers), and even more important, it’s easier to understand, and it’s easier to maintain. Just add an other URL to the Pattern Set.
add policy patset WebApp_secureURLs bind policy patset WebApp_secureURLs "/login" -index 1 ...
so this will create a Patern Set, containing URLs. This URLs will be used in the policy expression. You’ll simply have to add URLs if you needSSL for additional URLs
The Policy expression, using a pattern set
add responder policy res_pol_send2ssl "HTTP.REQ.URL.CONTAINS_ANY(\"WebApp_secureURLs\")" res_act_send2SSL
This will create a policy expression using a pattern set.
HTTP.REQ.URL us the URL (not containing the host name),
CONTAINS_ANY means, the URL has to contain any of the objects inside my pattern set. We could also use
ENDSWITH_ANY. It depends on, weather you are able to specify the URL exact enough or not (we can’t).
(\"WebApp_secureURLs\") specifies the pattern set to be used. The double quotes
" have to be masked with
\" in command line as policy expressions have to be set in double quotes (
" ... ").