Spring Boot with embedded Tomcat behind Apache proxy

Rop picture Rop · Aug 22, 2014 · Viewed 45.4k times · Source

We have a Spring Boot (Spring MVC) app with embedded Tomcat on a dedicated appserver behind an Apache SSL proxy.

The SSL port on the proxy server is 4433, forwarding to port 8080 on the appserver.

So the URL to the proxy server is forwarding like:

https://proxyserver:4433/appname   >>forward>>   http://appserver:8080/

When running WITHOUT proxy, the first thing that happens is that
Spring Security redirects the request, like:

http://appserver:8080/   >>redirect>>   http://appserver:8080/login

to display the login form, by extending WebSecurityConfigurerAdapter with

  ...
  httpSecurity.formLogin().loginPage("/login") ...
  ...

It works fine without the proxy, but WITH proxy the redirect needs to be changed,
so Spring should instead redirect to the corresponding proxy URL, like:

http://appserver:8080/   >>redirect>>   https://proxyserver:4433/appname/login

but no success yet.

I am trying to apply this solution: 59.8 Use Tomcat behind a front-end proxy server

We have configured mod_proxy in Apache, and verified that it sends the expected headers:

X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https

The application is started with parameters:

export ARG1='-Dserver.tomcat.protocol-header=x-forwarded-proto' 
export ARG2='-Dserver.tomcat.remote-ip-header=x-forwarded-for'
java $ARG1 $ARG2 -jar webapp.jar

Still the redirect does not work.

It will keep redirecting locally, to http://appserver:8080/login which is not available to the clients.

Is there anything else we need to do to make this scenario work?


UPDATE

Also, I am concerned about the "/appname" part in the proxy URL. On the appserver the application is rooted at "/". How should Spring be instructed that "/appname" should be included in all URLs sent back to the clients, when going thru the proxy?

Answer

Igor Mukhin picture Igor Mukhin · Dec 14, 2015

I had the same problem the other day. After some debugging of Spring Boot 1.3 I found the following solution.

1. You have to setup the headers on your Apache proxy:

<VirtualHost *:443>
    ServerName www.myapp.org
    ProxyPass / http://127.0.0.1:8080/
    RequestHeader set X-Forwarded-Proto https
    RequestHeader set X-Forwarded-Port 443
    ProxyPreserveHost On
    ... (SSL directives omitted for readability)
</VirtualHost>

2. You have to tell your Spring Boot app to use these headers. So put the following line in your application.properties (or any other place where Spring Boots understands properties):

server.use-forward-headers=true

If you do these two things correctly, every redirect your application sends will not go to http://127.0.0.1:8080/[path] but automatically to https://www.myapp.com/[path]

Update 1. The documentation about this topic is here. You should read it at least to be aware of the property server.tomcat.internal-proxies which defines the range of IP-addresses for proxy servers that can be trusted.