Certificate Authentication Behind a Bastion Host

I needed Certificate Authentication on a Bastion host. I was pointed to the article from Zeitoun.net (below) by a friend, but it did not work with Apache 2.2.

Apache took my SSL_* variables and passed them along as HTTP_SSL_* variables. This is ok, but not good enough if I don’t want to change source code.

After hacking it a little I found the following seemed to work:

Bastion:

#LoadModule proxy_module   modules/mod_proxy.so
#LoadModule headers_module modules/mod_headers.so
LoadModule ssl_module     modules/mod_ssl.so

Listen 443


AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl

SSLPassPhraseDialog  builtin
SSLSessionCache         shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout  300
SSLMutex default
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin

SSLCryptoDevice builtin


<VirtualHost _default_:443>
Servername bastion
# this did not work the way I wanted
# SSLProxyEngineSSLProxyMachineCertificateFile /usr/local/etc/proxyUser.crt

ErrorLog logs/bastion_error_log
TransferLog logs/bastion_access_log
LogLevel warn

SSLEngine on

SSLProtocol all -SSLv2

SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM

SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

SSLCACertificatePath /usr/local/etc/auth/

SSLVerifyClient require
SSLVerifyDepth 2

SSLOptions +ExportCertData

   <Proxy *>
     AddDefaultCharset Off
     Order deny,allow
     Allow from all
   </Proxy>
 
   # initialize the special headers to a blank value to avoid http header forgeries
   RequestHeader set SSL_CLIENT_S_DN    ""
   RequestHeader set SSL_CLIENT_I_DN    ""
   RequestHeader set SSL_SERVER_S_DN_OU ""
   RequestHeader set SSL_CLIENT_VERIFY  ""
   RequestHeader set SSL_CLIENT_S_DN_CN ""
 
   <Location />
     # add all the SSL_* you need in the internal web application
     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_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s"
 
     ProxyPass          https://internal/
     ProxyPassReverse   https://internal/
   </Location>

SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog logs/bastion_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

</VirtualHost>                                  

On the Internal machine
Turn off Client SSL Authentication
# SSLVerifyClient require
and add the following for each SSL variable that you need
SetEnvIfNoCase SSL_CLIENT_S_DN_CN “(.*)” SSL_CLIENT_S_DN_CN=$1

Cool thing is that I can run HTTPS on the backside, just not Client Certificate authentication.

http://www.zeitoun.net/articles/client-certificate-x509-authentication-behind-reverse-proxy/start
http://www.askapache.com/htaccess/setenvif.html
http://httpd.apache.org/docs/2.2/mod/mod_headers.html
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
http://httpd.apache.org/docs/2.2/mod/mod_ssl.html