Re: use connection hostname for SNI and SSLProxyCheckPeerCN instead of the Host: header

2013-04-12 Thread Ruediger Pluem


Tom Evans wrote:
> On Fri, Apr 12, 2013 at 7:18 AM, Lam, Eugene  wrote:
>> 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"  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.
>>
>>
> 
> I must be missing something. With ProxyPreserveHost, the backend must
> respond to requests for the frontend hostname. If so, and you wish to
> use SSL for the proxy connection, you should set up the backend so
> that it does have the required certificate, or don't use
> ProxyPreserveHost.
> 
> This whole thing seems to be "I told the proxy to treat
> backend.example.com to act as www.example.com, backend responds to
> www.., but I didn't give it www's certs, so validation fails".
> 
> Using ProxyPreserveHost implies that the backend will correctly
> respond to requests with the frontend's hostname, if that is not the
> case, don't use ProxyPreserveHost.

Or use SSLProxyCheckPeerCN off

Regards

Rüdiger



Re: use connection hostname for SNI and SSLProxyCheckPeerCN instead of the Host: header

2013-04-12 Thread Tom Evans
On Fri, Apr 12, 2013 at 7:18 AM, Lam, Eugene  wrote:
> 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"  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.
>
>

I must be missing something. With ProxyPreserveHost, the backend must
respond to requests for the frontend hostname. If so, and you wish to
use SSL for the proxy connection, you should set up the backend so
that it does have the required certificate, or don't use
ProxyPreserveHost.

This whole thing seems to be "I told the proxy to treat
backend.example.com to act as www.example.com, backend responds to
www.., but I didn't give it www's certs, so validation fails".

Using ProxyPreserveHost implies that the backend will correctly
respond to requests with the frontend's hostname, if that is not the
case, don't use ProxyPreserveHost.

Cheers

Tom


Re: use connection hostname for SNI and SSLProxyCheckPeerCN instead of the Host: header

2013-04-11 Thread Lam, Eugene
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" 
mailto:httpd-dev.2...@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.804%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 
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



Re: use connection hostname for SNI and SSLProxyCheckPeerCN instead of the Host: header

2013-04-10 Thread Kaspar Brand
On 10.04.2013 02:49, Lam, Eugene wrote:
> Was "Re: SSLProxyCheckPeerCN / ProxyPreserveHost issue"
> 
> So, what do folks think about adding this directive to use the
> connection hostname for SNI and the SSLProxyCheckPeerCN feature?
> Would such a directive be beneficial?  It seems a number of users who
> use ProxyPreserveHost will benefit from this.  It lets users revert
> to the behavior before the SNI change.

It's not really "the SNI change" which is the issue, it's the question
of whether you want to ignore cert name mismatches. From your PR:

> 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.

> 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.804%40velox.ch%3E

Kaspar