In one of my previous posts I installed badstore.net on my XenServer. This was not that easy, i solved all problems, however the results had not been so very good. There are 2 reasons for this:
- Badshop uses a java script to forward users to https://www.badshop.net/cgi-bin/badstore.cgi. So it will forward all your requests to an external website, even if you host it on your own environment.
- some of the hyperlinks on the web page are no relative links but link to https://www.badstore.net/something.cgi
- some of these hyperlinks forward to an ssl- url.
As I had to fix this using my NetScaler as badstore boots from a CD image.
So let’s start with number 1:
Ok. We have rewriting policies on a NetScaler, and we may use NetScaler rewriting policies to change content on a website. Unfortunately I could not really understand edocs about search and replace on websites. There are some blog articles about customizing NetScaler logon page, however they also had been of hardly any use to me. In the end I found a page describing rewriting for NetScaler 8.x, but I use NetScaler 10.5. The page was not completely right and very outdated, but it helped me finding my way.
The NetScaler rewrite action:
add rewrite action rw_act_badstore_net2local replace_all "HTTP.RES.BODY(22528)" "\"badstore.mydomain.local\"" -pattern www.badstore.net
This is what it would look like if I’d rather used the GUI of 10.5:
- The type of rewrite action is replace_all. We want to replace all www.badstore.net with our internal url badstore.mydomain.local!
- Where do we replace? In the first 22528 byte of the server response’s http response (but no header fields): http.res.body(22528)
The number should be as small as any possible if you host big pages to avoid unnecessary load on our NetScaler. I did not give it a try: this is just 22 kBt, so a near to unlimited size *lol*
Following Curtis’s suggestion:HTTP.RES.BODY(HTTP.RES.CONTENT_LENGTH)
would be all of the body, dynamically adapted. - which text should get replaced?
www.badstore.net
. That’s the pattern we’re searching for! - which text should be there instead?
badstore.mydomain.local
To be understood by the processing engine this string has to be in quotes, however the string itself has to be quoted too. So we add quotes, but we need to add a second set of quotes.""badstore.intern.mydomain.local""
would not do the trick as""
would be both, the beginning and the end of quotes. So we have to mask the 2nd set. That’s what\"
does. Did you understand? I’m so sorry. No matter if you understand or not: use it the way I did, it worked for me and it will work for you too!
The NetScaler rewrite policy
add rewrite policy rw_pol_badstore_net2local true rw_act_badstore_net2local
This adds a NetScaler rewriting policy. The filter is true, so all responses get rewritten. Be careful on this as it may be a waste of ressources! The policy action is the rw_act_badstore_net2local action described above.
bind lb vserver badstore.mydomain.local -policyName rw_pol_badstore_net2local -priority 100 -gotoPriorityExpression NEXT -type RESPONSE
- This will bind this very policy (rw_pol_badstore_net2local) to my vserver badstore.mydomain.local. Never bind a policy like that globally as it will process all responses of all servers. This may lead to unwanted behaviour, i.e. this blog would not work as the blog is hosted behind this very NetScaler! It is also a waste of resources as the string has not to be exchanged on any other website hosted behind this NetScaler!
- The priority of this Policy will be 100, and we will also process the next policy. This was nescesary as we will have to fix this https problem (problem number 3).
- And last, not least: This is a response policy. It will never affect requests.
What did this do?
It solved problem 1 and also problem 2!
All hyperlinks, but also our java script now points to badstore.mydomain.local. Even the SSL hyperlink mentioned in problem 3 points to the right domain!
NetScalers are rather cool, don’t you think?
Problem number 3
You may have guessed: there is no more problem about that. We create a 2nd replace policy and replace https with http. I don’t screen shot this policy as it is very similar to the first one, however I add the command here.
add rewrite action rw_act_badstore_https2http replace_all "http.RES.BODY(22048)" "\"https://\"" -pattern "https://"
I hope this helps having some fun with your NetScaler!
Best
[…] Customizing a website using rewrite policies 2015-02-18 […]
Thanks a lot! It was very helpful for me.
I’m glad I could help 🙂
Hi, I tried using your procedure to replace http with https in netscaler 10.5.57 by inverting the https and http in your query but the body of the page doesn”t get the replaced URL. What version of netscaler did you use to make this works ?
Cividan, I used 10.5. 55.8, but it also works with version 11.. There are some prerequisites to work. I”ll send a mail to you, I hope I can help 🙂
Hi,
How did you know to use 22048? I”m looking to replace strings in the content, but I don”t know where in the payload the strings will occur.
I started with 1024 (1k) and it was too little, so I did 2k, but it wasn’t enough, so I added a 2nd 2 in front of it (that’s why this is a funny number like that)
You can also target the entire html body by using HTTP.RES.BODY(HTTP.RES.CONTENT_LENGTH)
Oh, great, Curtis! You’re definitely right! I have overseen this. Thank you very much, I’ve already learned a little bit today :). I’ve fixed my blog.
You are writing very good blog on Netscaler, Thanks for this.
I”ve to setup a policy on NetScaler like this
From http://mydomain.com/abc/* to https://yourdomain.co.uk/xyz/*
Thanks. I am glad you like it 🙂
Hi,
It looks like a very nice tutorial but it is not working vor me on NetScaler 11. It try the following:
Users enter a URL like this: test.domain.com/xyz
When the user hits the enter button, it will end in this: test.domain.com/xyz/1000:123242356778,
My goal is that I just want the fqdn as URL name visible in the Address bar of the Browser. So in this case only test.domain.com.
Have you any idea?
Hi
I have a question regarding to HTTPS Status Response Code Policies. I hope,that I can describe exactly my Problem.
My Question can be see in below:
If my web page https://example.com can be called from outside,the HTTPS response code should adapt appropriate requirements
1 – if the request “/subscribe/” is a must if you should start header “Authorization Basic”.
If that does not have, the answer should be the 403rd
2 – “/ subscribe/search” must only be accessible by POST
3 – “/ subscribe/document” must only be accessible with GET
If the rules does not correspond to Article 2 and 3, the request should give appropriate error 422 Unprocessable Entity answer.
How can I create policies?
Best Regards
Just to try a quick answer, I’m currently on holidays and can’t spend. The Policy condition has to be something like http.req.url.startswith “/subscribe/search” && http.req.methode.eq post. http.req.url.contains “/subscribe/” && http.req.header “Authorization Basic” exists. …; In the end you would bind a responder Policy (condition simply true) responding with what ever error code you like (422).
Be aware about default policies being case sensitive! So if you use a case insensitive webserver (i.e. IIS) you may have to make your policies case insensitive!
Hi – Thanks for taking your time to put this together unfortunetely for me the above instructions did not work. I have using netscaler 11.1 Any further thoughts. Thank you
What did you want to rewrite? We can only rewrite html, no css, no scripts, …
This is a great example for rewrite. Thanks,
I was using URL transform for an SSL offload implementation. The site runs oracle SSO and does a series of redirects, It authenticates on port 7777, and displays content on 7778 all http. The SSL offload works fine with transform on NS 10.5, However one of the functions generates links to embedded javascript. Here is where this tutorial/example SHINES! According to Citrix escalation support the only way to do SSL offload for scripts is with a rewrite replace_all as explained here. It works!
Our SSL offload is 98% working. My only issue now is that the rewrite replace_all has to SKIP one particular part of the responses generated. Notice that the rewrite policy filter is set to true. So I need to Not to apply the policy for one particular URL. I tried a filter in the policy to match only the URL where the filter needs applied but it looks as if it ignores the filter and applies the rewrite all the time. Here is the filter in the policy I tried.
add rewrite action post-act-78 replace_all “HTTP.RES.BODY(1200000).SET_TEXT_MODE(ignorecase)” “\”csmstest.bctrain.cty\”” -pattern sy00011.bc.broward.cty
add rewrite policy policy_modify_post-78 “HTTP.RES.BODY(1200000).contains(\”/reports/\”)” post-act-78
bind lb vserver http_78_lb_svc -policyName policy_modify_post-78 -priority 100 -gotoPriorityExpression NEXT -type RESPONSE
Maybe you could add something like !HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/test”) to the policy filter. This would be true if the url (made case insensitive) is not /test?
Great blog Johannes!
Netscaler documentation seems to indicate that you can’t do multiple rewrites on the response body but I’ve seen two examples from you that do this. We’re on Netscaler v11..
A site we have needs multiple paths and a domain name changed in the response from the server, scattered throughout the body, but only the first rewrite action (REPLACE_ALL) gets applied. This is an unfortunate requirement due to a bad 3rd party site design.
I’ve raised a support call with Citrix but wondered if you knew what a fix may be.
Many thanks.
You can. I think this is a misunderstanding. 2 policies can’t depend on each other, this is as they get applied at the same time in the end of the packet processing process.
Does the succeeding policies get hit? Is the goto expression in bindings NEXT?