tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Schultz <>
Subject Re: [OT] Forward TLS connection information from AWS ELB -> httpd -> Tomcat
Date Thu, 02 Oct 2014 20:06:16 GMT
Hash: SHA256


On 10/1/14 10:26 AM, Christopher Schultz wrote:
> I'm interested in using AWS ELB for SSL termination but allowing
> the client's TLS connection information to be forwarded all the
> way through the chain to Tomcat.
> The setup looks like this:
> ELB /\ /  \ /    \ w0    w1 /  \   / \ t0  t1 t0  t1
> (t0 and t1 are repeated because otherwise the diagram would be
> even more difficult to read).
> w0 and w1 are running Apache httpd, t0 and t1 are running Tomcat.
> The client's connection is TLS terminated at ELB and whether the 
> connections between ELB/wx/tx are encrypted should be immaterial.
> I'm using mod_jk from httpd -> Tomcat.
> ELB provides the following HTTP headers to wx: X-Forwarded-For
> (client's IP) X-Forwarded-Port 	443 X-Forwarded-Proto 	https
> Unfortunately, it looks like I can't get things like the cipher 
> default, etc. but I'm okay with that for the time being.
> I'm wondering two things:
> 1. How can I get Apache httpd to trust that the connection is
> encrypted? I want to be able to use "RequireSSL" for certain
> resources and have httpd trust that the connection coming from the
> ELB is in fact secure.
> 2. How can I use that connection information to tell mod_jk that
> things are to be trusted as well?
> For #2, I might just be able to use SetEnv to set 
> REMOTE_ADDR=X-Forwarded-For, but I'm not sure how to say "yes, this
> is encrypted". Should I set up a separate VirtualHost on a
> different (non-80) port that is configured only for ELB connections
> and then force SSL to "on" regardless of the actual incoming
> connections?
> That would allow me to use port 80 for "regular" web traffic and
> not have to worry about proper checking to make sure that the
> connection was in fact coming from the ELB and not directly into
> the web server.

I have some information for those wanting to do this.

Here is a write-up someone did for how to get Apache to log things
appropriately when using AWS ELB:

Here are the two configurations I was able to get working and a few
notes about them.

I would highly recommend that anyone using ELB set up an ELB-only
VirtualHost that only handles requests being proxied through the ELB.
This will protect you against some misconfigurations, etc. that might
allow remote users to get access to resources they should not, or be
able to forge certain parts of the request.

Something like this:

<VirtualHost *:81>
  (remaining configuration)

Remember that you will have to "Listen 81" somewhere.

If you have httpd 2.4, then you have mod_remoteip out of the box.
That's nice:

    # Trust AWS ELB's X-Forwarded-For header
    # This will set REMOTE_ADDR to the client's real IP
    RemoteIPHeader X-Forwarded-For

    # Handle ELB requests; maintain client information
    SetEnvIf X-Forwarded-Proto "https" HTTPS=On
    SetEnvIf X-Forwarded-Port "(.*)" JK_LOCAL_PORT=$1

That last SetEnvIf is nearly entirely useless (because nobody really
cares about users' port numbers), but I put it in there for completeness.

Also, mod_remoteip will adjust the value of the REMOTE_ADDR
environment variable -- which is visible to CGI-style programs as well
as mod_jk/Tomcat/etc. but *it will not work in log files* if you use
"%h" as your remote-ip log format. You will have to use "%a" instead.
On AWS Linux, the httpd package comes with both "combined" and
"common" log formats defined using "%h" so you'll have to change those
to "%a".

If you have httpd 2.2. instead, you'll have to do things a bit
differently (unless you want to use the back-port of mod_remoteip for
httpd 2.2):

    # Handle ELB requests; maintain client information
    SetEnvIf X-Forwarded-Proto "https" HTTPS=On
    SetEnvIf X-Forwarded-For "(.*)" REMOTE_ADDR=$1 JK_REMOTE_ADDR=$1
    SetEnvIf X-Forwarded-Port "(.*)" JK_LOCAL_PORT=$1
    <Location "/">
      Order deny,allow
      Deny from all
      Allow from

If you want to log properly, I think the best thing to do is change
"%h" (or "%a") in your log formats to "%{X-Forwarded-For}i" or, if you
want to be super-correct, you want to do something like this:

    # The following line has been split over multiple lines.
    # httpd doesn't support this; it's for email readability only
    SetEnvIf X-Forwarded-For \
        "^.*?(\d{1,3}+\.\d{1,3}+\.\d{1,3}+\.\d{1,3}+)" \
    LogFormat "... %{XFFCLIENTIP}e ..." format-name
    CustomLog access_log format-name

This won't get you the right client IP address in error.log, though.
I'm not exactly sure how to do that. Apparently, setting REMOTE_ADDR
is only useful for CGI-style interaction and has no effect on how
httpd does logging, etc.

It also seems that you cannot re-define a LogFormat. I tried
re-defining my "combined" log format in a VirtualHost and it did not
work. Using a different LogFormat nickname gave me better results.

Hope that helps,
- -chris
Version: GnuPG v1
Comment: GPGTools -


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message