httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Lam, Eugene" <euge...@amazon.com>
Subject Re: use connection hostname for SNI and SSLProxyCheckPeerCN instead of the Host: header
Date Fri, 12 Apr 2013 06:18:00 GMT
Hi Kaspar,

Thanks for digging up that thread.  I still think SNI needs to be considered, but not in the
way I originally thought!

On 4/10/13 9:43 PM, "Kaspar Brand" <httpd-dev.2013@velox.ch<mailto:httpd-dev.2013@velox.ch>>
wrote:
On 10.04.2013 02:49, Lam, Eugene wrote:
ssl_engine_io.c will pull out this note and use it for SNI and
SSLProxyCheckPeerCN.  Unfortunately, www.example.com does not match
backend.example.com.

I wouldn't call this unfortunate, I would say that it's a
misunderstanding of what SSL proxying with mod_proxy_http is expected to
provide.

To help "iron out" any misunderstanding, I'll repeat what I know.  There's at least 2 types
of ways to configure mod_proxy_http.  I'm only interested in the ProxyPassReverse, not ProxyPass.

In the classic *reverse proxy* setup, the CN is always different between 1) the cert on the
reverse proxy that terminated the original HTTP request and 2) the cert on the backend server
terminating the backend HTTP request.  In other words, the reverse proxy (responding to request
for www.example.com) has already terminated the secure connection with the original HTTP requester.
 The reverse proxy is initiating a new connection with "backend.example.com", assuming "backend.example.com"
is what appeared in the ProxyPassReverse directive.  This is expected, right?

When ProxyPreserveHost is off, everything works fine.  The backend HTTP request's Host header
would be backend.example.com, and mod_ssl sees a cert with CN=backend.example.com.  This is
the expected behavior and is the supported configuration.

Turning on ProxyPreserveHost breaks this by affecting the Host header.  It changes the backend
HTTP request from the ProxyPassReverse value into the value of Host header the original HTTP
requester.

The reverse proxy shouldn't expect CN=www.example.com,
CN=www.example.org, etc. when the backend only has
CN=backend.example.com.

Looks like you're trying to use a "generic" SSL tunnel for any HTTP
request, irrespective of the host name in its URL. This is prone to MitM
attacks, and hardly a good idea. See also this message:

http://mail-archives.apache.org/mod_mbox/httpd-dev/201204.mbox/%3C4F8E7873.8000004%40velox.ch%3E


In my case, the intent of `ProxyPreserveHost on` is to trick the applications at backend.example.com
into thinking it's directly getting the request bound for www.example.com.  The correct way
would have been to rewrite applications to recover the info from X-Forwarded-Host, I don't
deny that.  My guess is, the history/motivation of the ProxyPreserveHost directive is for
compatibility with older, fossilized applications that can only understand Host header and
not X-Forwarded-Host.  It also helps with a reverse proxy that has to talk to both old and
new applications at the same time.

What I take away from reading "SNI with apache 2.4.1 reverse proxy" thread is: use ProxyPreserveHost
at your own risk, it doesn't work quite right for reverse proxy, although it doesn't stop
some users from trying.  It seems to me the Host header is an unstable source for SSLProxyCheckPeerCN
when `ProxyPreserveHost on`.  Is this conclusion logical?

So, I am suggesting a patch for mod_ssl to use the "connection-level" hostname from ProxyPassReverse
for SSLProxyCheckPeerCN.  I think it only *appears* to be like MitM, because the backend is
returning a cert with different CN than the backend request's Host header.  It is still the
job of the proxy server to decide what is expected, right?  In ProxyPreserveHost off case,
it was expecting backend.example.com.  When ProxyPreserveHost is on, it got backend.example.com
still; it shouldn't be any more at risk for MitM.  But, the backend is in a sense ignoring
the SNI.  You are right in that SNI isn't my goal here, the goal is making SSLProxyCheckPeerCN
a bit more sensible without turning it off completely.

Peter Sylvester<http://search.gmane.org/?author=Peter+Sylvester&sort=date> mentioned
that "If something is put into the SNI, it must be identical to what is in the Host:header."
 Perhaps I should leave SNI values alone, but instead introduce a directive called SSLProxyExpectPeerCNSupportsSNI.
 If off, then still proceed if the backend don’t obey SNI but ends up returning a cert with
CN equal to the connection-level hostname.  This way, SNI will still be attempted.  Thoughts?

Eugene Lam


Mime
View raw message