ARTICLE

BTC -

Click to copy address

Securing web apps through encryption.Quotation marks


Welcome to The Modern Guide to HTTPS!  This is a complete and comprehensive guide, covering all aspects of implementing and working with HTTPS that are relevant to the modern web developer.


If you want to roll up your sleeves and get started implementing HTTPS immediately, feel free to skip forward to The basics where you’ll get a quick overview of your options and get started with initial steps.  If you’re like me and you want to see the whole swimming pool before diving in, take the time to read and enjoy this guide from the beginning.  The big picture will give you context, history, and fill you in on why you should be using HTTPS to secure your web apps.



Guide navigation:

  1. { 1 }    The big picture: more than you ever wanted to know about HTTPS
  2. { 2 }    The basics: implementing HTTPS
  3. { 3 }    First things first: scrub your code
  4. { 4 }    Choose a certification method
  5. { 5 }    Open port 443
  6. { 6 }    Let’s Encrypt: obtain a free certificate
  7. { 7 }    Disable legacy protocols
  8. { 8 }    Remove weak ciphers
  9. { 9 }    Enable HSTS
  10. { 10 }  Finishing touches
  11. { 11 }  Next steps
  12. { 12 }  Bonus: configuration cheat sheet





The big picture: more than you ever wanted to know about HTTPS.Quotation marks


HTTP: the original.


In the beginning, there was HTTP.  As you probably know, HTTP, or Hypertext Transfer Protocol, is the main protocol used in a typical conversation between you (the client web browser) and a website (a remote web server).  HTTP is responsible for delivering web data when you connect to a web resource.  This occurs every time you navigate to, or interact with, a website.  When your computer receives data from the server, your web browser will decode and render it into a functioning website for you to then use.  This is HTTP on a basic level.


HTTP is a protocol that sits in the top “layer” of internet protocols called the Application Layer.  Let’s take a quick look at the Application Layer:


TCP/IP internet model beside the OSI internet model

We categorize and group all of the protocols having to do with the internet into different layers via either the TCP/IP Model or the OSI Model.  Understand that these two models are purely abstract categorization methods that engineers use to group internet protocols.  Both are valid and you can think about them any way you choose, just know that the TCP/IP Model is the current industry standard and that the HTTP protocol is placed in the top layer in BOTH models (as are API’s but that’s another topic entirely).  Keep in mind these models and the layer system for now because we will come back to it later.  As a developer you don’t need to know the entire scheme.


Back to HTTP: HTTP works very well and is still the main driver behind the internet today, however like many early protocols such as FTP (deprecated in favor of SFTP) and Telnet (deprecated in favor of SSH), it is insecure in its original form.  When the internet was just beginning, engineers didn’t give any thought to security, only to making it work, and that was fine for a long time.  Just like how SFTP is a secure version of FTP, and SSH is a secure version of Telnet, HTTPS is a secure version of HTTP.  What makes these protocols secure? We’ll get into that soon but the short answer is encryption.


Breaking HTTP.


We should take a moment to reflect on some of the threats to HTTP that made the development of HTTPS necessary, as these attacks can still occur today on any website not using HTTPS.  Attacking an unsecured HTTP communication usually takes one of these three forms:


  • - Intercepting the communication and gathering data.
  • - Intercepting the communication and tampering with the data.
  • - Tricking someone into communicating with you.

One of the most common HTTP exploits is eavesdropping, or listening in on the HTTP communication for sensitive/exploitable information.  If a user is communicating with a website on a public network (eg. open wifi), someone with the right tools can intercept the data packets being transmitted back and forth.  Often there is sensitive information contained within these packets such as the user’s site login credentials or his/her credit card information.  Really anything that the attacker deems useful can be gathered as the entire communication is “in the clear” and can more or less be overheard by anyone with the right skillset.


Another common, but more sophisticated exploit is packet injection.  Packet injection usually takes the form of an attacker intercepting packets and then modifying the data so that when the packets arrive at the client and his/her web browser re-assembles them, they run extra code that the attacker has planted within.  Packet injection can be used for “legitimate” purposes such as ISP’s injecting ads into 404 pages, but more commonly the packet hijacker will use this technique to run some type of malware on the client’s machine.  The different types of malware are beyond the scope of this guide but understand that a person listening in on an HTTP transmission can also pass in modified data which the receiving machine will automatically run on receipt.  This occurs because the client has no way of knowing that the transmission was tampered with.


