I use nginx and let's encrypt. Server is running on server.io
.
I need to setup mTLS and therefore I need client certificate as well.
I created another Let's encrypt certificate for client.io
(I used certbot
: I created NS entires etc and got private/public key for client.io
.
I want that client.io
is the only one who can connect to server.io
.
server {
listen 443 ssl;
server_name server.io;
ssl_certificate /etc/letsencrypt/live/server.io/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/server.io/privkey.pem; # managed by Certbot
ssl_verify_client on;
ssl_client_certificate /etc/ssl/shared_keys/client.io/fullchain.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
add_header Content-Type text/plain;
return 200 'Hello world $ssl_client_s_dn';
}
}
When I try to connect via:
curl -v --cert client.io/cert.pem --key client.io/privkey.pem https://secure-qa.topkey.io
I see this in the response"
* Trying 164.92.108.70:443...
* Connected to server.io (164.92.108.70) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* CAfile: /etc/ssl/cert.pem
* CApath: none
* [CONN-0-0][CF-SSL] (304) (OUT), TLS handshake, Client hello (1):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Server hello (2):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Unknown (8):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Request CERT (13):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Certificate (11):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, CERT verify (15):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Finished (20):
* [CONN-0-0][CF-SSL] (304) (OUT), TLS handshake, Certificate (11):
* [CONN-0-0][CF-SSL] (304) (OUT), TLS handshake, CERT verify (15):
* [CONN-0-0][CF-SSL] (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN: server accepted http/1.1
* Server certificate:
* subject: CN=server.io
* start date: Oct 3 06:54:33 2023 GMT
* expire date: Jan 1 06:54:32 2024 GMT
* subjectAltName: host "server.io" matched cert's "server.io"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
> GET / HTTP/1.1
> Host: server.io
> User-Agent: curl/7.87.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< Server: nginx/1.22.0 (Ubuntu)
< Date: Tue, 03 Oct 2023 11:58:38 GMT
< Content-Type: text/html
< Content-Length: 224
< Connection: close
<
<html>
<head><title>400 The SSL certificate error</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The SSL certificate error</center>
<hr><center>nginx/1.22.0 (Ubuntu)</center>
</body>
</html>
* Closing connection 0
Based on response it actually looks like mTLS is working however I am not sure why am I getting error in the response?
cat /var/log/nginx/error.log
returns:
2023/10/04 08:09:29 [crit] 21844#21844: *1250 SSL_do_handshake() failed (SSL: error:0A00006C:SSL routines::bad key share) while SSL handshaking, client: 162.142.125.221, server: 0.0.0.0:443
nginx setup worked with manually created CA certs so I guess there must be something wrong with idea to use Let's encrypt certificates even thought I read that this should work (ChatGPT). If I can not continue with Let's encrypt which certificate should I then use/buy in order to solve this problem easily?
curl --cert
should be the client certificate used for client authentication and not include the CA certificates you're sending with--cert /etc/../fullchain.pem
; use--cert /etc/../cert.pem
ssl_client_certificate
inyour config should point to the PEM certificates of the CERTIFICATE AUTHORITIES (CAs) you trust to sign client certificates. The bundled ones are listed under /etc/ssl/certs on a Ubuntu host near me - but with each CA in a separate file.server.io
and another set of key forclient.io
.