I am trying to establish a 2-way SSL connection between an nginx server and a client(browser/postman).
I am wondering whether it should be possible to tell nginx to trust the browser/postman's keys, assuming nginx requests and verifies client's certificates.
specifically, what should be put in that section of nginx
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/ssl/newcert.crt;
ssl_certificate_key /etc/nginx/ssl/newkey.pem;
ssl_session_timeout 15m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
ssl_verify_client on;
ssl_verify_depth 2;
# what should be the content of that file??
>>>>>> ssl_client_certificate /etc/nginx/ssl/trust/client.crt;
}
I failed to find any information regarding this...
Thanks.
The ssl_client_certificate directive points to a file containing the Certificate Authority used to sign the client's Certificate Request. See this document for details.
If you are using a self-signed certificate authority for your client certificates, the procedure would be something like this:
Create a self-signed certificate to use as a Certificate Authority. See OpenSSL CA(1) for a simplified scheme to manage this step.
Generate a certificate request for the client. For example:
openssl req -newkey rsa:2048 -nodes -keyout user.key -out user.req
Use the CA from step 1 to sign the request from step 2 to generate a certificate for the client. See OpenSSL CA(1) above.
Convert the certificate from step 3 into a PKCS#12 formatted file so that it can be imported by the client. For example:
cat user.key user.crt | openssl pkcs12 -export -out user.p12
Related
I am trying to understand the relationship between the client and server in the context of an SSL connection. Am I correct in understanding that the fact that the same certificate authority (me - in example below) sign both server and client certificate makes that they can communicate. Thus, that the server only accepts communication when client authenticates with client certificate signed by the same CA as the server certificate, and this is essential to the idea of an SSL connection?
(script underneath comes directly from http://blog.nategood.com/client-side-certificate-authentication-in-ngi)
# Create the CA Key and Certificate for signing Client Certs
openssl genrsa -des3 -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
# Create the Server Key, CSR, and Certificate
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
# We're self signing our own server cert here. This is a no-no in production.
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
# Create the Client Key and CSR
openssl genrsa -des3 -out client.key 1024
openssl req -new -key client.key -out client.csr
# Sign the client certificate with our CA cert. Unlike signing our own server cert, this is what we want to do.
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
server {
listen 443;
ssl on;
server_name example.com;
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
ssl_client_certificate /etc/nginx/certs/ca.crt;
ssl_verify_client on;
The short answer is No. These are two separate aspects.
Here:
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
You are configuring the server certificates which need to be trusted by the client.
And here:
ssl_client_certificate /etc/nginx/certs/ca.crt;
You configure the certification authority to verify your clients' certificates against.
"Must server and client certificate be signed by same CA in SSL"
Short answer is, it can be but not necessary.
To see why, let's break down the steps but without too much technical.
From your point of view when setting up the nginx server.
You want to achieve 2 goals.
Prove the identity of your server.
For this you get a CA to sign your server certificate and
present it to a client that connects to your server
Verify the identity of the client connecting to the server
For this, you set define the list of CA that you trust that signs the client's certificate.
When a client connects to your server, you check if the client certificate presented is signed by your list of CA
That's not the end. Let's look at the client's end.
The client also wants to achieve 2 goals.
Prove the client's identity when connecting to your server
For this, the client get a CA to sign its client certificate and
present it to your server when connecting.
Here is the catch, the CA that signs the client certificate must be in your server's list of CA.
Verify the identity of your server
For this, the client has to trust the CA that signs your server's certificate.
How is this done?
Typically this list is predefine on the system or browser so it happens transparently.
But if you are writing a client, then you may have to define this list of trusted CA or just let the client know the CA that signs your server certificate.
So, it can happen that the CA signing the server and the client is the same but it is not necessary. It all depends on the list of CA defined on both the server and the client.
Server certs and Client certs are used in completely different ways.
The only similarities are:
They both contain the word certificate
They both use public & private keys for encryption
Following Godaddy instructions, I have generated a private key and the corresponding CSR:
openssl req -new -newkey rsa:2048 -nodes -keyout mydomain.key -out mydomain.csr
Then, I uploaded mydomain.csr to Godaddy, getting a ZIP file containing the SSL and intermediate certificates, which I concatenated to have a single CRT file:
cat mysslcert.crt intermediate.crt >> mydomain.crt
Using the official NGINX image from the docker hub, the configuration is the following:
server {
listen 80;
listen 443 ssl;
keepalive_timeout 10m;
root /var/www;
server_name mydomain.com;
ssl on;
ssl_certificate /etc/ssl/mydomain.crt;
ssl_certificate_key /etc/ssl/mydomain.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on; ...
The files are accessible (checked with wrong paths). The error I'm getting is the following:
SSL_CTX_use_PrivateKey_file("/etc/ssl/mydomain.key") failed (SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)
The comparison of the MD5 tells me they're different, but what am I doing wrong?
Thanks #TarunLalwani, the problem was that the certificate that I can download from Godaddy takes time to be refreshed when a new CSR is uploaded. The solution is that I had to wait for the actual email indicating that my certificate is ready to be downloaded.
OCSP Stapling does not work for Thawte certificates on Nginx, what could be the problem?
Configured Nginx to work with OCSP Stapling.
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /ssl/ssl_trusted_certificate.crt;
The ssl_trusted_certificate.crt certificate includes the stitched root.crt and intermediate.crt.
The verification request indicates that OCSP Stapling is still off:
Openssl s_client -connect xxx.xxx:443 -tls1 -tlsextdebug -status
Result:
OCSP Response: No response sent
Who knows this problem?
As it turned out, the problem was not in the certificate and server settings. In order for OCSP Stapling to work, you need to go through a couple of pages of the site. On the first request, the server will request data from the certification center servers, and then go to OCSP.
I've gotten SSL to work on Apache servers and on a client's Nginx server. However, I am having issues with my EV SSL certificate installation. This is also on a server with a special character in the URL: weöm.com.
weöm.com is displayed as xn--wem-tna.com in browsers, which is fine. When I inspected my .ca-bundle that was emailed to me from COMODO, I saw my domain name rendered as we\xC3\xB6m.com, which made me think I have to generate my .csr and .key the same way.
Here's how I've been doing it (ran this command in Terminal):
openssl req -new -newkey rsa:2048 -nodes -out weom.csr -keyout weom.key -subj "/serialNumber=000000000/businessCategory=Private Organization/C=US/postalCode=00000/ST=California/L=Cupertino/street=1 Loop Way/O=Apple Inc/OU=COMODO EV SSL/CN=we\xC3\xB6m.com"
(I've replaced the serial number and other things with fake data in my example)
The code spits out a .csr and .key with the exact same data that my compiled .crt has and I cannot understand why I'm still getting this SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch error.
I've been wrangling with this for about a week, does anyone have any idea what I'm doing wrong?
EDIT: Proving more information...
Here is how I'm creating my master .crt:
cat xn--wem-tna.com.crt AddTrustExternalCARoot.crt COMODORSAAddTrustCA.crt COMODORSAExtendedValidationSecureServerCA.crt >> cert_chain.crt
This is the default file in my sites-available folder:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name xn--wem-tna.com;
return 301 https://$host$request_uri;
}
server {
# SSL configuration
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate cert_chain.crt;
ssl_certificate_key weom.key;
ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name xn--wem-tna.com;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
}
The reason for the error is that your KEY and CRT are different.
You can verify this by checking MD5 hashes on them:
openssl x509 -noout -modulus -in certificate.crt | openssl md5
openssl rsa -noout -modulus -in privateKey.key | openssl md5
Additionally I would change the order in the bundle CRT (cert_chain.crt),at the moment you have it this way:
xn--wem-tna.com.crt AddTrustExternalCARoot.crt COMODORSAAddTrustCA.crt COMODORSAExtendedValidationSecureServerCA.crt
It should be:
cat xn--wem-tna.com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > cert_chain.crt
This is Official Comodos Certificate Installation: NGINX
What gets me worried is your comment at the beginning:
If you have changed the key once your certificate had been issued you will need to invalidate it and apply for a new CRT with your new KEY and new CSR.
weöm.com is displayed as xn--wem-tna.com in browsers, which is fine. When I inspected my .ca-bundle that was emailed to me from COMODO, I saw my domain name rendered as we\xC3\xB6m.com, which made me think I have to generate my .csr and .key the same way.
Oh yeah, forgot to update.
I got a refund and went with CertSimple. Emailed them questions Friday night, went through the entire process of obtaining an EV cert Saturday morning/afternoon, and had it on my server by 6pm (and that's only because I was out running errands).
I'm working on a Ruby language server to manage multiple Telegram Bots via setwebhooks
BTW, I'll delivery the server as opensource at BOTServer
PROBLEM
I have troubles receiving webhook updates from Telegram Bot API Server. I have set a webhook token (Telegram reply "success") but I do not receive any update on the succesfully configured webhook.
I think the problem could be around self-signed Certificate mysteries. See old reddit question and answers.
I have similar problem and I fair the point is in some "misunderstanding" between Telegram Bot API Server that send HTTPs webhooks updates and the bot server receving webhooks (I use nginx as proxy/https SSL certificate handler).
It seems that someone solved the issue configuring nginx with a certificate "chain"; I'm pretty ingnorant in certificates tricks and so I ask:
QUESTION
May someone can post info, to configure nginx (any ssl web server!) with detailed settings / step-by step for dummies, showing how to pass from .key and .pem files described here: https://core.telegram.org/bots/self-signed to set-up the certificate "chain" to configure in nginx config, to be "accepted" by Telegram Bot API Server ?
BTW, my nginx config now:
upstream backend {
server 127.0.0.1:3000;
}
#
# HTTPS server
#
server {
listen 8443 ssl;
server_name myhost.com;
ssl on;
ssl_certificate /mypath/ssl/PUBLIC.pem;
ssl_certificate_key /mypath/ssl/PRIVATE.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
ssl_prefer_server_ciphers on;
location #backend {
proxy_pass http://backend;
}
location / {
try_files $uri #backend;
}
}
where PRIVATE.key + PUBLIC.pem files are that one generated following guidelines: Using self-signed certificates:
openssl req -newkey rsa:2048 -sha256 -nodes -keyout PRIVATE.key -x509 -days 365 -out PUBLIC.pem -subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=YOURDOMAIN.EXAMPLE"
thanks
giorgio
I answer myself, to share solution found here:
https://stackoverflow.com/a/33260827/1786393
the point was not the mentioned nginx configuration, but the PEM file:
openssl req -newkey rsa:2048 -sha256 -nodes -keyout YOURPRIVATE.key -x509 -days 365 -out YOURPUBLIC.pem -subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=YOURDOMAIN.EXAMPLE"
YOURDOMAIN.EXAMPLE in the subj strig of openssl must be real hostname of your server that receive webhooks.
the solution that works for me:
I generated key pairs: openssl genrsa -out webhook_pkey.pem 2048 and openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
don't forget to give FQDN name. give your host's ip at least
added it to nginx config
server {
listen 8443 ssl;
server_name MY_IP;
charset utf-8;
client_max_body_size 75M;
ssl_certificate /var/www/myproject/tg_keys/webhook_cert.pem;
ssl_certificate_key /var/www/myproject/tg_keys/webhook_pkey.pem;
location / { try_files $uri #yourapplication; }
location #yourapplication {
include uwsgi_params;
uwsgi_pass unix:/var/www/myproject/hb.sock;
}
}
cURL options:
CURLOPT_SSL_VERIFYPEER = false
CURLOPT_SSL_VERIFYHOST = false