Back in the days of pure HTTP, when we visited a website we had no way of knowing if roflcopter.com was actually roflcopter.com.  We only knew that typing in the web address sent us to a website by that name and there was some server that served us a website from that URL.  It was just assumed that the owners of the domain name were also the ones that owned and ran the server we were connecting to.  Eventually black hats realized that it was possible to co-opt a domain and run an alternative server that appeared to be legitimate but would harvest sensitive information from anyone that connected to it.  People that went to the website had no idea that they were entering their credit card information into a fake web store.  Essentially, there was no way to authenticate to the user that they were truly talking to the machine that they thought they were, and this weakness was exploited.


Enter HTTPS: a more secure version of HTTP that makes these common HTTP attacks (and more) largely impossible.


SSL: the early days of HTTPS.


You may still hear the term “SSL” thrown around quite a bit (as in “an SSL certificate”).  Often it is used interchangeably with the term HTTPS.  It is important that we take the time to make a few distinctions and explain what SSL actually is and how it relates to HTTPS.


SSL, or Secure Sockets Layer is not actually an entire layer despite its name, but simply another protocol, seperate from HTTP.  In the TCP/IP Model that we discussed previously, it exists in a sublayer below HTTP but is still considered part of the Application Layer.  Conveniently, SSL can serve as a base for HTTP, encrypting all communications that are run on top of it.  When HTTP is run on top of SSL it is sometimes called HTTP-over-SSL, but we all commonly know it as simply “HTTPS”. 


So what does HTTPS stand for?  Hypertext Transfer Protocol Secure.  The “secure” in the name is there because all HTTP communications are encrypted through the SSL protocol.  HTTP can become HTTPS if it is run through other encryption protocols such as TLS, but we will get to that a bit later.  Note that HTTPS is not technically a distinct protocol.  With HTTPS you have two protocols working together: HTTP and SSL.


SSL was the original HTTPS base and is what is known as a symmetric cryptographic protocol.  In other words it uses advanced ciphers and algorithms to encrypt communications between two machines that hold the same (symmetric) private key.  This guide won’t dive too deeply into the vast world of cryptography, but understand that within an SSL communication both machines hold the same key, therefore they have the ability to encrypt and decrypt data while sending and receiving that data.  This allows the entire HTTP communication to remain encrypted as long as both the client and the server trust each other.


Let’s quickly address one exception to the above rule: HTTPS actually has the ability to provide quite a bit of security when only one machine trusts the other.  If you think about how most websites work and what the common exploits are, you’ll notice that it is far more important for the server to be a trusted source than the client.  In most real-world scenarios, the server doesn’t need to care who the client is as its job is usually just to serve out the same public web data over and over to whomever requests it, regardless of who the user is.  As long as the server authenticates itself as a trusted source, HTTPS can still be used in the absence of a verified client, and this is true for the majority of web communications.


So how does HTTP-over-SSL (HTTPS) defeat the previous forms of attack that we encountered when running pure HTTP? Let’s address the three common attacks:


Before SSL, a third party could listen in on an HTTP communication and retrieve sensitive data from the intercepted packets.  SSL addresses this by encrypting the entire communication, rendering all intercepted packets incoherent (unless the encryption cipher is weak… more on that to come).


A third party could also intercept HTTP packets, tamper with them, and then send them on to be interpreted by the receiving machine.  Again, SSL solves this problem by encrypting the packets, therefore making them impossible to read and unrealistic to modify in a useful way.


Finally, SSL solves the problem of unknowingly communicating with an illegitimate server by issuing authentication certificates that are digitally signed by a trusted third party.  These certificates testify that a website is who they claimed to be.  This is where that extra one-way security largely comes into play, as it is really only servers that need to display their certificates of authenticity for a safer internet experience.


Let’s go a little deeper with these digitally signed “SSL Certificates” as they are a prominent feature of the web today:


It used to be that a third party corporation would affirm that you do in fact own your domain, and that the machine serving web requests at that domain is legitimate.  These trusted corporations were called certificate authorities.  Since these companies were the gatekeepers to HTTPS they charged quite a bit for digitally signing the SSL certificates.  This made HTTPS unpopular, however more recently, through efforts by the Electronic Frontier Foundation, collective efforts by large internet-reliant corporations such as Google and Microsoft, and the appearance of non-profit certificate authorities such as Let’s Encrypt, cost is no longer prohibitive.  In fact enabling HTTPS is often free and I will show you how to use free certificates in future sections of this guide.


Because HTTPS was originally encrypted with SSL, and these certificates were required to use HTTPS, they became generally known as “SSL certificates”.  In reality they are X.509 certificates, being based on the X.509 standard, and are no longer tied exclusively to SSL.


Today, there are 5 certificate authorities that issue almost all of the X.509 certificates on the internet: IdenTrust, DigiCert, Sectigo, GoDaddy, and GlobalSign.  They collectively account for 98.2% of signed certificates as of the publishing date of this guide.


When your web browser wants to check if a website’s certificate is authentic, it will either compare it to a CRL (Certificate Revocation List) or contact an OCSP server (Online Certificate Status Protocol), which will then confirm that certificate’s validity.


Breaking SSL.


The first public version of SSL was SSL 2.0, invented by Netscape in 1995.  This was around the time of the internet dark-age fondly known as the “browser wars”, when Microsoft and Netscape were battling for dominance of the web and refused to cooperate for the good of the technology.


Netscape’s senior engineer, Tahel Elgamal, was largely responsible for the birth of SSL in the mid 90’s.  It was quickly discovered, however, that his version (2.0) could be compromised in multiple ways.  Useful attacks included tricking clients and servers into agreeing to use an easily crack-able encryption cipher, or injecting termination signals without the user knowing if the signals are legitimate.


A Netscape team led by hired-gun and cryptographer Paul Kocher developed SSL 3.0, which was the standard until 2011.  Its block ciphers were found by Google Security Team to be vulnerable to attacks where repeated requests could eventually reveal encrypted data through padding fallbacks.  This exploit was dubbed the POODLE attack.


Enter TLS.


Although most people still associate HTTPS with SSL, the use of SSL for HTTPS has been deprecated in favor of a different protocol: TLS or Transport Layer Security.  TLS was built using SSL as a reference, but is its own distinct protocol.  This means that HTTPS is no longer HTTP-over-SSL, but rather HTTP-over-TLS.  SSL can still be used as a base for HTTPS, however it is considered a legacy protocol.


With a TLS connection, the client and server secretly exchange keys and agree on an encryption cipher to use during the conversation.  This is known as the TLS Handshake and enables encrypted data, just like with SSL.  What makes TLS more desirable than SSL is largely the ability to perform this handshake in a variety of ways.  TLS security parameters can be tailored to suit different situations.


TLS also uses asymmetric encryption as part of the handshake process.  Asymmetric encryption, devised by Rivest, Shamir, and Adleman, solves an issue of symmetric encryption where if the private key is intercepted then the entire conversation can be decrypted.  With asymmetric encryption, two keys are needed: one key to encrypt, and one key to decrypt.  This means that if one key is stolen the damage an attacker can do is severely limited.


Confusingly, even though TLS is called “Transport Layer Security”, it isn’t considered a part of the Transport Layer in either the TCP/IP Model or the OSI Model.  It has aspects of the Transport Layer, the Presentation Layer, and the Application Layer, but is commonly considered an Application Layer protocol.


This is a good time to point out that TLS and SSL only encrypt data in layers above it.  Any data that is added to the packet before TLS can wrap the HTTP message is still readable.  Examples of this include the IP addresses and port numbers which have been added by lower level protocols.  Because these are exposed, limited data about the communication can still be deduced by performing manual DNS lookups.  User fingerprinting could also still take place through diligent comparison of transmission logs.  This is not a weakness of TLS but rather a function of the entire TCP/IP protocol structure.


Breaking TLS.


TLS is the current standard and is considered very secure, however it has gone through several revisions.  All versions are still vulnerable to a variation of the POODLE attack, however any server that has enabled TLS can immunize itself against this exploit by disabling SSL fallbacks and padding checks.  Note that as of 2011, TLS is no longer backwards compatible with SSL.


TLS 1.0 was found to be vulnerable to forced SSL downgrades and cipher-block chaining.  It was thus revised to TLS 1.1 in 2006.  TLS 1.2 (introduced in 2008) is the current standard and improved upon 1.1 by introducing stronger encryption hashes and ciphers.  TLS 1.3 was proposed in 2018 and can be found “in the wild”, however it is not yet widely implemented.  It contains even stronger ciphers.


