Apache reverse proxy with self-signed certificate
I run a Unifi hardware appliance which comes with a self-signed certificate, issued on unifi.local
. For my current setup, it's not an option to import a certificate on the appliance directly for several reasons, so I tried to get rid of the invalid certificate message of my browser by using an apache2-based reverse proxy which provides access to the appliance under another domain, secured by a Letsencrypt certificate.
My current setup looks like the following:
Laptop <-> Apache Reverse Proxy (2.4.48, Debian, trusted wildcard domain certificate) <-> Unifi appliance (self-signed certificate)
My idea is to provide a secured domain called unifi.mydomain.tld
which allows secure access to the appliance.
In my apache reverse proxy, I created and enabled a config file which looks like following:
<IfModule mod_ssl.c>
<VirtualHost *:443>
Serveradmin [email protected]"
ServerName unifi.mydomain.tld
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPass "/" "https://10.0.1.1/"
ProxyPassReverse "/" "https://10.0.1.1/"
ProxyPreserveHost Off
TransferLog /var/log/apache2/proxies/unifi_access.log
ErrorLog /var/log/apache2/proxies/unifi_error.log
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
</IfModule>
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLCipherSuite SSL ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384
SSLCipherSuite TLSv1.3 TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
SSLOpenSSLConfCmd DHParameters /mnt/certificates/diffie-hellman/dhparam4096.pem
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off
SSLCertificateFile /etc/letsencrypt/live/mydomain.tld/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.tld/privkey.pem
</VirtualHost>
# Originally from /etc/letsencrypt/options-ssl-apache.conf
# Written directly here because otherwise SSLProtocol etc is overwritten
# Add vhost name to log entries:
SSLOptions +StrictRequire
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
</IfModule>
However, if I access unifi.mydomain.tld
, my browser returns the certificate for unifi.local
and not for unifi.mydomain.tld
and hence, it creates an error that the certificate is not trusted. Several tips mentioned to turn SSLProxyVerify
to none
, and SSLProxyCheckPeerName
, SSLProxyCheckPeerCN
, and SSLProxyCheckPeerExpire
to off
, however, none of these tricks worked. It's not an option for me to import Unifi's self-signed snakeoil certificate on my reverse proxy server.
I'm not sure whether apache2 itself complains about the certificate or returns the wrong certificate. How am I able to get access to the appliance by browsing unifi.mydomain.tld
without getting this certificate error?
Solution 1:
This worked for me!
Requirements:
- Apache Tomcat on :8443 with self-signed key
- Apache HTTPD with Reverse Proxy to localhost:8443 Tomcat
- Apache HTTPD REQUIRES Client Mutual Authentication. If that is not a requirement for you, then set: SSLVerifyClient none
- Apache HTTPD will pass along the X.509 identity of the caller through the reverse proxy to tomcat.
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
ProxyRequests On
ProxyPass /test1 https://localhost:8443/test/
ProxyPassReverse /test1 https://localhost:8443/test/
# SSL Settings for the DMZ
SSLEngine on
SSLProtocol TLSv1.2
SSLCipherSuite HIGH:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateKeyFile /home/jdoyle/sample_httpd_server_example_root_ca_.key
SSLCertificateFile /home/jdoyle/sample_httpd_server_example_root_ca_.cer
SSLCACertificateFile /home/jdoyle/consolidated_cacerts.cer
# SSL Settings for the Reverse Proxy
SSLProxyEngine on
SSLProxyVerify require
SSLProxyProtocol TLSv1.2
SSLProxyCheckPeerName off
SSLProxyCACertificateFile /home/jdoyle/consolidated_cacerts.cer
SSLVerifyClient require
SSLVerifyDepth 10
# Pass the SSL Conext on to tomcat
RequestHeader set SSL_CLIENT_S_DN "%{SSL_CLIENT_S_DN}s"
RequestHeader set SSL_CLIENT_I_DN "%{SSL_CLIENT_I_DN}s"
RequestHeader set SSL_SERVER_S_DN_OU "%{SSL_SERVER_S_DN_OU}s"
RequestHeader set SSL_CLIENT_VERIFY "%{SSL_CLIENT_VERIFY}s"
RequestHeader set SSL_CLIENT_V_START "%{SSL_CLIENT_V_START}s"
RequestHeader set SSL_CLIENT_V_END "%{SSL_CLIENT_V_END}s"
RequestHeader set SSL_CLIENT_M_VERSION "%{SSL_CLIENT_M_VERSION}s"
RequestHeader set SSL_CLIENT_M_SERIAL "%{SSL_CLIENT_M_SERIAL}s"
RequestHeader set SSL_CLIENT_VERIFY "%{SSL_CLIENT_VERIFY}s"
RequestHeader set SSL_SERVER_M_VERSION "%{SSL_SERVER_M_VERSION}s"
RequestHeader set SSL_SERVER_I_DN "%{SSL_SERVER_I_DN}s"
....
SSLOptions +ExportCertData +StrictRequire
....
Notes:
a. SSLProxyCACertificateFile is for the httpd<->tomcat connection and contains the Public Key of the Tomcat Server's self-signed cert.
b. SSLCACertificateFile is for the DMZ <-> httpd connection, and must contain and and all of the CA Certs for any inbound connection.