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.2...@velox.ch<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.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