Introduction
During development or internal testing phases, we often need to deploy various services to meet specific requirements, such as:
- Using Nginx to set up a web server for traffic distribution or serving static resources
- Implementing DNS over HTTPS (DoH) with AdGuardHome to block ads and enhance privacy
- Deploying dynamic applications using Node.js or Deno (e.g., APIs or full-stack frameworks like Next.js)
- Running services within Docker containers
When implementing intranet-related services, if a login page requires a password, the browser will display a warning stating that “this connection is not secure” if the HTTPS protocol is not used. This article explains how to generate self-signed certificates and apply them to these services, ultimately configuring the system to trust the certificates.
What is HTTP(S)
HTTP (HyperText Transfer Protocol) and HTTPS (HyperText Transfer Protocol Secure) are application-layer protocols commonly used for data transmission, defining how applications exchange information. HTTP transmits data in plain text, making it vulnerable to interception and analysis by hackers or third parties, potentially exposing sensitive information such as passwords or other confidential data. In contrast, HTTPS is an extension of HTTP that incorporates the TLS (Transport Layer Security) encryption protocol. It ensures the confidentiality, integrity, and authentication of data, meaning even if intercepted, the data cannot be decrypted or misused, significantly reducing the risk of sensitive information leakage.
TLS is the successor to SSL (Secure Sockets Layer) and has been the standard for network encryption since 1999, replacing SSL. Compared to the now-deprecated SSL, TLS offers a more efficient handshake process, improved encryption algorithms, and fixes for known vulnerabilities. It is recommended to use TLS 1.2 (introduced in 2008) or TLS 1.3 (introduced in 2018) to ensure modern communication security standards. Although the term “SSL” is still widely used as a generic reference for encryption protocols, modern HTTPS communications are entirely based on TLS.
Additionally, open-source tools like OpenSSL play a critical role in implementing TLS/SSL protocols. OpenSSL supports key operations such as certificate generation, signing, and verification, making it a cornerstone for establishing secure HTTPS environments.
What is a Certificate
A certificate is one of the core elements of HTTPS security. HTTPS uses digital certificates to verify the identity of a server. These digital certificates are typically implemented as X.509 certificates, which define essential server identity information such as the domain name, public key, validity period, issuing authority, and other extended attributes. A trusted Certificate Authority (CA) digitally signs this information to ensure the certificate’s integrity and trustworthiness, thereby preventing man-in-the-middle attacks and server impersonation.
To generate an X.509 certificate, a key pair must first be created, consisting of:
- Private Key: Used to encrypt data or create digital signatures. It must be securely stored and never disclosed.
- Public Key: Used to encrypt data or verify data signed with the private key, ensuring the integrity and authenticity of the information. The public key is derived from the private key through an asymmetric encryption algorithm and is paired with it. However, it is computationally infeasible to derive the private key from the public key.
Using the public key generated from the private key, we can create a Certificate Signing Request (CSR), which is the foundational document for generating a certificate. Once the CSR is submitted to a Certificate Authority (CA), the CA, as a trusted entity, verifies the server’s identity based on the information in the CSR. The CA then uses the public key in the CSR to issue and sign the official certificate, which is used for server authentication and encrypted communication. The CSR includes:
- Common Name (CN): The hostname or domain name, such as wellstsai.com
- Organization Information: Details such as the company name, country, and region.
- Public Key: Generated from the private key and embedded within the CSR file, used for identity verification and secure communication.
If the CSR is submitted to a CA, the CA will verify the server’s identity. Once the verification is complete, the CA uses its private key to digitally sign the CSR and set the certificate’s validity period, ultimately issuing a formal X.509 certificate.
If the certificate is self-signed, there is no need for a CA to be involved. In this case, you can use your private key to directly sign the CSR, producing a self-signed X.509 certificate. While self-signed certificates technically provide the same functionality as CA-signed certificates, they are not recognized by public trust authorities. Therefore, they are best suited for internal testing environments or private systems.
Finally, the generated private key and certificate are configured on the server and integrated into the server’s HTTPS settings (e.g., Nginx). When a user visits the website, the browser automatically initiates the digital certificate verification process with the server.
The browser determines whether a certificate is signed by a trusted CA, is still within its validity period, and matches the domain being accessed. If all these conditions are met, the browser will display a secure connection lock icon in the top-left corner of the address bar, indicating that the website’s certificate is valid and trustworthy. Subsequently, the browser and server will establish an encrypted communication channel.
During this process, the browser uses the public key from the server’s certificate to securely generate and transmit a symmetric encryption key. After the server decrypts this key, both parties share the same symmetric encryption key (which is faster) to encrypt subsequent data transmissions.
This ensures that the communication between the user and the server (e.g., browsing data, form submissions) is protected through symmetric encryption and decryption. This protection prevents third parties (such as man-in-the-middle attackers or malicious actors) from stealing or tampering with the transmitted data.
Generate a Self-Signed Certificate
Check OpenSSL Environment
Ensure OpenSSL is installed by entering the following command in the terminal:
|
|
If OpenSSL is installed, the output will be:
|
|
If it is not installed, you can use apt
to install it.
For Windows, you need to manually download the installer from slproweb.
|
|
After installation, check the version number using openssl version
. There should be a version output.
Create a One-Click Certificate Generation Script
Using your preferred editor (such as VS Code, Nano, or Vim), copy and paste the following content into the editor. Modify the corresponding parameters (e.g., country code, city name, domain
, certificate validity period, etc.) as needed, then save the file as ~/generate_tls_cert.sh
:
|
|
In this case, my local server name is wells_server
. If there is an actual domain name like wellstsai.com
, you should enter the corresponding domain or IP.
From the script, you can see that the process first generates a private key and then produces a CSR file. The CSR file must include relevant domain names and geographical information.
The subjectAltName
(SAN) in the CSR is an extended attribute of the X.509 certificate, primarily used to specify multiple hostnames, domain names, or IP addresses that the certificate applies to. The names in the SAN field are written into the certificate to ensure that browsers or other clients can correctly verify that the certificate matches the requested resource.
Since April 2017, Chrome version 58 and other Chromium-based browsers (such as Chrome and Edge) no longer rely on the certificate’s CN field for hostname validation and instead only depend on the SAN field. This makes SAN a necessary attribute in modern certificate configurations.
Finally, after generating the CSR file, the certificate is self-signed using the private key.
Execute the Script
After confirming that the domain settings are correct, save the modifications and add execute permissions to the script:
|
|
Next, execute the script to generate the certificate:
|
|
After running the script, three files will be generated in the ~/certificates/
folder in the user’s home directory: the private key, the CSR file, and the certificate.
|
|
Ensure that these files are properly stored, and avoid exposing the private key to maintain security.
Using the Certificate in Docker
Here, we use Portainer as an example. Since I have previously set up Portainer, I will first stop and remove the existing container using stop
and rm
commands, then recreate the container.
|
|
Then, recreate the container using the following command, which is based on the official documentation, but with the private key and certificate I provided.
|
|
Installing a Self-Signed Certificate on the System
When using a self-signed certificate to set up a server, since it is not signed by a CA, the system or browser will not automatically trust the certificate. Therefore, you need to manually add the certificate to the trust list, otherwise, the system or browser will warn that the connection is insecure and display a prompt indicating that the certificate is not trusted.
The following steps explain how to import a self-signed certificate into the system, primarily for Windows.
You can use scp [user]@[server]:[file path] [local path]
or use VS Code to download the file from the server to your local machine.
|
|
After downloading, you can install the certificate either through the graphical interface or via command line. Double-click on wells_server.crt
, click on “Install Certificate”, select Current User
as the storage scope, and place the certificate under Trusted Root Certification Authorities
.
Alternatively, you can use the terminal command to place the certificate under the Trusted Root Certification Authorities for the current user:
|
|
Close the browser and reopen it, then connect to the relevant service’s URL. At this point, the certificate status displayed in the top-left corner of the browser should show as a trusted certificate.
Common Certificate Authorities
Finally, a brief introduction to some common CAs. These organizations are responsible for issuing and verifying certificates, ensuring the trustworthiness of a website’s identity, and providing a secure HTTPS communication environment. Certificates signed by a CA are automatically trusted by the operating system and browsers (as long as the CA is part of the system’s “trusted root certificate store”). When users browse websites, an encrypted connection is established directly, avoiding “insecure” warnings and effectively preventing man-in-the-middle (MITM) attacks, thus improving website trustworthiness and user experience. This is typically used in production environments or for publicly accessible domains.
According to W3Techs statistics (as of December 4, 2024), here are the major CAs and their market share:
- Let’s Encrypt has a 59.1% usage rate and a market share of 62.9%. Its key feature is providing
free
andautomated
certificate services, making it especially popular among small-to-medium-sized websites and individual developers. - GlobalSign has a usage rate of 20.3% and a market share of 21.6%. It primarily serves enterprises and government organizations, known for its high security and reliability.
- Sectigo has a usage rate of 6.1% and a market share of 6.4%. It offers a variety of certificate products and affordable pricing to attract businesses of all sizes.
- GoDaddy holds a market share of 4.3%. This CA targets the small-to-medium business market, providing convenient domain and SSL certificate integration services.
- DigiCert has a usage rate of 4.0% and a market share of 4.2%. It focuses on high-security and enterprise-level needs, particularly in financial and high-risk industry applications.
Conclusion
This article provides a detailed explanation of how to use OpenSSL to generate a self-signed certificate and apply it to internal servers and container services (such as Nginx and Docker). By using self-signed certificates, we can quickly enable HTTPS in internal environments, encrypt communication, and enhance security. While self-signed certificates are not suitable for public websites, they offer a simple, efficient, and cost-effective solution for internal testing or development phases.
For IT personnel in internal networks, deploying the self-signed certificate across internal servers and adding it to the trusted certificate store of the internal system can quickly complete the full HTTPS upgrade, creating a secure and efficient internal communication environment.
The primary purpose of a certificate is to establish a secure connection between the server and the user. Although self-signed certificates are not recognized by public CAs, once the correct certificate is manually trusted, even if a man-in-the-middle attack occurs, the attacker cannot forge a matching private key for the original certificate. The browser will display a “Not Secure” warning due to the certificate mismatch, effectively preventing the threat of a man-in-the-middle attack.
In a previous article, “Taiwan’s DNS RPZ Network: Blocking and Unblocking Strategies,” similar certificate issues were also mentioned. In that case, certificate errors occurred due to DNS hijacking of the original website’s certificate, which further emphasizes the importance of properly configuring and verifying the trustworthiness of certificates.
References
- Rename OpenSSL to OpenTLS To Comply with RFC7568
- RFC 7568 - Deprecating Secure Sockets Layer Version 3.0
- RFC 2246 - The TLS Protocol Version 1.0
- TLS vs. SSL - Win32 apps | Microsoft Learn
- SSL vs TLS - Difference Between Communication Protocols - AWS
- X.509 - Wikipedia
- X.509 certificates | Microsoft Learn
- Deprecations and Removals in Chrome 58 | Chrome for Developers
- Security Changes in Chrome 58 - What You Need to Know
- Using your own SSL certificate with Portainer | Portainer Documentation
- How do you add a certificate authority (CA) to Ubuntu? - Super User
- Usage Statistics and Market Share of SSL Certificate Authorities for Websites, December 2024