It is important to know as a developer that any website or web app hosted on a server allowing TLS 1.0 and 1.1 may have its security rating penalized from March 2020 onward (around the time of this article).  This may affect search engine rankings.  I will show you how to disable these two soon-to-be-deprecated versions in an upcoming section.


HSTS: An extra layer of security.


Although HTTPS via TLS is extremely secure, it is still possible for an attacker to force HTTPS to downgrade to HTTP without the user knowing.  This exploit is known as SSL stripping and was discovered by security expert Moxie Marlinspike in 2009.  The solution is to simply not allow HTTP connections, even in the absence of HTTPS.


Rather than implement a whole new protocol, HSTS or HTTP Strict Transport Security was created.  It is simply the ability for a server to tell a web browser “hey, let’s only use HTTPS for a certain amount of time” via a response header.  This means any raw HTTP communications will be ignored.


All modern browsers are capable of using HTTPS so there is little reason not to implement HSTS as well.  There are arguments that simply closing port 80 on your server's firewall is an even more effective countermeasure, however it is best practice to leave port 80 open and to enable HSTS on the server.






The basics: implementing HTTPS.Quotation marks


In the previous section we explained HTTPS and its related protocols in detail, so let’s quickly recap.  Don’t worry, I’ll walk you through setting everything up in-depth in later sections of this guide.  Here are the bare bones of what you need to know before getting started:


HTTP (Hypertext Transfer Protocol) is the default way of communicating with websites, however HTTPS (Hypertext Transfer Protocol Secure) is a much more secure version and should be enabled on every website or web app that you deploy.


You know you’re using HTTPS when the website address begins with “HTTPS://” instead of “HTTP://”.  There is also usually a lock icon beside the address in your browser.  HTTP communications take place over port 80, whereas HTTPS communications take place over port 443.


HTTPS piggybacks on top of either SSL or TLS in order to work.  These are both encryption protocols and make it so the entire communication between the web browser and the web server is private.  SSL is older and has been deprecated in favor of TLS.  You should use the latest versions of TLS (versions 1.2 and 1.3) exclusively for maximum security and better SEO.


In order to enable HTTPS for your website, you will need an X.509 certificate (sometimes called an “SSL certificate”) to be issued to you by a third party.  There are paid and free options for this which we will go over.


For added security, you should also make sure that the server that is hosting your web app has HSTS (HTTP Strict Transport Security) enabled.


Using HTTPS also allows the use of HTTP/2, which can drastically speed up your website.  Enabling HTTP/2 is totally optional and not required for the use of HTTPS, however I recommend it and will walk you through setting that up in a future article.  You should complete this guide first!


Now that you have an overview of the HTTPS landscape, let’s get started!






First things first: scrub your code.Quotation marks


NOTE: If you are a web designer or a casual person setting up a website and did not code it yourself (or if you used a creation platform like WordPress, etc.), then you can skip this section!


After you have decided to use HTTPS (and I hope you have if you want improved security and search engine rankings), the very first thing that you need to do is go through your web app code and change any URLs or references to HTTP resources.  All HTTP communication within your website must take place over HTTPS, including connections to third-party content.  If not, the best case scenario is that HTTPS is only partially functioning and your site is still vulnerable; at worst, your site may break entirely when you enable HTTPS on the server.  Don’t be alarmed if you created your site using a third party site builder: these platforms do not require any tinkering.  If you have used a framework (React, etc.) or vanilla code then you need to be diligent about HTTP references.


Common culprits are links to third party fonts, libraries, and API connections.  Fixing this may be as simple as changing “HTTP://” to “HTTPS://” in your URLs, however if the third party server does not serve via HTTPS then you should strongly consider dropping that resource in favor of one that does.  Keep in mind that it is only the production code that needs to change, so be aware of possible situations where modifying your source code links could break the site on a non-HTTPS test server.






Choose a certification method.Quotation marks


Whether you call it an X.509 certificate, an SSL certificate, or a digitally signed certificate, it doesn’t matter; you will need one.  It is required to enable HTTPS.  This certificate is how your website authenticates itself to users as “the real website”, and not a fake.  Let’s take a look at our options:


  1. Option 1) Pay a third party certificate authority to issue you a certificate.
  2. Option 2) Issue yourself a self-signed certificate for free.
  3. Option 3) Have the non-profit Let’s Encrypt issue you a free certificate using certbot.

