3

I want to setup ELB to terminate SSL at load balancer and communicate with backend instances over HTTP. I have uploaded valid certificate on ELB. When I set up following configuration

ELB - HTTPS

Backend - HTTP

Then if application performs redirect in application, client/browser is redirected to HTTP instead of HTTPS.

Although, if I set ELB to use HTTPS and backend instances also on HTTPS(even using self signed certificate) everything works fine as both the configurations are on HTTPS!

I am using Tomcat on backend instances and do not want to use any other layer in between(e.g. nginx or haproxy)

4 Answers 4

4

I found this article which seems pretty similar to your problem: http://willwarren.com/2014/01/27/running-apache-tomcat-with-ssl-behind-amazon-elb/

Basically states on changing server.xml to this:

<Connector
    port="8080"
    protocol="HTTP/1.1"
    proxyPort="443"
    scheme="https"
    secure="true"
    proxyName="myapp.example.com"
    connectionTimeout="20000"
    URIEncoding="UTF-8"
    redirectPort="8443" />
3

I had a tough time finding this over the net and finally i found a way to do it.

The problem was that as soon as http redirected to https port on ELB internally it used to get redirected back to port 80 thus creating a loop. This happens because ELB offloads the SSL and then connects to port 80 again.

Finally after some research i got the correct rewrite rule to manage X-Forwarded-Proto in such a way that even if ELB offloads the SSL tomcat gets to now that the origin request was using SSL.

This is done using Tomcat Valves on Tomcat 8. Am sure it can be done on earlier versions too. I have enabled rewrite rules on Tomcat using valves. After that it was as simple as writing redirect rules on Apache.

Here are the steps:

Step 1: a. Open context.xml under tomcat conf folder b. Paste the following line just below

<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

Note : This will enable the valve globally. In case this needs to be enabled for specific host then it should be pasted inside the of server.xml for that particular domain

Step 2:

a. Open conf/server.xml b. Paste the following line just above </Host> tag

<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

Step 3:

a. Open the folder where web.xml is. For example if the application is hosted under ROOT then web.xml will be under webapps/ROOT/WEB-INF

b. Similarly if the application is hosted under webapps/myappfolder then the web.xml will be under webapps/myappfolder/WEB-INF

c. In the WEB-INF folder Create a new file rewrite.config. and paste the following rewrite rule:

RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
2

The rewrite.config rules in Ravi's answer did not work for me. Using Tomcat 8.0.32, AWS ELB and EC2 my rules are:

# bounce all requests coming in on HTTP to HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} ^http$
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]

BTW: remember HTTP redirects with 301s are cached in the browser and if it works once, you won't see it work again until you get rid of the browser cached redirect

0

This might be a old question but it was hard to find the answer. There are two problems here 1. Tomcat web container is receiving requests on http so the redirects it would construct would be on the same. Spring helps upto some length but falls short. 2. Redirecting the user to HTTPS even if they are trying to access HTTP

The second problem is easy one since ELB sends this information in header. It can be done by adding a simple code in the existing filters or in a new one

String protocol =req.getHeader("X-Forwarded-Proto");
    if(protocol!=null && "http".equalsIgnoreCase(protocol)){
        rep.sendRedirect( req.getRequestURL().toString().replaceFirst("http", "https"));
        return;
    }

For the first problem one of the solutions that worked for me was adding additional property (redirectHttp10Compatible) in the view resolver for spring servlet.

<bean id="tilesviewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">

    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" />
    <property name="redirectHttp10Compatible" value="false" />
 </bean>

Life was good if only the redirects were issues by spring but since the problem is with the container itself it required more help. The final solution is to manipulate the server.xml and add a RemoteIpValve property for the tomcat engine JavaDoc for RemoteIpValve

This one was the final fix. Hope that helps.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .