Tricks to do client certificate authentications behind a reverse proxy

The most classical reverse proxies utilizations are:

  • The reverse proxy is located on a DMZ (public Internet exposed area)
  • Web applications are located on a VLAN (private network)
  • The reverse proxy reads the initial request, then it initiates a similar (but new) request to the internal Web applications.

The problem we are tackling in this article is about X509 client certificate authentications. By definition and for security, a HTTPS request clear content cannot be spied. This is why when putting a reverse proxy behind the client and the internal web application, the HTTPS stream will be broken and we will loose all the client certificate data.

Here is some tips to forward without many efforts the client certificate data to the web application:

Between apache and apache

In this situation, the reverse proxy is an apache and the internal web application is also an apache. The tip is to use the headers modules to manually forward the wanted client cert data. Of course for security reasons, you have to configure your reverse proxy to only allow wanted client certificate (based on the AC for example).

On debian, to activate the headers module, just type this command:

sudo a2enmod headers

Then you have to edit the appropriate reverse proxy virtual host directive this way:

Listen 1981
NameVirtualHost *:1981
<VirtualHost *:1981>
   ServerName localhost
 
   ErrorLog /var/log/apache2/1981.error.log
   CustomLog /var/log/apache2/1981.access.log combined
 
   # activate HTTPS on the reverse proxy
   SSLEngine On
   SSLCertificateFile    /etc/apache2/ssl/mycert.crt
   SSLCertificateKeyFile /etc/apache2/ssl/mycert.key
 
   # activate the client certificate authentication 
   SSLCACertificateFile /etc/apache2/ssl/client-accepted-ca-chain.crt
   SSLVerifyClient require
   SSLVerifyDepth 2
 
   <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  ""
 
   <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"
 
     ProxyPass          http://localhost:50161/
     ProxyPassReverse   http://localhost:50161/
   </Location>
</VirtualHost>

The important directives are the RequestHeader lines. You can found a complete list of the SSL environement variables at the online apache documentation.

Between apache and tomcat

In this situation, the reverse proxy is an apache again and the internal web application is a tomcat server. The tip is to use the AJP protocol. Once your tomcat is configured with an AJP connector, you just have to configure HTTPS with a special option (+ExportCertData) on your apache reverse proxy.

Listen 1979
NameVirtualHost *:1979
<VirtualHost *:1979>
   ServerName localhost
 
   ErrorLog /var/log/apache2/1979.error.log
   CustomLog /var/log/apache2/1979.access.log combined
 
   SSLEngine On
   SSLCertificateFile    /etc/apache2/ssl/mycert.crt
   SSLCertificateKeyFile /etc/apache2/ssl/mycert.key
 
   SSLCACertificateFile /etc/apache2/ssl/client-accepted-ca-chain.crt
   SSLVerifyClient optional
   SSLVerifyDepth 2
 
   # this option is mandatory to force apache to forward the client cert data to tomcat
   SSLOptions +ExportCertData
 
   <Proxy *>
     AddDefaultCharset Off
     Order deny,allow
     Allow from all
   </Proxy>
 
   ProxyPass / ajp://localhost:8009/
   ProxyPassReverse / ajp://localhost:8009/
 
</VirtualHost>

Discussion

sebastien queguinersebastien queguiner, 2009/02/05 17:05

Hello,

I have a problem with client certificate authentication on Apache configured as a reverse proxy. I have followed your tricks to do client certificate authentications behind a reverse proxy and it doesn't work for me. Here is a short description of my problem:

Internet ===(http/https)=====⇒ Apache 2 (RP) Server ======(https)===⇒ IIS Server

The client authentication works on the RP but the certificate informations aren't forwaded to the IIS Server. Here is the configuration of the apache vhosts:

<VirtualHost 192.168.1.40:80>
        ServerName      192.168.1.40
        SSLEngine       Off
	ErrorLog /var/log/apache2/toto.error.log
        CustomLog /var/log/apache2/toto.access.log combined
#        ProxyPreserveHost        Off
	Redirect permanent / https://10.211.81.40/
</VirtualHost>
 
<VirtualHost 192.168.1.40:443>
	ServerName	XXXXXXXXXXXXXX
	ErrorLog /var/log/apache2/toto.error.log
        CustomLog /var/log/apache2/toto.access.log combined
        LogLevel debug
 
        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl.crt/XXX.crt
        SSLCertificateKeyFile /etc/apache2/ssl.key/XXX.key
 
	SSLCACertificatePath /etc/apache2/ssl.crt
	SSLVerifyClient require
	SSLVerifyDepth 2 
	#SSLOptions +ExportCertData +FakeBasicAuth +StrictRequire +StdEnvVars
 
        <Proxy *>
        AddDefaultCharset Off
        Order deny,allow
        Allow from all
        </Proxy>
 
        SSLProxyEngine          On
        #SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
 
# 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_V_START  ""
        RequestHeader set SSL_CLIENT_V_END  ""
        RequestHeader set SSL_CLIENT_M_VERSION  ""
        RequestHeader set SSL_CLIENT_M_SERIAL  ""
        RequestHeader set SSL_CLIENT_CERT  ""
        RequestHeader set SSL_CLIENT_VERIFY  ""
        RequestHeader set SSL_SERVER_M_SERIAL  ""
        RequestHeader set SSL_SERVER_M_VERSION  ""
        RequestHeader set SSL_SERVER_I_DN  ""
        RequestHeader set SSL_SERVER_CERT  ""
 
<Location />
	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_CERT "%{SSL_CLIENT_CERT}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"
        RequestHeader set SSL_SERVER_CERT "%{SSL_SERVER_CERT}s"
 
	ProxyPass https://IIS_SERVER/
        ProxyPassReverse  https://IIS_SERVER/
 
</Location>
 
</VirtualHost>

I would be very grateful if you could give me a piece of advice… Thanks

sebastien

Stéphane GullyStéphane Gully, 2009/02/05 18:53

To debug this problem, I think you should:

  • disable https between apache RP and IIS server
  • tcpdump the HTTP request between the apache RP and the IIS server
  • look in the headers if you found the SSL client data
Huiyu.ChouHuiyu.Chou, 2010/07/08 07:13

Could you please show me how to config with “Between Apache and IIS Server”.

I am in a situation just like Sébastien, I used his configuration code, and tried your advice, however my code in IIS server still can not read the Client Certificate.

Please help me, I really need this to work. Thanks very much.

sebastiensebastien, 2009/02/06 10:18

Thanks for the answer. I'll try this.

Sébastien

KevinKevin, 2011/01/12 01:47

Hi Sébastien,

Did you ever get resolution on this issue? We are trying to do the same thing, Apache to IIS using SSL and cannot get it to proxy that way. Did you ever get yours working? Are you willing to share what you did?

Thanks,

Kevin

Micheal Micheal , 2009/03/25 08:02

Hi, Guys kindly advice me! I wanna reverse to another web server as ur guys. but the problem is that web server(where will be reversed) does not belong to me. I cannot do anything in that web server. But My task is to evaluate wethere that client certificate are correct by authentication of reverse server.

My question is How I can get response from reversing server by sending them my client certificate. I need know the respond if reverse server. Thanks !!!

wojtiwojti, 2009/12/10 14:10

You saved my life :) Thx

RaphRaph, 2011/01/27 16:21

Hi, My question is : why the first apache proxy send to http://localhost:50161/ and the other apache proxy listen in port 1979 and https. How is possible ??

For the moment, my second proxy received the REQUEST header but AJP not deal the header and i have a message : java.lang.runtime.exception : Client certificat reuqired ……

DevoxDevox, 2011/06/17 14:01

Hi guys!! Very good arcticle about trick with apache proxy, but tell me, anyone had experience with nginx and apache/IIS?

So the idea is - client—ssl/certificate—> Nginx —-ssl/certificate—>Apache/IIS.

They need to use the same certificate on both nginx authorization and apache. Trying to figure out how to make it possible, but confused with headers which i need to set to make apache accept/IIS certificate. May be you have any ideas how to work this out?

JeremyJeremy, 2011/07/15 17:54

The problem with IIS/Apache is that the proxy request actually sets up a separate HTTPS session between Apache and IIS using the Apache server certificate as the basis for the SSL tunnel.

Apache/Tomcat is a special case with the AJP connector, because the AJP connector is specifically written to allow forwarding of the client SSL information.

EricaErica, 2011/08/01 16:54

I'm attempting to configure apache to do something similar…I'm using apache provided by Oracle (version 2.0), and I get the following error when trying the above trick:

Unrecognized Header or RequestHeader directive %s

I've verified the vars that I'm using do indeed exist for 2.0, and it seems to not complain until it load the RequestHeaders in a Location section. It doesn't complain about the ones used under "# initialize the special headers to a blank value to avoid http header forgeries"

venkateshvenkatesh, 2011/11/23 11:09

HI, iam using nginx as my webserver & reverse proxy and thin is my application server. ihave installed my ssl certificate in proxy server. the problem is–We have purchase "Premium EV SSL (2 Years)(annual) certificate" for our domain "www.mysite.com". when we type "www.mysite.com" in url it opens site with green coloured "https:" with lock symbol, but when we login to our site with a username and password-it doesn't show that green coloured "https". It shows "https" in black colur and lock symbol with orange coloured triangle. when i click on that lock it displays the following message –"Your connection to www.mysite.com is encrypted with 256-bit encryption. However, this page includes other resources which are not secure. These resources can be viewed by others while in transit, and can be modified by an attacker to change the look of the page." why and What is the problem? where to make changes to display green coloured "https" in the address bar. In this case how to install ssl certificate.

Stéphane GullyStéphane Gully, 2011/11/23 11:55

Your problem is related to HTTP ressources (javascript, css ..) which are included in your HTTPS page. Try to look the HTML source code and search for http string (without s)

Enter your comment
 
 
 

Recent changes RSS feed Valid XHTML 1.0 Valid CSS Driven by DokuWiki