I have an application (JVM 1.8.0_31-b13, Spring MVC 4.2.4, Security 4.0.3) deployed on Tomcat 7 (7.0.68) and I'm using an AWS ELB to handle requests from client.
In my application, I try to get the client ip address using the X-forwarded-for header. If I don't find it, then I use the method getRemoteAddr of the HttpServletRequest class.
And I have noticed several things when I log informations in the application:
First:
The header x-forwarded-for is always null
Second:
The remote address is sometimes the same as the elb ip and sometimes it's the same as client ip address.
I have noticed that:
when the remote address is the same as the client ip address then the request is considered as secured and the scheme is https (method isSecure and getScheme)
when the remote address is the same as the elb address ip then the request is not considered as secured and the scheme is http (method isSecure and getScheme)
Here's the valve configuration in server.xml:
<Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="X-Forwarded-Proto" internalProxies="172\.(1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}|10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}" />
Here's an example of elb address ip: 172.31.xxx.xxx
I don't understand:
Why the x-forwarded-for header is always null.
And why some requests are considered as secured and some are not.
Related
I'm running a Tomcat webserver on http port 8080. In front I have an Apache that handles https ssl connections.
How can I know if the client made a request using http:// or https://? Because the following shows http always, because the Apache internally sends only http:8080 requests to the Tomcat of course. So the initial scheme requested is lost here.
HttpServletRequest req;
req.getRequestURL().toString(); // always shows http://....
Apache should add following request headers as explained in mod_proxy docs:
X-Forwarded-For - The IP address of the client.
X-Forwarded-Host - The original host requested by the client in the Host HTTP request header.
X-Forwarded-Server - The hostname of the proxy server.
Additionally X-Forwaded-Proto with the original protocol can be added as explained in this example:
<VirtualHost *:443>
<strong>RequestHeader set X-Forwarded-Proto "https"</strong>
If I am using HTTP I can get the normal IP address but if I am using HTTPS it returns the proxy server's IP address. How can I get the IP address of the client and not the proxy server?
A proxy will generally add a X-Forwarded-For header see here which will contain the IP address of the real client.
Note there's no difference between HTTP and HTTPS in terms of the IP addresses you can see on a request, they will both give you the IP address of the User-Agent that originated the request.
To obtain the client IP address in my ASP.NET application I've used the X-Forwarded-For, and get the first IP address from the list (accordingly to the information I've found, there is a client, proxy1, proxy2..). But I've heard recently that it is better to get this information from X-Forwarded-IP header because the client IP address in X-Forwarded-For can be modified by proxy, what is the difference, and which one address should I use?
X-Forwarded-For is the conventional way of identifying the originating IP address of the user connecting to the web server coming from either a HTTP proxy, load balancer.
X-Forwarded-IP is the conventional way of identifying the originating IP address of the user connecting to the email server through an HTTP mail service.
X-Forwarded-For is a non-standard header, introduced originally by Squid. It is a proxy- specific header, that helps a server identify the original requestor of a call that did pass-through the proxy - so obviously any proxy on the request path should/will modify X-Forwarded-For. Without proxy on the request path, this header shouldn't even be in the request.
Because this header is non-standard, there is no guarantee you'll get it, and the way it is handled can differ on the proxy implementation. You have no guarantee either that it will contain a proper IP.
Since 2014, the IETF has approved a standard header definition for proxy, called "Forwarded", documented here https://www.rfc-editor.org/rfc/rfc7239 that should be use instead of X-Forwarded headers. This is the one you should use reliably to get originating IP in case your request is handled by a proxy.
In general, the proxy headers (Forwarded or X-Forwarded-For) are the right way to get your client IP only when you are sure they come to you via a proxy. If there is no proxy header or no usable value in, you should default to the REMOTE_ADDR server variable.
I have deployed my web application on Tomcat 6.0 in machine having ip address 10.xx.xx.90. Then i am making a http request(from browser) to this app from m/c having ip address (10.xx.xx.56).
I am trying to get the IP address of client(10.xx.xx.56) in my app using the below code. But I am getting null value for request.getHeader("X-FORWARDED-FOR") where as request.getRemoteAddr() returns the ip address of the machine on which the application is deployed i.e 10.xx.xx.90.
But, if I make a http call to the application from standalone java program I am able to get the client m/c ip address. So, what is the correct way to get the client IP address. Do I need to configure something in my tomcat ??
String ipAddress = request.getHeader("X-FORWARDED-FOR");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
If you are using a reverse proxy you should know it. However, the end-client could presumably be behind a regular web-proxy. Anyway, the load balancer or proxy would set "X-Forwarded-For". From the Wikipedia article,
The X-Forwarded-For (XFF) HTTP header field is a de facto standard for identifying the originating IP address of a client connecting to a web server through an HTTP proxy or load balancer.
Based on your comments and question there isn't a proxy or load balancer. For best practices I would recommend you check that header first. If it's null then use request.getRemoteAddr() (which you reported as working).
We have a JSF application , serving the requests via tomcat ajp protocol. The entire web site is sitting behind Cloudflare CDN. When the following code is executed
String ipaddress = httpServletRequest.getHeader(HTTP_CF_CONNECTING_IP);
The ipaddress is always null.
httpServletRequest.getRemoteAddr()
always gives the cloud flare ip address.
Have found this http://danielmiessler.com/blog/getting-real-ip-addresses-using-cloudflare-nginx-and-varnish for websites using jninix.
Do we have a similar solution for apache http server
Found solution by loading
LoadModule cloudflare_module modules/mod_cloudflare.so
This sets the remote ip instead of cloudflare's ip