Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save itn3000/53a83626e2c9dd0a4c5a44a493615a4c to your computer and use it in GitHub Desktop.
Save itn3000/53a83626e2c9dd0a4c5a44a493615a4c to your computer and use it in GitHub Desktop.
investigation of discarding client certificate problem on IIS

Steps to reproduce

Environment

  • Windows Server 2022 for server
  • ubuntu-20.04 with curl for HTTP client

setup

  1. creating self signed CA certificate using openssl and import to server root CA
  2. creating server certificate from CA certificate using openssl and import to server computer cert store
  3. creating client certificate from CA certificate using openssl and convert to pkcs12 file
  4. enable IIS on Windows Server 2022
  5. install ASP.NET Core 6.0 Hosting Bundle
  6. build and publish ReturnClientCertificateThumbprintIIS project
  7. setting up ASP.NET Core IIS hosting
  8. deploy ReturnClientCertificateThumbprintIIS project on /aspnetcoretest
  9. set IIS's client certificate setting to "Accept"
  10. build and publish ReturnClientCertificateThumbprintKestrel project
  11. run ReturnClientCertificateThumbprintKestrel
  12. allow 443/tcp and 5001/tcp port

run

  1. run curl https://[host]:[IIS port]/aspnetcoretest -k -E client.p12:[pkcs12 password] --tlsv1.3 --tls-max 1.3
    • IIS+tls1.3
  2. run curl https://[host]:[IIS port]/aspnetcoretest -k -E client.p12:[pkcs12 password] --tlsv1.2 --tls-max 1.2
    • IIS+tls1.2
  3. run curl https://[host]:[Kestrel port]/ -k -E client.p12:[pkcs12 password] --tlsv1.3 --tls-max 1.3
    • Kestrel+tls1.3
  4. run curl https://[host]:[Kestrel port]/ -k -E client.p12:[pkcs12 password] --tlsv1.2 --tls-max 1.2
    • Kestrel+tls1.2

Expected Result

all running commands return client cert is [certificate hash string]

Actual Result

IIS+tls1.2 pattern returns client cert is null, other pattern returns client cert is [certificate hash string]

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UsePathBase("/aspnetcoretest");
app.MapGet("/", (context) => context.Connection.ClientCertificate != null ?
context.Response.WriteAsync("client cert is " + context.Connection.ClientCertificate.GetCertHashString()) :
context.Response.WriteAsync("client cert is null"));
app.Run();
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore.Server.Kestrel.Https;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, options) =>
{
var pfxpassword = context.Configuration["pfxpassword"];
options.Listen(IPAddress.Any, 5001, listenOptions =>
{
listenOptions.UseHttps("mycert.p12", pfxpassword, httpsOptions =>
{
httpsOptions.AllowAnyClientCertificate();
httpsOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
httpsOptions.ClientCertificateValidation = (cert, chain, policyError) =>
{
return true;
};
});
});
});
var app = builder.Build();
app.MapGet("/", (context) =>
{
if(context.Connection.ClientCertificate != null)
{
return context.Response.WriteAsync("client cert is " + context.Connection.ClientCertificate.GetCertHashString());
}
else
{
return context.Response.WriteAsync("client cert is null");
}
});
app.Run();
* Trying 10.0.0.4:443...
* TCP_NODELAY set
* Connected to vmskitoy2k221 (10.0.0.4) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: ca.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=vmskitoy2k221; [email protected]
* start date: Apr 16 07:30:35 2022 GMT
* expire date: Apr 16 07:30:35 2023 GMT
* subjectAltName: host "vmskitoy2k221" matched cert's "vmskitoy2k221"
* issuer: C=JP; ST=Some-State; O=Internet Widgits Pty Ltd; CN=myrootca
* SSL certificate verify ok.
> GET /iistest HTTP/1.1
> Host: vmskitoy2k221
> User-Agent: curl/7.68.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, CERT verify (15):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Transfer-Encoding: chunked
< Server: Microsoft-IIS/10.0
< X-Powered-By: ASP.NET
< Date: Sun, 17 Apr 2022 18:43:41 GMT
<
client cert is F3CF2DDF270583560250D1AAE01BEE297B7FD0C7
* Connection #0 to host vmskitoy2k221 left intact
* Trying 10.0.0.4:443...
* TCP_NODELAY set
* Connected to vmskitoy2k221 (10.0.0.4) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: ca.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=vmskitoy2k221; [email protected]
* start date: Apr 16 07:30:35 2022 GMT
* expire date: Apr 16 07:30:35 2023 GMT
* subjectAltName: host "vmskitoy2k221" matched cert's "vmskitoy2k221"
* issuer: C=JP; ST=Some-State; O=Internet Widgits Pty Ltd; CN=myrootca
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x563d876e6880)
> GET /iistest HTTP/2
> Host: vmskitoy2k221
> user-agent: curl/7.68.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
* HTTP/2 stream 0 was not closed cleanly: HTTP_1_1_REQUIRED (err 13)
* Downgrades to HTTP/1.1!
* Empty reply from server
* Connection #0 to host vmskitoy2k221 left intact
* Issue another request to this URL: 'https://vmskitoy2k221/iistest'
* Found bundle for host vmskitoy2k221: 0x563d876daaa0 [can multiplex]
* Re-using existing connection! (#0) with host vmskitoy2k221
* Connected to vmskitoy2k221 (10.0.0.4) port 443 (#0)
* Using Stream ID: 3 (easy handle 0x563d876e6880)
> GET /iistest HTTP/2
> Host: vmskitoy2k221
> user-agent: curl/7.68.0
> accept: */*
>
* HTTP/2 stream 0 was not closed cleanly: HTTP_1_1_REQUIRED (err 13)
* Connection died, retrying a fresh connect
* Downgrades to HTTP/1.1!
* Closing connection 0
* TLSv1.3 (OUT), TLS alert, close notify (256):
* Issue another request to this URL: 'https://vmskitoy2k221/iistest'
* Hostname vmskitoy2k221 was found in DNS cache
* Trying 10.0.0.4:443...
* TCP_NODELAY set
* Connected to vmskitoy2k221 (10.0.0.4) port 443 (#1)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: ca.crt
CApath: /etc/ssl/certs
* SSL re-using session ID
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=vmskitoy2k221; [email protected]
* start date: Apr 16 07:30:35 2022 GMT
* expire date: Apr 16 07:30:35 2023 GMT
* subjectAltName: host "vmskitoy2k221" matched cert's "vmskitoy2k221"
* issuer: C=JP; ST=Some-State; O=Internet Widgits Pty Ltd; CN=myrootca
* SSL certificate verify ok.
> GET /iistest HTTP/1.1
> Host: vmskitoy2k221
> User-Agent: curl/7.68.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Transfer-Encoding: chunked
< Server: Microsoft-IIS/10.0
< X-Powered-By: ASP.NET
< Date: Sun, 17 Apr 2022 18:39:29 GMT
<
client cert is null
* Connection #1 to host vmskitoy2k221 left intact
@itn3000
Copy link
Author

itn3000 commented Apr 14, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment