Self-signed certificate, issues and solutions
Recently, I've encounter several situations where I have to deal with self-signed certificate. As this is such a common issue, I've decided to write this article to document my learnings and for my own reference in the future.
This article will start by explaining what is a SSL certificate, and what is a self-signed certificate. From there, I will detail the problems I encountered recently on self-signed certificate, and how I solved them.
What is a (SSL) certificate?
A certificate, is something you used to prove you identity. For example, in most countries around the world, you would usually have something to identify who you are and prove you are who you claimed to be, this could be something like a driver license, and are usually issued by the government.
In the context of internet security, you've got SSL certificate. This is something the browser would use to authenticate the identity of a website. An SSL certificate is most likely issued and signed by a trusted CA or certificate authority.
What is a self-signed certificate?
To put it in short, a self-signed certificate is something that's issued and signed by the same party. In other words, this is like you have issued yourself a driver license, to identify and prove you are you. I'm pretty sure you would have a hard time convincing people to accept that as a proof of your identity.
Benefits and risks associated with self-signed certificate
It is quite obvious that to most people, self-signed certificate would pose a big risk. Because SSL certificate are usually used for HTTPS communication, if a self-signed certificate is obtained from an untrusted source and installed on your computer, the malicious party can pretend to be a any website, and will be able to decrypt the HTTPS traffic from your computer. This is called Man-in-the-middle attack.
However, with increasingly strict requirement on HTTPS in most browsers, it is necessary to trust a self-signed certificate. Here are some common scenarios.
- In a large enterprise, the intranet traffic is usually not exposed to the public. In this situation, a self-signed certificate is appropriate because it would allow the traffic to be encrypted properly.
- In a home or SOHO network environment, you may want to use a self-signed certificate on your router, this will stop your browser from complaining about HTTP traffic.
- In a development environment, you may also want to use a self-signed certificate. This is so that you can utilize the Man-in-the-middle method and sniff some of the HTTPS traffic, making things easier to debug. (This is especially useful when you are doing mobile application development)
Issues and solutions
I would like to go over the issues I have encountered recently on self-signed certificates. In most situations, to solve the problem, you can either bypass or trust. Bypass means blindly trust all self-signed certificate and don't warn me again. Trust means trusting only the certificate in question, which means if you ever have another self-signed certificate, you would have to trust it again. Unless you have a very good reason, do not use the bypass solution.
Using self-signed certificate in JavaScript/NodeJS
If you are a NodeJS developer, you would most likely to have encounter error message like Self-signed certificate in certificate chain
. This error is actually from NodeJS https client, if you are using a third party library (like Apollo server client), you will have to dig and find how to pass custom http client to that library.
There are several ways to bypass this warning.
- At global level: using environment variable,
export NODE_TLS_REJECT_UNAUTHORIZED=0
- At HTTPS client level:
1
2
3
4
5
6
7
8
9https.request({
host: '192.168.1.1',
port: 443,
path: '/',
method: 'GET',
rejectUnauthorized: false,
requestCert: true,
agent: false
})
1 | const https = require('https'); |
Using self-signed certificate in Python
To bypass at a client level, add verify=False.
1 | import requests |
To trust the certificate, you will need to put the certificate on that machine and either use the environment variable or pass the certificate in the path
1 | import requests |
Or export REQUESTS_CA_BUNDLE = /path/to/your/certificate.pem
Using self-signed certificate with Docker/Colima
This is something I encountered recently, our internal Docker registry uses self-signed certificate, this turned out to be quite a challenge. I had to find ways to add the certificate Colima host machine for this to work correctly.
Here's the command I ran:colima ssh -- sudo sh -c "openssl s_client -showcerts -connect our-internal-url:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > /usr/local/share/ca-certificates/internal.crt && update-ca-certificates && cat /var/run/docker.pid | xargs kill"
This will download the certificate and install in the certificate storage in the colima VM in one go.
References
https://gist.github.com/jkremser/a8143384049b171d4e64c5aeb6da4793
- Some of the code in this article was generated using ChatGPT.