14

Can any one guide me in working with X-FORWARDED-PROTO header in Java web application deployed to Apache Tomcat.

The application setup is in such a way that tomcat talks with Apache webserver, which in turn talks with Cisco Load Balancer, finally the balancer publishes the pages to the client (tomcat -> apache2 -> load balancer -> client).

The SSL Certificate is installed in Load Balancer and it's handling HTTPS requests. My requirement is to make the application behave in such a way that it uses the X-FORWARDED-PROTO and change the pages as HTTP or HTTPS.

Checking on the header files of my webpages I could not find the X-FORWARDED-PROTO header. I don't have access to the Load Balancer configuration either, and the IT has suggested us to use the X-FORWARDED-PROTO to differentiate between HTTP and HTTPS request.

Is there any configuration to be done in Tomcat or Apache level so that it will return the X-FORWARDED-PROTO header? Or is it that the configuration should be handled in Load Balancer?

informatik01
  • 16,038
  • 10
  • 74
  • 104
Manoj
  • 141
  • 1
  • 1
  • 5

2 Answers2

28

I am pretty sure you have it all figured out by now but I will add the answer nonetheless.

You can use the class org.apache.catalina.valves.RemoteIpValve in the engine tag in conf/server.xml of tomcat.

    <Valve className="org.apache.catalina.valves.RemoteIpValve"
           internalProxies="192.168.1.XXX"
           remoteIpHeader="x-forwarded-for"
           remoteIpProxiesHeader="x-forwarded-by"
           protocolHeader="x-forwarded-proto"
    />

Something to note that is very important is to set the internalProxies value. If this is not set and you are you using a non-standard network setup it could cause some issues where tomcat will not check for x-forwarded headers and it will default to "http". For security reasons I'd recommend to set it even if it works with the defaults.

Look here for more information.

Yaro
  • 13
  • 3
Allan
  • 281
  • 3
  • 3
  • 1
    If you're using Apache to proxy requests to Tomcat, you need to add this to your SSL config in Apache: RequestHeader set X-Forwarded-Proto "https" – James Cooper Jul 02 '13 at 18:42
  • 4
    Tomcat 7 fields are slightly different - http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html – Alex Dean May 19 '14 at 13:21
  • 1
    You said "For security reasons I'd recommend to set it even if it works with the defaults." Can you elaborate? I've been wondering if this should be set even if the proxying IP(s) are in the default allowed ranges. – em_bo Oct 05 '18 at 16:14
  • This answer is perfect. @Allan Thanks for stressing the importance of internalProxies, that was what I was missing. – codependent Jan 11 '19 at 12:40
  • Note that you only actually need to set `protocolHeader="X-Forwarded-Proto"` (and maybe `internalProxies` depending on your setup). The rest comes with default values that should be fine in most cases. Specifically IP is already re-written (so `remoteIpHeader` and `remoteIpProxiesHeader` is not needed). – Nux May 11 '20 at 15:04
  • Almost working for me. I connect like `https://site:8888`, adding the seeing to my server.xml fixed the issue of it forwarding to `http://site:8888/login`. It now forward to https correctly in the URL. However, it looses the port. So `https://site:8888` goes to `https://site/login`... how do you get the port kept too? – user1667016 Oct 26 '22 at 15:49
0

Add this to your apache vhost managing connections

<VirtualHost *:80>
  ...
  RewriteEngine On
  RewriteCond %{HTTP:X-Forwarded-Proto} !https
  RewriteRule !/status https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</VirtualHost>

this assumes your health check is /status, which doesn’t require https

hernangarcia
  • 584
  • 2
  • 6
  • 14