If you work with Netscalers, you already know how SNIPs and MIPs work. They are the IPs that communicate with your servers. Every packet from the outside world that passes through the Netscaler will hit your server as though it was coming from this IP. This is the default behavior on a Netscaler.
Unfortunately if your servers require the client’s true IP address, all you will see for every client will be the SNIP or MIP address you are using. Here are a few examples I have personally had to deal with:
– IIS requires client IP for IIS logs
– IIS requires client IP for ACL filtering
– Web application requires client IP for it’s own logging purposes
– Web application requires cilent IP for authentication
Now to get around this for IIS, you can install ISAPI filters and set your Netscaler to use a custom header to store the true client IP address and pass that along with every packet. The ISAPI filter in IIS would look for this particular header and log that instead of the SNIP/MIP. There’s a very nice Client IP extraction ISAPI filter with some great instructions located on this page from Citrix or you can even write your own:
http://support.citrix.com/article/CTX119347
This is great for logging but sometimes your web application may grab the IP address from web server variables. To return the IP address of the host making the request, the server variable that your ASP, ASP.NET, and PHP code will call is “REMOTE_ADDR”. Unfortunately REMOTE_ADR is going to have your SNIP IP and not the client IP when passing through the Netscaler. The good news is that if you have control of your code, you can make it call from a different location that includes the client IP your ISAPI filter is passing. So if your code currently uses:
Request.ServerVariables("REMOTE_ADDR")
then switch it to:
Request.ServerVariables("http_client_ip")
where “http_client_ip” is the real client IP address and not the SNIP. Everything will work fine after that.
Here’s a nice snippet of code you can run on your web server and hit from your client browser to see what all the Netscaler is passing to the server:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<html/> <body/> <p/> NS SNIP or MIP IP address: <%Response.Write(Request.ServerVariables("remote_addr"))%> <br/> <b/>The NS Inserted Client IP:</b/> <%Response.Write(Request.ServerVariables("http_Client_ip"))%> <br/> Accept Encoding: <%Response.Write(Request.ServerVariables("HTTP_ACCEPT_ENCODING"))%> <br/> Cookies: <%Response.Write(Request.ServerVariables("HTTP_COOKIE"))%> <br/> </body/> </html/> |
(***NOTE: I apologize in advance if my website messes up the code block above. If you have issues with it, I will host a .txt file here with the code. Just post a comment below if you need it.)
This is all well and good when you have access to the code and can make this change but what about web apps that are 3rd party and you cannot modify the code? Well then you have no choice but to use the USIP (Use Source IP) feature on the Netscaler. What this does is pass the client IP straight through the Netscaler to your backend server so that the SNIP or MIP you are using on your Netscaler is never seen by the server (except for monitor probes from the Netscaler itself of course). This option is disabled by default. It can be applied to the entire Netscaler or turned on and off per service.
Best practice is not to use it and avoid it as much as possible. The reason is that using the USIP feature means you are going to lose very important features on the Netscaler such as connection multiplexing and surge protection. It’s always better to use the Client IP header insertion instead. In fact to date I have personally never enabled USIP in any environment I have built so far.
Here’s a very excellent and recent article from Citrix on the pros and cons of using USIP mode:
http://support.citrix.com/article/CTX121974
I hope this helps anyone trying to get around Client IP address related issues. Please feel free to post a comment on your own experiences or suggestions.
Jason Samuel is a visionary product leader and trusted advisor with a proven track record of shaping strategy and driving technology innovation. With extensive expertise in enterprise end-user computing, security, cloud, automation, and virtualization technologies, Jason has become a globally recognized authority in the IT industry. His career spans consulting for hundreds of Fortune 500 enterprises across diverse business sectors worldwide, delivering cutting-edge digital solutions from Citrix, Microsoft, VMware, Amazon, Google, and NVIDIA that seamlessly balance security with exceptional user experiences.
Jason’s leadership is amplified by his dedication to knowledge-sharing as an author, speaker, podcaster, and mentor within the global IT and technology community. Recognized with numerous prestigious awards, Jason’s contributions underscore his commitment to advancing technology and empowering organizations to achieve transformative results. Follow him on LinkedIn.
Eric Smith
June 6, 2011 at 9:04 AM
Hi Jason,
Just curious: Why could you not just enable the Client IP insertion on the load balancing service?
Jason Samuel
June 14, 2011 at 11:38 PM
@Eric Smith
Hi Eric, enabling Client IP is part of the solution. If you just enabled it and did not use the ISAPI filter, IIS would only log the SNIP. You have to instruct IIS to pull the new Client IP that is being inserted by the Netscaler in the custom header. This is where the ISAPI filter comes in to play. It’s a 2 part solution.
Zaher
December 2, 2011 at 4:20 PM
How can we do the same thing with weblogic instead of IIS?
Josh
January 30, 2012 at 12:09 PM
This post was very helpful. Thanks!
deepti
July 9, 2013 at 7:05 AM
hi
we have an issue with one of our netscaler VPX. Users at a particular site are unable to access the https site (note , doesnt work with http as well). We are able to access the site without any issues but users get IE cannot display the page. Checked all ports and all are open.. Ran nstcpdump.sh and for user’s machine and port 443. Can see the requests coming from users machine to NS but not gng back.
Pls guide.
Kari Ruissalo
April 13, 2017 at 7:24 AM
What if I write the REMOTE_ADDR header with NetScaler rewrite on to the response? Like in this article:
https://support.citrix.com/article/CTX123676
… slightly modified like this:
add rewrite action rw_act_insert-http-header_REMOTE_ADDR insert_http_header REMOTE_ADDR CLIENT.IP.SRC
add rewrite policy rw_act_insert-http-header_REMOTE_ADDR true rw_act_insert-http-header_REMOTE_ADDR
bind lb vserver vs_ssl_myserver.domain.dom -policyName rw_act_insert-http-header_REMOTE_ADDR -priority 100 -gotoPriorityExpression END -type RESPONSE
Jason
November 27, 2017 at 1:42 PM
Hi,
I am trying to get client ip to filter out the external and internal users trying to access my site. I get null when i use “http_client_ip” and when i use “Remote_ADDR” i get an IP associated with netscaler. I have also used HTTP_X_FORWARDED_for and it returns null or empty. Server is DMZ and uses citrix netscaler. I have tried almost all the server variables available but none of them helped me get client real ip.
Kari Ruissalo
November 30, 2017 at 8:23 AM
Jason, add the Client IP in the NetScaler Service Group/service. Enter “X-Forwarded-For”. This should send the client IP to the back with the header. So if your backend can identify that field, that should do the trick.
krishna
July 24, 2018 at 6:43 AM
HI Jason,
Thanks for sharing your knowledge.
I am struggling to attach the client IP header to backend servers. I have configured x-forwarded-for in client IP filed of NetScaler service group and bound it to virtual server. But I do not have any joy as it is not working. you script does anything different to GUI config which I have done in NetScaler load balancing? how could I run this script on storefront server which are load balanced behind the VIP? could you also please send me the script in txt file?
Many Thanks,
Krishna