Secure Apache with a Self-Signed TLS/SSL Certificate on Ubuntu 20.04
Introduction
Transport Layer Security (TLS) and Secure Sockets Layer (SSL) are both internet-based security protocols that encrypt data over a network. For instance, when clients connect to your webserver to request a web page, you should encrypt the connection with a TLS/SSL certificate when receiving their sensitive data such as passwords and credit card information.
There is always a serious cyber threat across the internet when you exchange classified information in plain text between a client (for instance, a web browser, a mobile app, or desktop software) and a server system like Apache. Therefore, you need to implement a security layer between your systems. This is where an SSL/TLS certificate comes into play.
To generate an SSL/TLS certificate, you start by creating a Certificate Signing Request (CSR) on your server which generates a public/private key pair and a subject identifying the name of your website. Then, you simply send the CSR to a trusted Certificate Authority (CA) for signing at a fee.
Sometimes, there is no need to send the certificate for signing to a publicly trusted third-party CA. You can easily deploy and customize a self-signed certificate using OpenSSL without incurring any costs. However, only you can trust the certificate and anyone trying to connect to your web server will get a warning in their browser. Nevertheless, these kinds of certificates are highly suitable for internal networks and testing environments when performing initial configurations.
In this guide, you'll secure your Apache webserver with a self-signed certificate on Ubuntu 20.04 server.
Prerequisites
To complete this guide, make sure you've the following:
- An Ubuntu 20.04 server.
- A sudo user.
- An Apache webserver.
1. Generate a Private Key and a Certificate File
When securing your web traffic with the SSL/TLS protocol, you simply share your public key with anyone and keep your private key on your server. To create these keys, run the following openssl
command.
$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache.key -out /etc/ssl/certs/apache.crt
The openssl
command explained:
req -x509: You're using this option to create a self-signed certificate instead of generating a CSR.
-nodes: By specifying this option, you're telling
openssl
to avoid encrypting the private key with a passphrase. This is because you don't want to keep entering a password manually every time your server restarts. Apache should read this file without your intervention.-days n: This is the number of days that you want the certificate to remain valid. For instance
365
days.-newkey rsa:2048: You declare an explicit key size with this option. The smallest acceptable file is
512
bits but a larger value of2048
offers more security.-keyout filename: This is the file name where you're saving your newly created private key.
-out filename: Here, you specify an output
*.crt
file to store your signed certificate.
Once you execute the openssl
command, you'll be prompted to provide the following information to generate your certificate. Enter the appropriate values and press Enter after every response.
Country Name (2 letter code) [AU]: Keyin a two-letter code of your country. For instance KE, or USA.
State or Province Name (full name) [Some-State]: Enter a full name for your state, for instance, CALIFORNIA.
Locality Name (eg, city) []: Enter your city e.g. LOS ANGELES.
Organization Name (eg, company) [Internet Widgits Pty Ltd]: Enter the name of your organization. For instance, SAMPLE COMPANY
Organizational Unit Name (eg, section) []: Key in your organization department e.g. IT.
Common Name (e.g. server FQDN or YOUR name) []: Enter the fully qualified domain name or IP address for your server. For instance example.com or 192.0.2.1.
Email Address []: Enter your email address e.g. info@example.com.
Once you complete providing the information, the openssl
command should generate a private key and a certificate file in the following locations.
/etc/ssl/private/apache.key
/etc/ssl/certs/apache.crt
You've now generated the necessary files for your SSL/TLS certificate. In the next step, you will configure the SSL/TLS settings on the Apache virtual host file.
2. Enable SSL on the Virtual Host File
Apache maintains a default virtual host file to handle SSL traffic under the /etc/apache2/sites-available
directory named default-ssl.conf
. In order for the webserver to encrypt data with your certificate, you'll make some configuration changes in this file.
Use nano
text editor to open the /etc/apache2/sites-available/default-ssl.conf
file.
$ sudo nano /etc/apache2/sites-available/default-ssl.conf
In this file, locate the line ServerAdmin sample_email@example.com
as shown below.
...
ServerAdmin sample_email@example.com
DocumentRoot /var/www/html
...
Under the above line, add the ServerName
name directive followed by your domain name or the public IP address of your server as shown below.
...
ServerAdmin sample_email@example.com
ServerName 192.0.2.1
DocumentRoot /var/www/html
...
Then, still in the same file, locate the SSL settings below.
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
Specify the full file paths of your certificate (/etc/ssl/certs/apache.crt
) and private key (/etc/ssl/private/apache.key
). The two lines should look as follows after editing.
SSLCertificateFile /etc/ssl/certs/apache.crt
SSLCertificateKeyFile /etc/ssl/private/apache.key
Save and close the file when you're done with editing. Next, use the Apache a2enmod
command to enable the ssl
module.
$ sudo a2enmod ssl
Then, use the a2ensite
to enable the default-ssl.conf
virtual host file.
$ sudo a2ensite default-ssl.conf
Restart the Apache webserver to load the new changes.
$ sudo systemctl restart apache2
Your apache web server is now ready to serve encrypted content. However, before you test the new settings, you'll configure your firewall to allow secure connections through port 443
.
3. Enable SSL Port on the Firewall
In Apache, you should allow secure traffic to be exchanged through port 443
as opposed to the default port 80
which sends data in plain text. You can enable the HTTPS
port using the ufw
utility. First, enable your firewall by executing the following command.
$ sudo ufw enable
When prompted, press Y and Enter. Ensure you get the following response.
Firewall is active and enabled on system startup
Next, allow Apache to listen on both ports 80
and 443
by executing the command below.
$ sudo ufw allow 'Apache Full'
Output.
Rule added
Rule added (v6)
To avoid locking yourself out of the server, allow ssh
connections through the OpenSSH
port by running the following command.
$ sudo ufw allow 'OpenSSH'
Output.
Rule added
Rule added (v6)
Make sure you've opened any other port depending on the applications you're running. Then, execute the ufw status
command to check if you've successfully added the new firewall rules.
$ sudo ufw status
You should receive the following output.
To Action From
-- ------ ----
Apache Full ALLOW Anywhere
OpenSSH ALLOW Anywhere
Apache Full (v6) ALLOW Anywhere (v6)
OpenSSH (v6) ALLOW Anywhere (v6)
...
You've now configured your firewall to allow encrypted traffic to your webserver. In the next step, you'll visit your secured site and see if everything works as expected.
4. Test the New Configuration
Visit the URL below in a web browser and replace 192.0.2.1
with the correct public IP address or domain name. Make sure you're using the https://
protocol.
Your Apache server should now encrypt any data that you may try to exchange using the SSL/TLS certificate. Please note, your browser may issue a warning when you visit the page (Your connection is not private
) because this certificate is not signed by a trusted CA. However, just suppress the warning and visit the page because you're only interested in the encryption part of your certificate. In the next step, you'll direct anyone trying to connect to the server via the insecure port 80
to the encrypted port 443
.
5. Redirect HTTP Traffic to HTTPS (Optional)
Once you've generated, set up, and tested your SSL/TLS certificate, you can optionally redirect any HTTP
traffic to HTTPS
by editing the /etc/apache2/sites-available/000-default.conf
file. Use nano
to open the file.
$ sudo nano /etc/apache2/sites-available/000-default.conf
Then, enter the line Redirect "/" "https://192.0.2.1/"
just below the <VirtualHost *:80>
opening tags. Again, replace 192.0.2.1
with your domain name or server's public IP address.
<VirtualHost *:80>
...
Redirect "/" "https://192.0.2.1/"
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
...
</VirtualHost>
Save and close the file. Next restart the Apache webserver to load the new configuration settings.
$ sudo systemctl restart apache2
Visit the HTTP
URL below on a web browser. You should now be redirected to the HTTPS
version of the web page.
Your SSL/TLS certificate and redirection settings are now working as expected. Any further communications between the webserver and clients will now be exchanged through the secure channel.
Conclusion
In this guide, you've secured traffic on your Apache webserver with an SSL/TLS certificate. You can now connect your APIs, mobile apps, and desktop applications to the secure port and encrypt sensitive data as it flows through the network.
To bypass SSL/TLS certificate warnings when using the self-signed certificates, refer to the resource below: