Hi!
I’m trying to establish a client certificate/mutual authentication mechanism with this setup:
Computer (shall require certificate) ↔ xxx.duckdns.org ↔ reverse-proxy (nginx) ↔ server application
The reverse proxy works fine if I do not use a client certificate. But once I set it up and configure it in nginx I can’t solve this error:
400 Bad Request
No required SSL certificate was sent
The nginx error log also shows
client sent no required SSL certificate while reading client request headers, client: …, server: xxx.duckdns.org, request: “GET /service_worker.js HTTP/2.0”, host: “xxx.duckdns.org”
The certificate was generated according to this page:
echo "Setting up client-certificate signing CA ..."
openssl genrsa -aes256 -passout pass:${PRIVATE_CA_PASSWORD} -out ca.pass.key 4096
openssl rsa -passin pass:${PRIVATE_CA_PASSWORD} -in ca.pass.key -out ca.key
echo "Make the signing CA valid for 100 years ..."
openssl req -new -x509 -days 36500 -key ca.key -out ca.pem -subj '/CN=Martin'
echo "Creating a client keypair ..."
echo "- RSA key"
openssl genrsa -aes256 -passout pass:${PUBLIC_KEY} -out ${CLIENT_ID}.pass.key 4096
openssl rsa -passin pass:${PUBLIC_KEY} -in ${CLIENT_ID}.pass.key -out ${CLIENT_ID}.key
echo "- CSR"
openssl req -new -passin pass:${PUBLIC_KEY} -key ${CLIENT_ID}.key -out ${CLIENT_ID}.csr -subj '/CN=User'
echo "Signing this key with the CA ..."
# valid: 100 years
openssl x509 -req -days 36500 -in ${CLIENT_ID}.csr -CA ca.pem -CAkey ca.key -set_serial ${CLIENT_SERIAL} -passin pass:${PRIVATE_CA_PASSWORD} -out ${CLIENT_ID}.pem
echo "Generating crt file from pem file ..."
openssl x509 -outform der -in ${CLIENT_ID}.pem -out ${CLIENT_ID}.crt
echo "Bundle client key into pfx file ..."
openssl pkcs12 -export -out ${CLIENT_ID}.pfx -inkey ${CLIENT_ID}.key -in ${CLIENT_ID}.pem -certfile ca.pem -password pass:${EXPORT_PASSWORD}
echo "Checking certificate ..."
openssl verify -CAfile ca.pem user.pem
The certificate check in the last line shows OK in the end.
On the computer I tried out using the ${CLIENT_ID}.pfx and the ${CLIENT_ID}.crt - both without success.
Before trying this, I established the SSL certificate for the proxy according to this page using certbot-auto.
The nginx config looks like this:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name xxx.duckdns.org;
listen [::]:80 default_server ipv6only=off;
return 301 https://$host$request_uri;
}
server {
server_name xxx.duckdns.org;
ssl_certificate /etc/letsencrypt/live/xxx.duckdns.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx.duckdns.org/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/xxx.duckdns.org/chain.pem;
ssl_dhparam /etc/nginx/ssl/dhparams.pem;
listen [::]:443 ssl http2 default_server ipv6only=off;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
ssl on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:EECDH+CHACHA20:EECDH+AESGCM:EECDH+AES;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
### once I remove these 3 lines everything works but without the client certificate ###
ssl_client_certificate /etc/nginx/certificates/ca.pem;
ssl_verify_client on;
ssl_verify_depth 3;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
proxy_buffering off;
location / {
# the server application runs on port 30303 of the same machine
proxy_pass https://127.0.0.1:30303;
proxy_set_header Host $host;
proxy_redirect http:// https://;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
The nginx error sounds like the client did not even try to send a certificate… the certificate chain does not seem to be established? (no wonder - I did not use any of the files from the SSL proxy certificate generation in the client certificate generation or vise versa.)
How can I invoke this in the given setup? Basically all tutorials I read only state that in nginx I need to use the ssl_client_certificate option… but I could not find information about the usage together with a DNS server and a reverse proxy.
Thanks a lot for hints!