Ssl – Apache2.4: Forward proxy for client certificate authentication to IIS7

apache-2.4httpsiis-7PROXYssl

We have a Asp.Net 1.1 web services (https://dev-ms01/MsgService/default.asmx) running on IIS7 (win server 2008 standard), we have configured client certificate authentication in IIS and below is the .netcode for
ClientCertificate authentication

private void Authenticate(DataTable dtUserMap,HttpContext context)
    {
        /// Convert the serial number from IIS to the DC format
        /// which is: no dashs octets are in proper order.
        string SerialNum = context.Request.ClientCertificate.SerialNumber.Replace("-","");

        Debug.WriteLine("Authenticate User with cert = " + SerialNum);

        /// get the column names from the table
        string[] columnNames = new String[dtUserMap.Columns.Count];

        /// populate the string array with the names
        for(int i=0;i<dtUserMap.Columns.Count;i++)
        {
            columnNames[i] = dtUserMap.Columns[i].ColumnName;
        }

        /// Run a select query with the serial number
        DataRow[] rows = dtUserMap.Select("SerialNumber='" + SerialNum + "'");
        if (rows.Length==1){
            /// the user exits
            Debug.WriteLine("User Authenticated");
            // further logic
        }
        else
        {
            /// either too many users or not any users
            Debug.WriteLine("No single User Found");
            context.Items.Add("IsAuthenticated",false);
        }
    }

We are setting up an apache2.4 server to support TLS 1.2 and also acts as proxy for the IIS , below is the apache configuarion

<VirtualHost *:443>
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"  
ServerName  secure-dev-ms01
SSLEngine on
SSLProtocol -ALL TLSv1.2

SSLVerifyClient optional
SSLVerifyDepth  3


<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "C:/elm/apache/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>


SSLProxyEngine On
SSLOptions +ExportCertData
ProxyPreserveHost On
ProxyRequests Off
ProxyVia On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
#ProxyPass should be prior to any other Proxy directives    
ProxyPass        /  http://dev-ms01:80/
ProxyPassReverse /  http://dev-ms01:80/ 

RewriteEngine  on

RequestHeader set X_SSL_CLIENT_M_SERIAL "%{SSL_CLIENT_M_SERIAL}s"
RequestHeader set X_FORWARDED_PROTO "https" env=HTTPS
RequestHeader set SslSubject "%{SSL_CLIENT_S_DN}s"
</VirtualHost>

When I browse the https://secure-dev-ms01/MsgService/default.asmx URL it is prompting for the client certificate and when I choose the client cert am not seeing the authorized content that am supposed to see, I suspect SSLOptions +ExportCertData config of apache not forwarding the client certificate to IIS.I couldn't find much info/articles on how to forward client certificate from apache to IIS.

Can someone please help me configuring apache with forward proxy for client certificate authentication to IIS?

Update 1:

Tried forwarding the requests to https://dev-ms01/ instead of http://dev-ms01:80/ and also setting the SSL_* request headers in Apache VirtualHost as below, but still no luck

SSLProxyEngine On
SSLOptions +ExportCertData +StdEnvVars 
#ProxyPreserveHost On
ProxyRequests Off
ProxyVia On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
#ProxyPass should be prior to any other Proxy directives
ProxyPass   / https://dev-ms01/
ProxyPassReverse   / https://dev-ms01/
RewriteEngine  on

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_S_DN_CN "%{SSL_SERVER_S_DN_CN}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_CERT_CHAIN_0 "%{SSL_CLIENT_CERT_CHAIN_0}s"
RequestHeader set SSL_CLIENT_CERT_CHAIN_1 "%{SSL_CLIENT_CERT_CHAIN_1}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"
RequestHeader set X_SSL_CLIENT_M_SERIAL "%{SSL_CLIENT_M_SERIAL}s"
RequestHeader set X_FORWARDED_PROTO "https" env=HTTPS
RequestHeader set SslSubject "%{SSL_CLIENT_S_DN}s"

Best Answer

AFAIK if Apache terminates the TLS request there isn't going to be any way from IIS to see the original client certificate. There is no way that Apache's proxy function could initiate a https request that would have the original client certificate, since Apache would not have any access to the associated private key.

SSLOptions +ExportCertData config of apache not forwarding the client certificate to IIS

That isn't what the ExportCertData option does. That options simply sets up some environment variables that can be used by CGI or other directives in Apache. It doesn't magically pass that certificate on. You are even using some of those variables in the RequestHeader ... lines.

If you really need to proxy your requests in Apache, then you will need to update your application behind the proxy, to accept and trust the HTTP headers you are setting in Apache as the equivalent to a certificate.