Apache ProxyPass HTTPS and remote server with SNI

gaf picture gaf · Dec 8, 2017 · Viewed 8.3k times · Source

I'm wanting to front an AWS APIGateway URL with a reverse proxy in Apache. The reason is due to a process requiring a static IP to provision a service behind a strict firewall and that the current infrastructure has mod_proxy already in place. The solution I'm looking to implement is to simply to route https->https(apiGateway) via mod_proxy.

But.. AWS uses SNI and I can not get mod_proxy to handshake.

I have the following settings enabled

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ProxyPreserveHost On
  SSLProxyEngine On

  ProxyPass /api/1_0/ https://xxx.execute-api.eu-west-1.amazonaws.com/1_0/
  ProxyPassReverse /api/1_0/ https://xxx.execute-api.eu-west-1.amazonaws.com/1_0/

The following logs are available in debug mode

proxy_util.c(2020): AH00942: HTTPS: has acquired connection for (xxx.execute-api.eu-west-1.amazonaws.com)
proxy_util.c(2610): AH00962: HTTPS: connection complete to 52.x.x.x:443 (xxx.execute-api.eu-west-1.amazonaws.com)
AH01964: Connection to child 0 established (server domain.com:443)
AH02003: SSL Proxy connect failed
SSL Library Error: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
AH01998: Connection closed to child 0 with abortive shutdown (server domain.com:443)
AH01997: SSL handshake failed: sending 502

If I connect using openssl, I can demonstrate a similar error

openssl s_client -tls1_2 -connect xxx.execute-api.eu-west-
1.amazonaws.com:443
CONNECTED(00000003)
140735866254216:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert 
handshake failure:s3_pkt.c:1494:SSL alert number 40
140735866254216:error:1409E0E5:SSL routines:ssl3_write_bytes:ssl handshake failure:s3_pkt.c:659:

adding -servername for SNI, results in a valid connection

SSL handshake has read 3601 bytes and written 489 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
...

I therefore believe that mod_proxy and mod_ssl are not sending the servername to the remote https server and could be a bug.

I am running Ubuntu 14.04 with Server version: Apache/2.4.7 (Ubuntu) Server built: Sep 18 2017 16:37:54 OpenSSL 1.0.1f 6 Jan 2014

I have attempted to limit the SSLProxyProtocol to TLS1_2 and the cipher list too however the sslv3 alert handshake failure log still exists regardless.

Has any one come across this and know how to ensure that the SNI values are being sent or is this a restriction in the Apache modules?

Answer

gaf picture gaf · Dec 18, 2017

This is due to ProxyPreserveHost On being set early in the configuration. Setting ProxyPreserveHost Off under a proxy tag completes as expected:

<Proxy "https://xxx.execute-api.eu-west-1.amazonaws.com/1_0">
    ProxyAddHeaders off
    ProxyPreserveHost off
</Proxy>

Info on the directive:

When enabled, this option will pass the Host: line from the incoming request to the proxied host, instead of the hostname specified in the ProxyPass line.

This option should normally be turned Off. It is mostly useful in special configurations like proxied mass name-based virtual hosting, where the original Host header needs to be evaluated by the backend server.