This applies to any situation involving a proxy, regardless of SSL.
As I understand your problem, Tomcat does not know its own publicly exposed protocol/hostname/port, and therefore produces erroneous links/redirects. The cause of this is that Tomcat only sees the request sent by the Apache proxy, which uses some internal protocol/hostname/port. Tomcat has no way of knowing what protocol/hostname/port values the client is expecting.


The fix is to add some extra headers to the proxy request. These headers will give Tomcat a clue as to what the "real" protocol/hostname/port values are.

mod_proxy automatically adds these headers to the backend request:
X-Forwarded-For     (original IP)
X-Forwarded-Host    (original Host header)
X-Forwarded-Server  (proxy IP)

but to communicate the protocol (http/https) to the backend you need to add that manually in httpd.conf: (using mod_headers)
RequestHeader set X-Forwarded-Proto https env=HTTPS
RequestHeader set X-Forwarded-Proto http env=!HTTPS



The next step is to make sure Tomcat reads these new headers and overrides its default values for request.serverName, request.secure, request.scheme, etc Again, I have never done this myself on Tomcat (with Jetty you simply set "forwarded"=true) but Tomcat's documentation mentions a filter that supposedly does this for you:

     <filter>
       <filter-name>RemoteIpFilter</filter-name>
       <filter-class>org.apache.catalina.filters.RemoteIpFilter</filter-class>
       <init-param>
         <param-name>remoteIpHeader</param-name>
         <param-value>x-forwarded-for</param-value>
       </init-param>
       <init-param>
         <param-name>remoteIpProxiesHeader</param-name>
         <param-value>x-forwarded-by</param-value>
       </init-param>
       <init-param>
         <param-name>protocolHeader</param-name>
         <param-value>x-forwarded-proto</param-value>
       </init-param>
     </filter>

RemoteIpFilter does not mention any support for "X-Forwarded-Host", but if that's not supported you can instead set the "Host" header on the backend request by setting "ProxyPreserveHost On" in httpd.conf. With that setting, Apache will use the "Host" header from the original request when communicating with the backend.

Also, if you happen to use an earlier version of Tomcat, with no RemoteIpFilter, you can use XForwardedFilter instead; it does the same thing:
http://code.google.com/p/xebia-france/wiki/XForwardedFilter

Martin

On Mon, 19 Sep 2011 17:08:50 +0200, Michael Molloy <tapestrya...@gmail.com> wrote:

Unless I'm misunderstanding, I don't think this would apply since all SSL is being handled at the load balancer, correct? I apologize, I think I introduced that confusion at the beginning.

--Michael

On Sep 19, 2011, at 9:52 AM, Martin Strand wrote:

Typically, when SSL is offloaded to an Apache proxy, that proxy should add a number of X-Forwarded-* headers to any requests sent to the backend. The servlet container then uses those headers to set up request.scheme, request.secure, request.remotAddr, etc so that they match the original request sent to the proxy.

With Jetty, all you have to do to support this is set forwarded=true on the connector in question. I haven't used Tomcat for a long time, but this page seems to have the info you need:
http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#Basic_configuration_to_handle_'x-forwarded-for'_and_'x-forwarded-proto'


On the Apache side, mod_proxy automatically adds these headers:
X-Forwarded-For     (original IP)
X-Forwarded-Host    (original Host header)
X-Forwarded-Server  (proxy IP)
( see http://httpd.apache.org/docs/current/mod/mod_proxy.html#x-headers )

But you need to add X-Forwarded-Proto manually, using mod_headers:
RequestHeader set X-Forwarded-Proto https env=HTTPS
RequestHeader set X-Forwarded-Proto http env=!HTTPS


Once this is done, and Tomcat is configured to take these headers into account, you won't need to fiddle around with any BaseURLSource since the webapp will be able to get all the info it needs directly from the Request object.

If you happen to be using an old version of Jetty or Tomcat, where there is no support for X-Forwarded-* headers, you can use this servlet filter instead:
http://code.google.com/p/xebia-france/wiki/XForwardedFilter

Martin

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to