NOTE: No matter what option you choose, you must have a web server up and running at a domain that you own.


If you do not have superuser access to your web server, or you don’t want to deal with the potential headaches of using a command line interface, then I suggest that you go for the first option.  You can easily have any of the big certificate authorities (such as GoDaddy) issue your site one for a price.  If you go with option 1 then you can also skip the rest of this guide, as any big hosting company will have a user-friendly (or automatic) paid way to accomplish the necessary HTTPS tasks.  The path to doing so will be different depending on the company.  For the rest of you who have set up their own servers on a VPS, at home, or who simply want to save some cash, that leaves options 2 and 3…


Option 2, obtaining a self-signed certificate, is possible, however I do not recommend it.  Because your certificate was not signed by a trusted third party, web browsers will not recognize it as legit, however communications with the website will still be secure and private.  This was useful before option 3 was possible, but there is absolutely no advantage to self-signing as of the publishing date of this guide.  For that reason I am not including instructions on creating a self-signed X.509 certificate.


The best free option (if you have some patience typing in commands) is option 3.  I will show you how to set up a 100% legitimate certificate through Let’s Encrypt using the certbot program on your web server's machine!






Open port 443.Quotation marks


From this point on you will need port 443 open on any firewalls that your web server sits behind.  HTTPS communications take place over port 443, not port 80 (which will usually be the only open port on a web server firewall by default).  Even if you know that port 443 is open, you should take the time to confirm it now in order to avoid any headaches later.  It is best practice to leave port 80 open in addition to port 443.


NOTE: Certbot will automatically adjust your web server settings to begin listening on port 443.  That will be covered in the next section.  In this section we are only concerned with allowing port 443 data to pass through the firewall.


If you’re using “firewalld”, you can open port 443 by running these two commands:


$ sudo firewall-cmd --add-service=https $ sudo firewall-cmd --runtime-to-permanent

If you’re using “ufw” you can run...


$ sudo ufw allow https

You should be good to go!






Let’s Encrypt: obtain a free certificate.Quotation marks


Choose your server technology from the list below to jump to the appropriate subsection.  When you have completed the steps and obtained your certificate, you can skip to the next section: “Disable legacy protocols”.  If you run into trouble you can refer to certbot's installation instructions.


Choose a server:

Nginx


NOTE: This walkthrough assumes a fresh and updated modern version of either Ubuntu, Debian, or CentOS.  Modify these steps appropriately for other linux versions and skip any steps that don’t apply to your installation.


First, add the certbot repository. If you’re using Debian, the stock repositories are fine, just make sure your package list is updated.


Ubuntu:

$ sudo add-apt-repository ppa:certbot/certbot

Then press ENTER to accept.


CentOS:

$ sudo yum install epel-release

Next, install certbot.


Ubuntu:

$ sudo apt install python-certbot-nginx

Debian:

$ sudo apt-get install certbot python-certbot-nginx

CentOS:

$ sudo yum install certbot-nginx

Certbot will work at this point, but you need to make sure that your Nginx server block file contains the correct directive for certbot to do its job automatically.


If you have a server block set up for your site in Nginx, open the server block file with a text editor (eg. nano or vi)...


$ sudo nano /etc/nginx/sites-available/yourserverblock

...or if you do not have your own server block, open the default server block file.


$ sudo nano /etc/nginx/sites-available/default

Find the line that begins with “server_name” and make sure it looks like this:


server_name yourwebsite.com www.yourwebsite.com;

If not, edit it to fit your domain and save/exit your text editor.  In nano this is CTRL-X.  If you modified any of your server block files, check the syntax for errors with:


$ sudo nginx -t

...and then reload Nginx with:


$ sudo systemctl reload nginx

Next you’ll want to run certbot (Make sure your web server is serving from both yourwebsite.com AND www.yourwebsite.com before you run certbot!).


$ sudo certbot --nginx -d yourwebsite.com -d www.yourwebsite.com

You will be asked to enter an email address for emergency contact in case of renewal failure.  You will also be asked to agree to the terms of service.  Certbot will contact the Let’s Encrypt certificate authority and verify that you are the domain owner.


