I need to set up a forward proxy with 2-way SSL verification. I got pretty far using Apache 2.4.10 on Debian, but it fails because the certificate CN is compared to the wrong name. I've searched and read every page that remotely mentions something similar, but I can't find the solution.
Setup:
- tomcat server running on http://localhost:8080 with namebased virtual hosts
- when triggered each of the vhosts sends a request to https://externalserver.com:443/uri
- the SSL connection should provide the certificate belonging to the vhost and verify the certificate of the externalserver
I've set up a virtual host in Apache 2.4.10 for each tomcat vhost, with the following configuration:
<Virtualhost *:80> ServerName domain1.example.com SSLProxyEngine On ProxyVia On SSLProxyMachineCertificateFile /proxysetup/certs/domain1.example.certandkey.pem # server certificate verification SSLProxyCACertificatePath /proxysetup/ca SSLProxyCARevocationCheck leaf SSLProxyCARevocationPath /proxysetup/crl SSLProxyVerify require SSLProxyVerifyDepth 4 SSLProxyCheckPeerName off SSLProxyCheckPeerCN on SSLProxyCheckPeerExpire on ProxyPass /external https://externalserver.com/ ProxyPassReverse /external https://externalserver.com/ <Proxy "*"> Order deny,allow Allow from all </Proxy> LogLevel Debug ErrorLog /proxysetup/logs/domain1.example-error-80.log CustomLog /proxysetup/logs/domain1.example-access-80.log combined </VirtualHost>
When I start a request (http://domain1.example.com/external/someuri) I see the SSL handshake taking place but fails with the following error
SSL Proxy: Peer certificate CN mismatch: Certificate CN: EXTERNALSERVER.COM Requested hostname: domain1.example.com
The connection is then closed.
When adding ProxyPerserveHost off
the handshake stops even before this check is performed.
What needs to be done to get the certificate successfully verified?
UPDATE
I managed to get this working by changing the configuration to:
<Virtualhost *:80> ServerName domain1.example.com SSLProxyEngine On SSLProxyMachineCertificateFile /proxysetup/certs/domain1.example.certandkey.pem # server certificate verification SSLProxyCACertificatePath /proxysetup/ca SSLProxyCARevocationCheck leaf SSLProxyCARevocationPath /proxysetup/crl SSLProxyVerify require SSLProxyVerifyDepth 4 SSLProxyCheckPeerName off SSLProxyCheckPeerCN off SSLProxyCheckPeerExpire on ProxyPass /external/ https://externalserver.com/ ProxyPassReverse /external/ https://externalserver.com/ ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/ <Proxy "*"> Require all granted </Proxy> <Proxy "*/external/"> # only allow local requests # and only if the server certificate contains the correct FQDN Require all denied Require local SSLRequire %{SSL_SERVER_S_DN_CN} in {"externalserver.com"} </Proxy> LogLevel Debug ErrorLog /proxysetup/logs/domain1.example-error-80.log CustomLog /proxysetup/logs/domain1.example-access-80.log combined </VirtualHost>
Update 2
There is still something wrong:
- When I change
SSLRequire %{SSL_SERVER_S_DN_CN} in {"externalserver.com"}
to
SSLRequire %{SSL_SERVER_S_DN_CN} in {"somethingelse.com"}
I still get a connection. Even when adding SSLOptions +StrictRequire
- When I set
SSLProxyCheckPeerName on
The certificate of the server (externalserver.com) is matched to domain1.example.com. I would expect it to match to 'externalserver.com'
Am I doing something wrong or did I stumble upon a bug?