Nginx install intermediate certificate - ssl

I'm trying to install an intermediate certificate on Nginx ( laravel forge ).
Right now the certificate is properly installed, just the intermediate that is missing.
I've seen that I need to concatenate the current certificate with the intermediate. What is the best/safest way to add the intermediate certificate.
Also, if the install of the intermediate failed, can I just roll back to the previous certificate, and reboot nginx? ( the website site is live, so I can't have a too long downtime )

Nginx expects all server section certificates in a file that you refer with ssl_certificate. Just put all vendor's intermediate certificates and your domain's certificate in a file. It'll look like this.
-----BEGIN CERTIFICATE-----
MII...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MII...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MII...
-----END CERTIFICATE-----
To make sure everything is okay and to avoid downtime, I would suggest you to setup Nginx locally, add 127.0.0.1 yourdomain.com to /etc/hosts, and try open it from major browsers. When you've verified that everything is correct your can replicate it to the production server.
When you're done, it is a good idea to use some SSL checker tool to verify (e.g. this one). Because pre-installed CA certificates may vary depending on browser and platform, you can easily overlook a misconfiguration checking from one OS or a limited set of browsers.
Edit
As #Martin pointed out, the order of certificates in the file is important.
RFC 4346 for TLS 1.1 states:
This is a sequence (chain) of X.509v3 certificates. The sender's
certificate must come first in the list. Each following
certificate must directly certify the one preceding it.
Thus the order is:
1. Your domain's certificate
2. Vendor's intermediate certificate that certifies (1)
3. Vendor's intermediate certificate that certifies (2)
...
n. Vendor's root certificate that certifies (n-1). Optional, because it should be contained in client's CA store.

Letsencrypt: fullchain.pem
Same trouble for me. I was using Letsencrypt and, in my Nginx configuration, I needed to NOT use this:
ssl_certificate /etc/letsencrypt/live/domain.tld/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem;
But use this:
ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem;

Related

Nginx PEM_read_bio_X509 PEM_read_bio:bad end line

Unable to crack why this is happening. Certificate bundle file seems proper but receiving PEM routines:PEM_read_bio:bad end line
-----BEGIN CERTIFICATE-----
MIIEizCCA3OgAwIBAgIQDI7gyQ1qiRWIBAYe4kH5rzANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0yODA4MDExMjAwMDBaMEQxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxHjAcBgNVBAMTFURpZ2lDZXJ0IEdsb2Jh
bCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNIfL7zBYZd
W9UvhU5L4IatFaxhz1uvPmoKR/uadpFgC4przc/cV35gmAvkVNlW7SHMArZagV+X
au4CLyMnuG3UsOcGAngLH1ypmTb+u6wbBfpXzYEQQGfWMItYNdSWYb7QjHqXnxr5
IuYUL6nG6AEfq/gmD6yOTSwyOR2Bm40cZbIc22GoiS9g5+vCShjEbyrpEJIJ7RfR
ACvmfe8EiRROM6GyD5eHn7OgzS+8LOy4g2gxPR/VSpAQGQuBldYpdlH5NnbQtwl6
OErXb4y/E3w57bqukPyV93t4CTZedJMeJfD/1K2uaGvG/w/VNfFVbkhJ+Pi474j4
8V4Rd6rfArMCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0P
AQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29j
c3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9jcmw0LmRp
Z2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwN6A1oDOGMWh0dHA6
Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwPQYD
VR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2lj
ZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFCRuKy3QapJRUSVpAaqaR6aJ50AgMB8GA1Ud
IwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA0GCSqGSIb3DQEBCwUAA4IBAQAL
OYSR+ZfrqoGvhOlaOJL84mxZvzbIRacxAxHhBsCsMsdaVSnaT0AC9aHesO3ewPj2
dZ12uYf+QYB6z13jAMZbAuabeGLJ3LhimnftiQjXS8X9Q9ViIyfEBFltcT8jW+rZ
8uckJ2/0lYDblizkVIvP6hnZf1WZUXoOLRg9eFhSvGNoVwvdRLNXSmDmyHBwW4co
atc7TlJFGa8kBpJIERqLrqwYElesA8u49L3KJg6nwd3jM+/AVTANlVlOnAM2BvjA
jxSZnE0qnsHhfTuvcqdFuhOWKU4Z0BqYBvQ3lBetoxi6PrABDJXWKTUgNX31EGDk
92hiHuwZ4STyhxGs6QiA1213PQJWENMASDASDDDAA
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEizCCA3OgAwIBAgIQDI7gyQ1qiRWIBAYe4kH5rzANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0yODA4MDExMjAwMDBaMEQxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxHjAcBgNVBAMTFURpZ2lDZXJ0IEdsb2Jh
CTq4G+zb43X1T77nJgSOI9pq/TqCwtukZ7u9VLL3JAq3Wdy2moKLvvC8tVmRzkAe
0xQCkRKIjbBG80MSyDX/R4uYgj6ZiNT/Zg6GI6RofgqgpDdssLc0XIRQEotxIZcK
zP3pGJ9FCbMHmMLLyuBd+uCWvVcF2ogYAawufChS/PT61D9rqzPRS5I2uqa3tmIT
44JhJgWhBnFMb7AGQkvNq9KNS9dd3GWc17H/dXa1enoxzWjE0hBdFjxPhUb0W3wi
8o34/m8Fxw==
-----END CERTIFICATE-----
Configuration file
server {
listen 443 ssl;
ssl_certificate /etc/nginx/bundle.crt;
ssl_certificate_key /etc/nginx/abc-private.key;
server_name localhost;
location / {
index index.html;
}
error_log /var/log/nginx/auth-api-error.log;
access_log /var/log/nginx/auth-api-access.log;
}
Error in /var/log/nginx/error.log while starting nginx
2020/01/07 17:13:32 [emerg] 4267#4267: cannot load certificate "/etc/nginx/bundle.crt": PEM_read_bio_X509() failed (SSL: error:0906D066:PEM routines:PEM_read_bio:bad end line)
The first certificate block has had the invalid characters 1213PQJWENMASDASDDDAA appended to its last line. Remove those and that cert can be parsed correctly. But it is a CA cert, specifically an intermediate cert for C=US, O=DigiCert Inc, CN=DigiCert Global CA G2, and not a valid server cert as the first cert in an nginx cert file should be.
The second block starts with the same first 5 lines (encoding 240 bytes) as the first block, perhaps copied, but the rest of it, although valid base64, appears to encode garbage and when combined doesn't produce anything even remotely resembling a valid cert. Remove it entirely. Then before the current first cert insert an actual server cert issued by that DigiCert intermediate if you have such; otherwise throw this away entirely and get correct certs from DigiCert or some other CA.
Sometimes, during initial SSL certificate installation or its renewal, the concatenation command corrupts certificate codes and reloading Nginx’s configuration files results in this error:
If we open a file with concatenated certificate codes, we can see that closing tag -----END CERTIFICATE----- of one certificate and opening tag -----BEGIN CERTIFICATE----- of another one are joined in one line:
The issue fix is quite simple: use a text editor of your choice (for example, Nano or vim on Linux-based operating systems, Notepad on Windows, Textedit on Mac OS X) and create a line break between the two certificate codes, so that -----BEGIN CERTIFICATE----- tag starts with the next line:
Make sure that you count five dashes at the start and end of a footer and a header. Save the file and exit the text editor.
The Nginx configuration file can be reloaded with one of the following commands:
nginx -s reload
or
service nginx reload
The server should serve HTTPS from now on without any issues.
REFERENCE:
https://www.namecheap.com/support/knowledgebase/article.aspx/9855/2238/nginxapache-error-0906d066pem-routinespem_read_biobad-end-line/

Mandrill webhooks, SSL certificate verify failed, verify that the CA cert is OK

I've been getting this error for a long while:
POST to https://www.xxxxxx.com/hook/mandrill/quotations/opened failed: SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
I got my certificates re-newed by Comodo recently & ever since, I've been getting these errors.
It still seems to work though, but I'm worried some of the webhooks might not get through.
Is someone getting these errors as well? Might it be a problem on their side? Cause I have checked my website on https://www.sslshopper.com/ssl-checker.html and it's seems to be perfectly fine..
Also I'm hosting my website on Amazon
Thanks
This is an issue with your installed SSL certificate. You most likely did not combine the .crt file and the .ca-bundle file they provided to you and only installed the .crt file. Comodo provides the following two files in the zip package they make available to you:
_yourdomain_com.crt
_yourdomain_com.ca-bundle
The .ca-bundle includes all your intermediate certificates. You need to combine the contents of the two above files together. Your output .crt file would look something like:
-----BEGIN CERTIFICATE-----
contents of original crt file
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
contents of 1st cert in ca-bundle file
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
contents of 2nd cert in ca-bundle file
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
etc...
-----END CERTIFICATE-----
You must list the original certificate as the first certificate in the output file. Then comes the intermediate certificates in your bundle.
Replace the .crt file that your server is pointing to with the above output .crt file. No need to change any of the web server configurations for either Apache or Nginx - both support bundled certificates. Make sure to restart your web server once the changes are made.
Before you make any of the above changes, you can actually see whether or not the missing .ca-bundle is causing your error by running a SSL test against your domain. In the results section after the test finishes, look for Additiona Certificates. The results will state that you are missing certificates if you do not have the appropriate intermediate certificates in your .crt file.

Heroku SSL: install intermediate cert?

My registrar, gandi, gave me an intermediate cert to install, so I have 3 files:
Private key file (server.key)
Certificate file (mycert.crt)
Intermediate cert (GandiSomething.pem)
I'm using the SSL Beta service on heroku. The heroku CLI heroku _certs:add, takes exactly two arguments, CRT and KEY. how do I install the intermediate cert?
Paul is right, you can combine certificates:
cat ssl.crt middle.crt root.crt > all.crt
Be assured that newlines at the end of cert files!
And upload it to Heroku (use add if you haven't SSL Endpoint yet):
heroku certs:update --app $YOUR_APP --confirm $YOUR_APP all.crt private.key
But there are some tricks you haven't forget:
Update your DNS CNAME record. Change target from <app>.herokuapp.com to secure <domain>.herokudns.com (be careful, if you have *.your.domain record it can catch requests and forward it to another server)
Check the cert chain works right: SSL Checker
Flush local DNS: Flush DNS tips (antivirus also can patch and cache you connections)
Restart your browser (to flush browser's cache too)
Check your app with browser by https:// connection
The solution here is to combine the intermediate cert and the generated cert into one file, as described here. Because that link is shady, here's how the cert file should look once combined:
-----BEGIN CERTIFICATE-----
MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
wfsm5p9GJKaxB825DOgNghYAHZaS/KYIoA==
-----END CERTIFICATE-----
Then, this command will work:
heroku _certs:add --app name-of-my-app file-with-combined-certs.crt myserver.key
Just pass it in as an argument. Put the intermediate in the middle, it takes it as another argument. Then check heroku certs and report back if it doesn't work.

OPENSSL connection to a public server gives X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY

I am writing a very basic SSL client to connect to a HTTPS web server. I can connect and process the request/response just fine. However OpenSSL is reporting UNABLE_TO_GET_ISSUER_CERT_LOCALLY, but so far I choose to ignore the error :-). Now I want to solve that part of the problem.
I am testing by connecting to a public SSL server on HTTPS, such as Google or Yahoo, and checking the return of SSL_get_verify_result(...).
As I understand it, I need the CA pem files for that specific site so that OpenSSL can verify the chain to a trusted certificate authority. In this case, that would be the authority that signed the certs for Google or Yahoo.
To get the PEM files which I expect should work, I opened my FireFox, navigated to those sites, and performed a View Certificate and exported each one up the list. So for example, I have a file called "GeoTrustGlobalCA.pem" which all looks good. In fact, when I went to the GeoTrust site directly and downloaded their root certificate, it is identical to the one I exported from FireFox, as I would expect.
So, for example with Google which showed two certificates in the tree in FireFox, I load each one with:
result = SSL_CTX_load_verify_locations(ctx,"GoogleInternetAuthorityG2.pem",NULL);
if (result == 0) {
puts("Opps... Can't load the certificate");
}
result = SSL_CTX_load_verify_locations(ctx,"GeoTrustGlobalCA.pem",NULL);
if (result == 0) {
puts("Opps... Can't load the certificate");
}
After that, the usual stuff to connect and communicate:
BIO_set_conn_hostname(bio, "www.google.com:https");
And get no errors when loading or connecting.
However, the verification does not work.
result = SSL_get_verify_result(ssl);
printf("The Verify Result is %d \n",result);
I get the return UNABLE_TO_GET_ISSUER_CERT_LOCALLY (error code 20).
So, am I missing some concept here? Wouldn't this give me the X509_V_OK result because it has the trusted certificates? There were only two that were up the chain from google.com, and I used them.
The second call to SSL_CTX_load_verify_locations is replacing the certificate from the first call.
You should combine your roots into a single file:
$ cat my-trusted-roots.pem
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
And then load that single file with SSL_CTX_load_verify_locations. See the OpenSSL docs on SSL_CTX_load_verify_locations. In partuclar, the NOTES section:
If CAfile is not NULL, it points to a file of CA certificates in PEM
format. The file can contain several CA certificates identified by
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
sequences. Before, between, and after the certificates text is allowed
which can be used e.g. for descriptions of the certificates.
Just bike shedding here...
result = SSL_get_verify_result(ssl);
printf("The Verify Result is %d \n",result);
That's one of three tests you need to perform.
The second test you need to perform is below. Anonymous Diffie-Hellman (ADH) does not use a certificate, so you need to check for that.
X509* cert = SSL_get_peer_certificate(ssl);
if(cert) X509_free(cert);
if(cert == NULL)
/* Error - Anonymous Diffie-Hellman */
SSL_get_peer_certificate bumps the reference count on the certificate, so you need a matching call to X509_free.
The third test you need to perform is hostname matching. OpenSSL 1.1.0 WILL perform hostname matching (and other name matching, like PKCS9 email addresses); but lesser versions, like 0.9.8 and 1.0.1, DO NOT perform the matching.
Thanks to this post I could finally get the SSL/TLS Client to work on Windows. I built openssl using MSYS2. I had to make some changes to the openssl-bio-fetch.tar.gz code so it could build/run in Windows/MSYS2, mostly adjusting the Makefile includes and setting -DNDEBUG to avoid the Posix signals.
However when running the code I got:
$ ./openssl-bio-fetch.exe
Warning: thread locking is not implemented
verify_callback (depth=1)(preverify=0)
Issuer (cn): DigiCert High Assurance EV Root CA
Subject (cn): DigiCert SHA2 Extended Validation Server CA
Error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
certificate verify failed
I had to download the 2 .pem files:
DigiCert High Assurance EV Root CA
DigiCert SHA2 Extended Validation Server CA
AND PASTE THE CERTIFICATES TO THE SAME .pem FILE ALREADY IN USE BY THE CODE: random-org-chain.pem
Thank You!

OpenSSL: unable to verify the first certificate for Experian URL

I am trying to verify an SSL connection to Experian in Ubuntu 10.10 with OpenSSL client.
openssl s_client -CApath /etc/ssl/certs/ -connect dm1.experian.com:443
The problem is that the connection closes with a Verify return code: 21 (unable to verify the first certificate).
I've checked the certificate list, and the Certificate used to sign Experian (VeriSign Class 3 Secure Server CA - G3) is included in the list.
/etc/ssl/certs/ca-certificates.crt
Yet I don't know why it is not able to verify the first certificate.
The entire response could be seen here:
https://gist.github.com/1248790
The first error message is telling you more about the problem:
verify error:num=20:unable to get local issuer certificate
The issuing certificate authority of the end entity server certificate is
VeriSign Class 3 Secure Server CA - G3
Look closely in your CA file - you will not find this certificate since it is an intermediary CA - what you found was a similar-named G3 Public Primary CA of VeriSign.
But why does the other connection succeed, but this one doesn't? The problem is a misconfiguration of the servers (see for yourself using the -debug option). The "good" server sends the entire certificate chain during the handshake, therefore providing you with the necessary intermediate certificates.
But the server that is failing sends you only the end entity certificate, and OpenSSL is not capable of downloading the missing intermediate certificate "on the fly" (which would be possible by interpreting the Authority Information Access extension). Therefore your attempt fails using s_client but it would succeed nevertheless if you browse to the same URL using e.g. FireFox (which does support the "certificate discovery" feature).
Your options to solve the problem are either fixing this on the server side by making the server send the entire chain, too, or by passing the missing intermediate certificate to OpenSSL as a client-side parameter.
Adding additional information to emboss's answer.
To put it simply, there is an incorrect cert in your certificate chain.
For example, your certificate authority will have most likely given you 3 files.
your_domain_name.crt
DigiCertCA.crt # (Or whatever the name of your certificate authority is)
TrustedRoot.crt
You most likely combined all of these files into one bundle.
-----BEGIN CERTIFICATE-----
(Your Primary SSL certificate: your_domain_name.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Intermediate certificate: DigiCertCA.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Root certificate: TrustedRoot.crt)
-----END CERTIFICATE-----
If you create the bundle, but use an old, or an incorrect version of your Intermediate Cert (DigiCertCA.crt in my example), you will get the exact symptoms you are describing.
SSL connections appear to work from browser
SSL connections fail from other clients
Curl fails with error: "curl: (60) SSL certificate : unable to get local issuer certificate"
openssl s_client -connect gives error "verify error:num=20:unable to get local issuer certificate"
Redownload all certs from your certificate authority and make a fresh bundle.
I came across the same issue installing my signed certificate on an Amazon Elastic Load Balancer instance.
All seemed find via a browser (Chrome) but accessing the site via my java client produced the exception javax.net.ssl.SSLPeerUnverifiedException
What I had not done was provide a "certificate chain" file when installing my certificate on my ELB instance (see https://serverfault.com/questions/419432/install-ssl-on-amazon-elastic-load-balancer-with-godaddy-wildcard-certificate)
We were only sent our signed public key from the signing authority so I had to create my own certificate chain file. Using my browser's certificate viewer panel I exported each certificate in the signing chain. (The order of the certificate chain in important, see https://forums.aws.amazon.com/message.jspa?messageID=222086)
Here is what you can do:-
Exim SSL certificates
By default, the /etc/exim.conf will use the cert/key files:
/etc/exim.cert
/etc/exim.key
so if you're wondering where to set your files, that's where.
They're controlled by the exim.conf's options:
tls_certificate = /etc/exim.cert
tls_privatekey = /etc/exim.key
Intermediate Certificates
If you have a CA Root certificate (ca bundle, chain, etc.) you'll add the contents of your CA into the exim.cert, after your actual certificate.
Probably a good idea to make sure you have a copy of everything elsewhere in case you make an error.
Dovecot and ProFtpd should also read it correctly, so dovecot no longer needs the ssl_ca option.
So for both cases, there is no need to make any changes to either the exim.conf or dovecot.conf(/etc/dovecot/conf/ssl.conf)
If you are using MacOS use:
sudo cp /usr/local/etc/openssl/cert.pem /etc/ssl/certs
after this Trust anchor not found error disappears
For those using zerossl.com certificates, drag and drop all certificates (as is) to their respective folders.
Cut and pasting text into existing files, may cause utf8 issues - depending upon OS, format and character spacings.