When asked if you want to redirect all traffic to HTTPS, choose option 2, “redirect”.


When certbot has finished successfully, you will get a congratulations message.  Restart Nginx with:


$ sudo systemctl reload nginx

Finally, test certbot’s auto renewal process by running:


$ sudo certbot renew --dry-run

If everything is successful, certbot will automatically renew your certificate whenever it is close to expiring.  If it can’t then it will contact you at the email address that you provided.


Well done!  You can skip past the instructions for Apache and move to the next section: Disable legacy protocols.


Apache


NOTE: This walkthrough assumes a fresh and updated modern version of either Ubuntu, Debian, or CentOS.  Modify these steps appropriately for other linux versions and skip any steps that don’t apply to your installation.


ALSO BE AWARE!: Your build of Apache must include mod_ssl, mod_socache_shmcb, mod_rewrite, and mod_headers in order for many of the settings in this guide to work.  Please make sure that is the case before proceeding.


First, add the certbot repository.  If you’re using Debian, the stock repositories are fine, just make sure your package list is updated.


Ubuntu:

$ sudo add-apt-repository ppa:certbot/certbot

Then press ENTER to accept.


CentOS:

$ sudo yum install epel-release

Next, install certbot.


Ubuntu:

$ sudo apt install python-certbot-apache

Debian:

$ sudo apt-get install certbot python-certbot-apache

CentOS:

$ sudo yum install certbot python2-certbot-apache mod_ssl

Accept the GPG key if asked.


Certbot will work at this point but you need to make sure that your Apache virtual host file contains the correct directive in order for certbot to do its job automatically.


If you have a virtual host set up for your site in Apache, open the virtual host file with a text editor (eg. nano or vi):


$ sudo nano /etc/apache2/sites-available/yourvirtualhost.conf

Find the line that begins with “ServerName” and make sure it looks like this:


ServerName yourwebsite.com;

If not, edit it to fit your domain and save/exit your text editor.  In nano this is CTRL-X.  If you modified any of your virtual host files, check the syntax for errors with:


$ sudo apache2ctl configtest

...and then reload Apache with:


$ sudo systemctl reload apache2

Next you’ll want to run certbot (Make sure your web server is serving from both yourwebsite.com AND www.yourwebsite.com before you run certbot!).


$ sudo certbot --apache -d yourwebsite.com -d www.yourwebsite.com

You will be asked to enter an email address for emergency contact in case of renewal failure.  You will also be asked to agree to the terms of service.  Certbot will contact the Let’s Encrypt certificate authority and verify that you are the domain owner.


When asked if you want to redirect all traffic to HTTPS, choose option 2, “redirect”.


When certbot has finished successfully, you will get a congratulations message.  Restart Apache with:


$ sudo systemctl reload apache2

Finally, test certbot’s auto renewal process by running:


$ sudo certbot renew --dry-run

If everything is successful, certbot will automatically renew your certificate whenever it is close to expiring.  If it can’t then it will contact you at the email address that you provided.


Well done!






Disable legacy protocols.Quotation marks


We need to make sure that older versions of TLS cannot be used in a connection in order to secure your HTTPS installation as tightly as possible.  Versions 1.0 and 1.1 are being deprecated during the time of this writing (March 2020), therefore we need to make sure that they are not used past this date.


Choose a server:

Nginx


First open the Nginx configuration file with a text editor (eg. nano or vi):


$ sudo nano /etc/nginx/nginx.conf

Locate the line that looks like this...


ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

...and erase the protocols that we don’t want to use.  Also add TLSv1.3 to the end in order to provide support for that if it is not already there.  The same line should now look like this:


ssl_protocols TLSv1.2 TLSv1.3;

Exit/save your text editor.  Check your config file for syntax errors with:


$ sudo nginx -t

...and then reload Nginx with:


$ sudo systemctl reload nginx

That’s it.  You can skip past the instructions for Apache and move to the next section: Remove weak ciphers.


Apache


First open the Nginx configuration file with a text editor (eg. nano or vi):


$ sudo nano /etc/httpd/conf.d/ssl.conf

Locate the line that looks like this...


SSLProtocol all -SSLv3

...and modify it so that only modern versions of TLS are used.  The same line should now look like this:


