I have an API running with express using https. For testing, I've been using tinycert.org for the certificates, which work fine on my machine.
I'm using docker to package up the app, and docker-machine with docker-compose to run it on a digital ocean server.
When I try to connect with Chrome, I get ERR_SSL_VERSION_OR_CIPHER_MISMATCH. When running this with curl, I get a handshake failure: curl: (35) SSL peer handshake failed, the server most likely requires a client certificate to connect.
I tried to debug with Wireshark's SSL dissector, but it hasn't given me much more info: I can see the "Client Hello" and then the next frame is "Handshake Failure (40)".
I considered that maybe node on the docker container has no available ciphers, but it has a huge list, so it can't be that. I'm unsure as to what's going on and how to remedy it.
EDIT
Here's my createServer() block:
let app = express();
let httpsOpts = {
key: fs.readFileSync("./secure/key.pem"),
cert: fs.readFileSync("./secure/cert.pem")
};
let port = 8080;
https.createServer(httpsOpts, app).listen(port);
I've had this problem for a really long time too, there's a weird fix:
Don't convert your certs to .pem; it works fine as .crt and .key files.
Add ca: fs.readFileSync("path to CA bundle file") to the https options.
It looks like your server is only sending the top certificate and the CA bundle file has the intermediate and root certificates which you'll need for non-browser use.
IMPORTANT! Reinstall or update node to the latest version.
You can use sudo apt-get upgrade if you're on Linux (it may take a while).
Re-download your certificate or get a new one.
If you are acting as your own certificate authority it could be not recognizing / trusting the certificate, so try testing your site on ssllabs.com.
If you're using the http2 API try adding allowHTTP1: true to the options.
Related
I'm building a WebApp with Node- & ExpressJS. Currently I'm trying to connect my app to our company's Keycloak with the keycloak-connect module. I configured it as mentioned in different tutorials and it works (atleast mostly).
When I connect to my WebApp, I receive the keycloak login screen and the login procedure is successful (session created on keycloak). After the login procedure and the redirect I receive an "Access denied" error and in the logs "Could not obtain grant code: unable to get local issuer certificate".
WebApp runs on port 443 with valid certificates
I've googled everything I could and tried following solutions:
-- Disable rejecting unauthorized TLS --
Disabled TLS Rejection for unauthorized certificates with the node envorinment variable:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
Works but isn't very secure...
Log.
-- Add an extra CA certificate --
Installed dotenv module and set following env variable in .env file:
NODE_EXTRA_CA_CERTS='/etc/pki/tls/cert.pem' (& ca-bundle.crt)
Included it in app.js with "require('dotenv').config();", doesn't work... Also tried to set it as a system environment variable with export.
It stands behind a proxy but I also configured express to trust all proxies with "app.set('trust proxy', true);".
-- Versions --
Node - v16.13.1
Express - ~4.16.1
Keycloak-connect - ^16.1.1
I've seen this problem on many different pages and they're mostly not fully resolved... Would be nice to find a solution for this problem.
Thanks in advance! :)
Yannic
Well I've found a solution and it works perfectly!
This comment on a GitHub issue describes, how to send ca files with the HTTPS server from NodeJS.
You can enter your ca files / bundles in an array:
const trustedCa = [
'/etc/pki/tls/certs/ca-bundle.crt',
'/etc/pki/tls/cert.pem'
];
Then read them with fileSync and set them as the globalAgent.options.ca option for the HTTPS server:
https.globalAgent.options.ca = [];
for (const ca of trustedCa) {
https.globalAgent.options.ca.push(fs.readFileSync(ca));
}
And that's all that needs to be done! Now I can login via Keycloak and it successfully redirects me to my WebApp without any errors.
Hopefully this helps.
Yannic
I am using Django 2.2, I want to enable https in it.
I have installed Django-SSL server and I have the certificate and the private key.
I am running the script like:
python manage.py runsslserver --certificate /path/to/certificate.pem --key /path/to/key.key
when I am running the above command the server is running like:
Starting development server at https://127.0.0.1:8000/
Using SSL certificate: C:\Users\djangotutorial\myvenv\lib\site-packages\sslserver\certs\certificate.pem
Using SSL key: C:\Users\djangotutorial\myvenv\lib\site-packages\sslserver\certs\key.key
but when I am opening the link it is showing the unsecure connection.
How to fix this?
Cause you have used a self-singed ssl certificate, just ingore the warning and you'll got your web page.
I am trying to make work icecast 2 and my letsencrypt SSL with no luck. So far what I did is built icecast 2 with openssl support and I also made it run but it always give the next error in the log file.
[2018-03-15 12:48:21] WARN connection/get_ssl_certificate Invalid private key file /usr/local/icecast/share/fullchain.pem
[2018-03-15 12:48:21] INFO connection/get_ssl_certificate No SSL capability on any configured ports
I have set these cert files readable by user: richard and of course I am also running the server itself with the richard user.
Maybe you have any idea what is wrong?
You may also see my config file here:
<listen-socket>
<port>8443</port>
<ssl>1</ssl>
</listen-socket>
In the path section I have set the ssl-certificate part to the SSL.
<ssl-certificate>/usr/local/icecast/share/icecast/fullchain.pem</ssl-certificate>
Nothing so far. The server itself is starting on the port, however when visiting it through https:// it just doesn't load. with http:// the port (8443) works fine.
Any help appricated.
Actually, I solved the issue myself.
The problem was the SSL not the configurations. Seems the LetsEncrypt SSL that is generated (fullchain.pem) is not working correctly. So instead of using that, I have copied the content from cert.pem and privkey.pem and made a new file named icecast.pem and pasted both into one. (first cert and then the privkey) and now everything is works fine and secure!
I am a genius!!!
For the Icecast2 complete certificate, you can use the command:
cat /etc/letsencrypt/live/domain.com/fullcert.pem /etc/letsencrypt/live/domain.com/privkey.pem > /etc/icecast2/bundle.pem
This will concatenate and save both certificates to a single file called bundle.pem under icecast2 folder, to which you can point the icecast2 configuration.
I have also found this very helpful and complete guide for reference: https://mediarealm.com.au/articles/icecast-https-ssl-setup-lets-encrypt/
There is another way, by forwarding of Nginx, whose config is common on internet. So that the server only expose 80 and 443 port for http web. Then use letsencrypt for SSL of Nginx.
How do I download a proxy's SSL cert and save it to a file using the Linux command line.
It's possible to download an ssl cert via the openssl tool: https://superuser.com/questions/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file. But this does not work when behind a corporate proxy that re-writes the SSL cert. I would like to download the proxy's ssl cert. Changing the HOST and PORT to my proxy's host and port does not work either.
Downloading the cert using my browser works but I need to do this in a bash script.
You can only extract certificates from the connection which actually get send inside the connection. Within a MITM proxy the root CA you want to have usually does not get send since it is expected to be installed locally as trusted, similar to a public root CA. And the reason you can extract this MITM CA within your browser is because the browser already has this CA as trusted in the CA store and can thus export it.
As mentioned here, openssl 1.1.0 and above support the -proxy argument so you can get the proxy's certificates with a command like (jcenter.bintray.com is just an example host to connect to)
openssl s_client -showcerts -proxy $https_proxy -connect jcenter.bintray.com:443
Also see this script for a more complete example how to import the certificate(s) to a JVM keystore and the system certificates.
I'm trying to setup IIS 8 (Windows Server 2012) to accept client certificates for a secured WebAPI endpoint. Following this post I created a self signed certificate and a client certificate:
makecert.exe -r -n "CN=MyCompany" -pe -sv MyCompany.pvk -a sha1 -len 2048 -cy authority MyCompany.cer
makecert.exe -iv MyCompany.pvk -ic MyCompany.cer -n "CN=MY Client" -pe -sv MyClient.pvk -a sha1 -len 2048 -sky exchange MyClient.cer -eku 1.3.6.1.5.5.7.3.2
pvk2pfx.exe -pvk MyClient.pvk -spc MyClient.cer -pfx MyClient.pfx -po THE_PASSWORD
I installed the root certificate MyCompany.cer on the IIS server, then on IIS Manager/SSL Settings I selected the "Accept" radio button to allow the website accept client certificates.
On the client side a have a C# test console app that loads the client cert MyClient.pfx file and calls the WebAPI endpoint:
var certHandler = new WebRequestHandler();
certHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
certHandler.UseProxy = false;
var certificate = new X509Certificate2(File.ReadAllBytes(#"C:\MyClient.pfx"), "THE_PASSWORD");
certHandler.ClientCertificates.Add(certificate);
var client = new HttpClient(certHandler);
var result = client.GetAsync("https://MyServer/api/MyEndpoint").Result;
string resultStr = result.Content.ReadAsStringAsync().Result;
Console.WriteLine(resultStr);
I'm getting back a 403 error:
403 - Forbidden: Access is denied.
You do not have permission to view this directory or page using the credentials that you supplied.
I tried the same setup on my local IIS (Windows 7): Imported the MyCompany.cer file, setup SSL in IIS. This time everything works fine and the WebAPI endpoint can see the client certificate with no problem.
Any ideas?
-- Update 1
I enabled Failed REquest Tracing on IIS and I get this:
<failedRequest url="https://myserver:443/"
siteId="35"
appPoolId="CertTest"
processId="7248"
verb="GET"
authenticationType="NOT_AVAILABLE" activityId="{00000000-0000-0000-B0AA-0280000000E0}"
failureReason="STATUS_CODE"
statusCode="403.16"
triggerStatusCode="403.16"
timeTaken="0"
xmlns:freb="http://schemas.microsoft.com/win/2006/06/iis/freb"
>
If I understand right the error is 403.16. I understand that happens when the certificate on the server is not imported into the Trusted Root Certification Authorities under Local Computer. I double checked and that's not my case.
Check that
On your IIS machine you have installed Server's cert issuer certificate to Trusted Root Certification Authorities under Local Computer
On your IIS machine you have installed Client's cert issuer certificate to Trusted Root Certification Authorities under Local Computer
On your client machine you have installed Server's cert issuer certificate to Trusted Root Certification Authorities under Windows User that runs console app
On your client machine you have installed Client's cert issuer certificate to Trusted Root Certification Authorities under Windows User that runs console app. Or you can make sure to include all necessary certificate's chain to pfx file
In code use X509Certificate2's ctor version with X509KeyStorageFlags.UserKeySet explicitly.
If it won't help,
try to open url in IE (under the same Windows User Account that runs console app).
open *.cer files with double click on a client machine under Windows User Account that runs console app and see what Windows says about they validity.
change IIS SSL settings to ignore client certificate to see if it's all good with server certificate. Try both browser and console app.
Have a look at the following blog post: https://configmgrblog.com/2014/02/23/configmgr-2012-r2-internet-facing-mp-windows-server-2012-r2-note/
In short: There seems to be an issue with client certificate authentication and IIS 8.x in Windows Server 2012 (R2), that might cause status code 403.16 to be returned when using client certificates. Solution:
Set registry DWORD entries under HKey_Local_Machine\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL on your server:
SendTrustedIssuerList = 0
ClientAuthTrustMode = 2
The post further mentions that if your get a 403.13 (client certificate revoked) after fixing the in initial problem (403.16), you should disable client certificate revocation check on the server. I would not recommend that. Please make sure that the CDP is correctly set in the client certificate. The CDP has to be reachable from the server and the revocation list should be valid and not outdated.