SSLProtocol TLSv1.2 TLSv1.3

Exit/save your text editor.  Check your config file for syntax errors with:


$ sudo apache2ctl configtest

...and then reload Apache with:


$ sudo systemctl reload apache2

That’s it.






Remove weak ciphers.Quotation marks


Your server communications will be extremely secure now, however we can still go a bit further!  As time passes certain encryption ciphers fall out of favor.  Although they are still useful, dropping them will raise the security level of your connections.  We will remove these less-secure ciphers in this section.


Before proceeding you should be aware that TLS 1.3 does not contain any weak or blacklisted ciphers.  You can choose to restrict connections to 1.3-only (simply follow the instructions in the previous section and leave out TLSv1.2 in the configuration file), and then skip this section entirely.  The disadvantage to that approach is that you sacrifice some backwards compatibility with older browser versions.  The steps in this section ensure both a strong cipher suite, as well as compatibility.


Choose a server:

Nginx


When you ran certbot to get your digitally signed certificate, it created a file holding all of the ciphers that an HTTPS connection can potentially use called options-ssl-nginx.conf.  Because this file contains weak ciphers, and because modifying it would break certbot updates, let’s define our own ciphers and tell Nginx to use those instead.


First let’s make sure that Nginx is using our cipher preferences instead of the client’s.  Open your Nginx configuration file once more…


$ sudo nano /etc/nginx/nginx.conf

...and make sure this line exists and that the value is set to “on”:


NOTE: If you have removed the use of TLS 1.2 it is preferred to leave this setting “off”.

ssl_prefer_server_ciphers on;

Exit your editor and save the file if you made any changes.


If you have a server block set up for your site in Nginx, open the server block file...


$ sudo nano /etc/nginx/sites-available/yourserverblock

...or if you don't have your own server block, open the default server block file.


$ sudo nano /etc/nginx/sites-available/default

Find the line that contains a reference to the weak cipher file options-ssl-nginx.conf and comment it out by inserting a # character at the beginning.  The result should look something like this:


# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

Insert this line below that line to define new ciphers:


ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

Exit your editor and save the file.


Now open this configuration file with your text editor...


$ sudo nano /etc/nginx/snippets/ssl-params.conf

...and change the line that begins with “ssl_ciphers” to:


ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

Once again, exit your text editor and save the file.  Check your config for syntax errors with:


$ sudo nginx -t

...and then reload Nginx with:


$ sudo systemctl reload nginx

Nice one.  You can skip past the instructions for Apache and move to the next section: Enable HSTS.


Apache


In order to define a list of strong ciphers for Apache to use, we need to modify the default SSL configuration file again.  Open it with a text editor:


$ sudo nano /etc/httpd/conf.d/ssl.conf

Find the line that you edited in the previous section:


SSLProtocol TLSv1.2 TLSv1.3

Place the following text in a single line below it:


SSLCipherSuite EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5

If a similar line already exists, erase it and replace it with the new text.


Ensure that our strong cipher list is followed by inserting this text on the next line:


NOTE: If you have removed the use of TLS 1.2 it is preferred to leave the this setting “off”.

SSLHonorCipherOrder on

Exit/save your text editor, then check for syntax errors with:


$ sudo apache2ctl configtest

...and then reload Apache with:


$ sudo systemctl reload apache2

Nice one.






Enable HSTS.Quotation marks


HTTP Strict Transport Security (HSTS) disables communication over raw HTTP and forces clients to use HTTPS instead.  This is necessary to prevent attacks which force a connection to fall back to HTTP, which can then be exploited.


Although this could limit compatibility with much older browsers, practically speaking: all browsers are HTTPS-compatible as of the writing of this article so this is not really a concern.  You should enable HSTS for all of your web apps.


Disabling raw HTTP communications can also be achieved by simply closing port 80, however it is better practice to leave it open and to enable HSTS.  HSTS also prevents HTTP redirects and can save time serving web data.


Choose a server:

Nginx


Open your Nginx configuration file with:


$ sudo nano /etc/nginx/nginx.conf

Look for the line:


include /etc/nginx/sites-enabled/*;

NOTE: It is in the section # Virtual Host Configs within the “http” block.


Below that line, add this single line:


add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

Exit/save your text editor and check for syntax errors with:


$ sudo nginx -t

...and then reload Nginx with:


$ sudo systemctl reload nginx

You now have HSTS enabled!  You can skip past the instructions for Apache and move to the next section: Finishing touches.


Apache


If you have a virtual host set up for your site, open the virtual host file with a text editor:


$ sudo nano /etc/apache2/sites-available/yourvirtualhost.conf

Add this line as the last line within the <VirtualHost *:443>...</VirtualHost> section:


Header always set Strict-Transport-Security "max-age=63072000"

Exit/save your text editor and check for syntax errors with:


$ sudo apache2ctl configtest

...and then reload Apache with:


$ sudo systemctl reload apache2

You now have HSTS enabled!






Finishing touches.Quotation marks


Congratulations, your server connections are now locked down tight… and yet, there are still a few more things we can do to take HTTPS security to the next level.


Black hats can gain access to a client’s authentication web cookies using TLS compression oracle attacks, however your server can protect clients by disabling SSL compression.  An attacker may also be able to compromise a server’s secrecy given a long time between restarts, however we can prevent this as well by disabling SSL session tickets.  We also want to enable OCSP stapling in order to more efficiently check the validity of digitally signed certificates.


We'll make all of these improvements in this section.


Choose a server:

Nginx


NOTE: Modern versions of Nginx will have SSL compression disabled by default, so you do not need to be worried about that, however it is good to go through the config files that we will open in this walk-through just to check that there are NO references to SSL compression.  If there are, it means that you have an outdated version and you should strongly consider upgrading.  If that is not desirable, you can edit that file so that the SSL compression value is “off”.


Open your Nginx configuration file with:


$ sudo nano /etc/nginx/nginx.conf

Look for the line you added in the previous section:


add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

Below it, add these two lines:


ssl_stapling on; ssl_stapling_verify on;

Exit/save your text editor and check for syntax errors with:


$ sudo nginx -t

If you have a server block set up for your site, open the server block file...


$ sudo nano /etc/nginx/sites-available/yourserverblock

...or if you don’t, open the default server block file.


$ sudo nano /etc/nginx/sites-available/default

Find the line that begins with ssl_certificate_key and add this line below it:


ssl_session_tickets off;

Exit/save your text editor and check for syntax errors again:


$ sudo nginx -t

...and then reload Nginx with:


$ sudo systemctl reload nginx

That's all there is to it.  You can skip past the instructions for Apache and move to the next section: Next steps.


Apache


Open your configuration file with a text editor:


$ sudo nano /etc/httpd/conf.d/ssl.conf

...and find this line:


SSLHonorCipherOrder on

Below it, add these two lines:


SSLSessionTickets off SSLCompression off

Add an empty line for separation/readability, and then add these two lines:


SSLUseStapling On SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

Exit/save your text editor and check for syntax errors with:


$ sudo apache2ctl configtest

...and then reload Apache with:


$ sudo systemctl reload apache2

That's all there is to it.






Next steps.Quotation marks


You have graduated from the school of HTTPS and are now armed with information that will serve you in 99% of situations that a web developer will encounter.  Not only that, your website is now more secure than the vast majority out there in the wild.  If you want to prove it to yourself (and you should), run your site through the SSL Labs test and you will receive an A+ rating.  Very well done.  You are now part of the solution.


One more great thing about working through this guide is that you now have a 100% HTTP/2 compliant server.  Enabling HTTP/2 requires a strong HTTPS setup and yours is ready.  We won’t get into the benefits or how to set up HTTP/2 in this guide but stay tuned for an upcoming article on the subject.


Before we go, one final tip to keep in mind every time you use HTTPS: it is best to serve the entire domain with HTTPS rather than specfic pages (order forms for instance).  This ensures that sitewide cookies are secure and no parts of the communication are exposed.


Give yourself a hand for making it through this entire guide: you earned it!  As always, I enjoyed making it for you and I hope that you stick around for more.






Bonus: configuration cheat sheet.Quotation marks


If at any time you get stuck with any of the configuration settings, an extremely useful tool is Mozilla’s SSL Configuration Generator: ssl-config.mozilla.org. This can be used as a reference to play around with useful HTTPS settings for just about any server installation.


Happy coding. _Isometric cube outline


{ References: }

Like what you read? Consider showing your love:

BTC -

Click to copy address

100% of your donations go directly to this author!

Any amount shows the author you appreciate their work.