Difference between revisions of "Secure Sockets Layer"

From Organic Design wiki
(Free SSL certificates: Godaddy)
(Change source-code blocks to standard format)
Line 8: Line 8:
  
 
First we need to create a private key. Note that this process will require a pass-phrase for the key - don't worry, we'll remove it later to make things easier,
 
First we need to create a private key. Note that this process will require a pass-phrase for the key - don't worry, we'll remove it later to make things easier,
{{code|<pre>openssl genrsa -des3 -out ssl.key 2048</pre>}}
+
<source>
 +
openssl genrsa -des3 -out ssl.key 2048
 +
</source>
  
  
 
Now we need to create a CSR (Certificate Signing Request):
 
Now we need to create a CSR (Certificate Signing Request):
{{code|<pre>openssl req -new -key ssl.key -out ssl.csr</pre>}}
+
<source>
 +
openssl req -new -key ssl.key -out ssl.csr
 +
</source>
  
  
 
Now we need to remove the pass-phrase otherwise it'll prevent the web-server from restarting without it being entered (you'll need to enter the pass-phrase to remove it though),
 
Now we need to remove the pass-phrase otherwise it'll prevent the web-server from restarting without it being entered (you'll need to enter the pass-phrase to remove it though),
{{code|<pre>cp ssl.key ssl-pass.key
+
<source>
openssl rsa -in ssl-pass.key -out ssl.key</pre>}}
+
cp ssl.key ssl-pass.key
 +
openssl rsa -in ssl-pass.key -out ssl.key
 +
</source>
  
  
 
Now we can generate the actual certificate:
 
Now we can generate the actual certificate:
{{code|<pre>openssl x509 -req -days 3650 -in ssl.csr -signkey ssl.key -out ssl.crt</pre>}}
+
<source>
 +
openssl x509 -req -days 3650 -in ssl.csr -signkey ssl.key -out ssl.crt
 +
</source>
  
  
 
Each secure domain will require virtual-host definition in a separate file in the ''/var/www/ssl'' directory and having the same file name as the domain name it applies to, and can then be referred to by the relevant host container in the web server configuration, for example for Nginx:
 
Each secure domain will require virtual-host definition in a separate file in the ''/var/www/ssl'' directory and having the same file name as the domain name it applies to, and can then be referred to by the relevant host container in the web server configuration, for example for Nginx:
{{code|<pre>
+
<source>
 
ssl on;
 
ssl on;
 
ssl_certificate /var/www/ssl/foo.crt;
 
ssl_certificate /var/www/ssl/foo.crt;
 
ssl_certificate_key /var/www/ssl/foo.key;
 
ssl_certificate_key /var/www/ssl/foo.key;
</pre>}}
+
</source>
  
  
 
If running an older version of Nginx (pre 1.1), it's a good idea to add some extra entropy to the key for use by Diffie Hellman ciphers:
 
If running an older version of Nginx (pre 1.1), it's a good idea to add some extra entropy to the key for use by Diffie Hellman ciphers:
{{code|<pre>
+
<source>
 
openssl dhparam -rand - 2048 >> /var/www/ssl/foo.key
 
openssl dhparam -rand - 2048 >> /var/www/ssl/foo.key
</pre>}}
+
</source>
  
  
 
Check the config before restarting with '''apachectl -t''' or '''nginx -t''', and if everything is fine, start or restart the web server from ''/etc/init.d'' as usual. After starting, follow the web server error log as you start the server and as you make SSL requests and see if problems show up.
 
Check the config before restarting with '''apachectl -t''' or '''nginx -t''', and if everything is fine, start or restart the web server from ''/etc/init.d'' as usual. After starting, follow the web server error log as you start the server and as you make SSL requests and see if problems show up.
{{code|<pre>
+
<source>
 
tail -f /var/log/[apache2|nginx]/error.log
 
tail -f /var/log/[apache2|nginx]/error.log
</pre>}}
+
</source>
  
  
Line 53: Line 61:
  
 
You'll need at least OpenSSL version 1.0 and Apache version 2.3.3 (or [[Nginx]] which has supported it for quite some time now). First check that your version of OpenSSL supports [[w:Elliptic curve cryptography|elliptic curve Diffie-Hellman]] protocols.
 
You'll need at least OpenSSL version 1.0 and Apache version 2.3.3 (or [[Nginx]] which has supported it for quite some time now). First check that your version of OpenSSL supports [[w:Elliptic curve cryptography|elliptic curve Diffie-Hellman]] protocols.
{{code|<bash>openssl ciphers ECDH</bash>}}
+
<source lang="bash">
 +
openssl ciphers ECDH
 +
</source>
 
If you have support for it, you'll get a long list of output like the following example, or if not you'll get an "Error in cipher list: result.
 
If you have support for it, you'll get a long list of output like the following example, or if not you'll get an "Error in cipher list: result.
{{code|<pre>
+
<source>
 
ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-
 
ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-
 
SHA:AECDH-AES256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-
 
SHA:AECDH-AES256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-
Line 63: Line 73:
 
SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AECDH-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDHE-RSA-NULL-SHA:ECDHE-ECDSA-NULL-SHA:AECDH-NULL-SHA:ECDH-
 
SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AECDH-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDHE-RSA-NULL-SHA:ECDHE-ECDSA-NULL-SHA:AECDH-NULL-SHA:ECDH-
 
RSA-NULL-SHA:ECDH-ECDSA-NULL-SHA
 
RSA-NULL-SHA:ECDH-ECDSA-NULL-SHA
</pre>}}
+
</source>
  
  
Line 71: Line 81:
  
 
The cipher suite used to obtain this result is the set recommended by SSLlabs and is as follows. It's put in the '''SSLCipherSuite''' setting in ''/etc/apache2/mods-available/ssl.conf'', or in the '''ssl_ciphers''' value in the site's SSL server container of the Nginx configuration. Our Nginx configuration is as follows:
 
The cipher suite used to obtain this result is the set recommended by SSLlabs and is as follows. It's put in the '''SSLCipherSuite''' setting in ''/etc/apache2/mods-available/ssl.conf'', or in the '''ssl_ciphers''' value in the site's SSL server container of the Nginx configuration. Our Nginx configuration is as follows:
{{code|<pre>
+
<source>
 
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
 
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
 
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+RC4:EDH+aRSA:EECDH:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
 
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+RC4:EDH+aRSA:EECDH:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
 
ssl_prefer_server_ciphers on;
 
ssl_prefer_server_ciphers on;
</pre>}}
+
</source>
  
  
 
It's a good idea to also change the default logging format so that you can see what cipher clients are connecting with - especially to ensure that your own browser is using a ''ECDHE'' cipher.
 
It's a good idea to also change the default logging format so that you can see what cipher clients are connecting with - especially to ensure that your own browser is using a ''ECDHE'' cipher.
{{code|<pre>
+
<source>
 
log_format organicdesign '$remote_addr - [$time_local] '
 
log_format organicdesign '$remote_addr - [$time_local] '
 
                         '"$request" $status $body_bytes_sent '
 
                         '"$request" $status $body_bytes_sent '
 
                         '"$http_referer" "$http_user_agent" $ssl_cipher';
 
                         '"$http_referer" "$http_user_agent" $ssl_cipher';
 
access_log /var/log/nginx/access.log organicdesign;
 
access_log /var/log/nginx/access.log organicdesign;
</pre>}}
+
</source>
  
 
== SSLlabs perfect result, but not well supported by browsers ==
 
== SSLlabs perfect result, but not well supported by browsers ==
 
[[File:SSLlabs all good.jpg|550px|right]]I was able to get the result to the right, by using the following settings which is the SSLlabs recommended cipher set, but with RC4 removed and only TLSv1.2 allowed. As of 2015 this is supported by Firefox, so we're using this selection on Organic Design now.
 
[[File:SSLlabs all good.jpg|550px|right]]I was able to get the result to the right, by using the following settings which is the SSLlabs recommended cipher set, but with RC4 removed and only TLSv1.2 allowed. As of 2015 this is supported by Firefox, so we're using this selection on Organic Design now.
<div style="width:515px">{{code|<pre>
+
<div style="width:515px"><source>
 
ssl_protocols TLSv1.2;
 
ssl_protocols TLSv1.2;
 
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:
 
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:
Line 94: Line 104:
 
             !RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
 
             !RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
 
ssl_prefer_server_ciphers on;
 
ssl_prefer_server_ciphers on;
</pre>}}</div>
+
</source></div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
  

Revision as of 18:11, 22 May 2015

Procedure.svg Secure Sockets Layer
Organic Design procedure

First we need to ensure that we have a valid SSL certificate for each domain that will be using SSL connections. First generate a self signed certificate for each domain. Remember that this will raise the "untrusted secure site" error in the client browser, for sites that require a proper commercial certificate, use the generate a certificate request for a commercial Certificate Authority procedure instead.

Our convention is to keep all the certificates in /var/www/ssl, so first change the current directory to that and create the certificate with the following command format. Ensure the common name (cn) is entered as a wildcard such as *.foo.com so that the certificate applies to all the sub-domains such as www.foo.com or webmail.foo.com etc. This certificate format will work for both Apache and Nginx.

First we need to create a private key. Note that this process will require a pass-phrase for the key - don't worry, we'll remove it later to make things easier,

openssl genrsa -des3 -out ssl.key 2048


Now we need to create a CSR (Certificate Signing Request):

openssl req -new -key ssl.key -out ssl.csr


Now we need to remove the pass-phrase otherwise it'll prevent the web-server from restarting without it being entered (you'll need to enter the pass-phrase to remove it though),

cp ssl.key ssl-pass.key
openssl rsa -in ssl-pass.key -out ssl.key


Now we can generate the actual certificate:

openssl x509 -req -days 3650 -in ssl.csr -signkey ssl.key -out ssl.crt


Each secure domain will require virtual-host definition in a separate file in the /var/www/ssl directory and having the same file name as the domain name it applies to, and can then be referred to by the relevant host container in the web server configuration, for example for Nginx:

ssl on;
ssl_certificate /var/www/ssl/foo.crt;
ssl_certificate_key /var/www/ssl/foo.key;


If running an older version of Nginx (pre 1.1), it's a good idea to add some extra entropy to the key for use by Diffie Hellman ciphers:

openssl dhparam -rand - 2048 >> /var/www/ssl/foo.key


Check the config before restarting with apachectl -t or nginx -t, and if everything is fine, start or restart the web server from /etc/init.d as usual. After starting, follow the web server error log as you start the server and as you make SSL requests and see if problems show up.

tail -f /var/log/[apache2|nginx]/error.log


Other SSL certificates

We also run a number of other SSL certificates in the system which may need rebuilding from time to time. See the appropriate procedure for each one for the details on building the certificates.

Selecting a good set of ciphers

With revelations about mass surveillance in the news everywhere, such as this article, an obscure feature of SSL/TLS called perfect forward secrecy has suddenly become a very important feature to enable.

You'll need at least OpenSSL version 1.0 and Apache version 2.3.3 (or Nginx which has supported it for quite some time now). First check that your version of OpenSSL supports elliptic curve Diffie-Hellman protocols.

openssl ciphers ECDH

If you have support for it, you'll get a long list of output like the following example, or if not you'll get an "Error in cipher list: result.

ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-
SHA:AECDH-AES256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-
ECDSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AECDH-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES128-
GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:AECDH-AES128-
SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-
SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AECDH-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDHE-RSA-NULL-SHA:ECDHE-ECDSA-NULL-SHA:AECDH-NULL-SHA:ECDH-
RSA-NULL-SHA:ECDH-ECDSA-NULL-SHA


You can then set the protocols in your cypher suite to an optimal list and prioritisation. You can use Qualys SSL labs test. I'm not sure if it's possible to get a combination of ciphers that satisfy everything. The best I've come up with is a value that allows perfect forward secrecy and mitigates the BEAST attack, but it allows RC4 which vulnerabilities have been found in, but haven't yet been exploited in any way. Here's a screenshot of the best result I've managed to obtain (and the best I've seen from the top results in their chart).

SSL Labs result.jpg

The cipher suite used to obtain this result is the set recommended by SSLlabs and is as follows. It's put in the SSLCipherSuite setting in /etc/apache2/mods-available/ssl.conf, or in the ssl_ciphers value in the site's SSL server container of the Nginx configuration. Our Nginx configuration is as follows:

ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+RC4:EDH+aRSA:EECDH:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
ssl_prefer_server_ciphers on;


It's a good idea to also change the default logging format so that you can see what cipher clients are connecting with - especially to ensure that your own browser is using a ECDHE cipher.

log_format organicdesign '$remote_addr - [$time_local] '
                         '"$request" $status $body_bytes_sent '
                         '"$http_referer" "$http_user_agent" $ssl_cipher';
access_log /var/log/nginx/access.log organicdesign;

SSLlabs perfect result, but not well supported by browsers

SSLlabs all good.jpg

I was able to get the result to the right, by using the following settings which is the SSLlabs recommended cipher set, but with RC4 removed and only TLSv1.2 allowed. As of 2015 this is supported by Firefox, so we're using this selection on Organic Design now.

ssl_protocols TLSv1.2;
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:
            EECDH+ECDSA+SHA256:EECDH+aRSA:EDH+aRSA:EECDH:
            !RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
ssl_prefer_server_ciphers on;

Critical bug named "Heartbleed" found in OpenSSL

On April 7, 2014, it was announced that all versions of OpenSSL in the 1.0.1 series up to and including 1.0.1f had a severe memory handling error in their implementation of the TLS Heartbeat Extension. This error could be used to reveal up to 64 kilobytes of the application's memory. The vulnerability had existed since December 31, 2011, and had been adopted to widespread use since the release of the OpenSSL version 1.0.1 on March 14, 2012. By reading the memory of the SSL server, attackers could access sensitive data, compromising the security of the server and its users. Potentially vulnerable secure data include the server's private master key, which enables attackers to break the encryption of the server's earlier eavesdropped communications and impersonate as the server. The vulnerability might also reveal unencrypted parts of other user's sensitive requests and responses, including session cookies and passwords, which might allow attackers to hijack the identity of another user of the service. At its disclosure, some 17% or half a million of the Internet's secure web servers certified by trusted authorities were believed to have been vulnerable to the attack. [more...].

The warning about the bug in OpenSSL coincided with the release of version 1.0.1g of the open-source program, which is the default cryptographic library used in the Apache and nginx Web server applications, as well as a wide variety of operating systems and e-mail and instant-messaging clients. The bug, which has resided in production versions of OpenSSL for more than two years, could make it possible for people to recover the private encryption key at the heart of the digital certificates used to authenticate Internet servers and to encrypt data traveling between them and end users. Attacks leave no traces in server logs, so there's no way of knowing if the bug has been actively exploited. Still, the risk is extraordinary, given the ability to disclose keys, passwords, and other credentials that could be used in future compromises. [more...] [Debian patch info...]

Critical vulnerability named "Poodle" renders SSL v3.0 useless

After more than a week of persistent rumours, yesterday (Oct 14) we finally learned about the new SSL 3 vulnerability everyone was afraid of. The so-called POODLE attack is a problem in the CBC encryption scheme as implemented in the SSL 3 protocol. (Other protocols are not vulnerable because this area had been strengthened in TLS 1.0.) Conceptually, the vulnerability is very similar to the 2011 BEAST exploit. In order to successfully exploit POODLE the attacker must be able to inject malicious JavaScript into the victim's browser and also be able to observe and manipulate encrypted network traffic on the wire. As far as MITM attacks go, this one is complicated, but easier to execute than BEAST because it doesn't require any special browser plugins. If you care to learn the details, you can find them in the short paper or in Adam Langley's blog post.

Free SSL certificates

Free certificates are finally starting to become a reality with companies like StartSSL and GoDaddy offering 1-year certificates for non-commercial use. SSL shopper have an article here as well about the various options which may be more up to date and more informative than this one.

StartSSL is pretty picky about what non-commercial means though, for example Organic Design was declined because it accepts donations! So really it's just a teaser to get you in the door and then they start convincing you to pay for their "class 2" certificates, which although very reasonably priced at $25 per year, are not free.

GoDaddy's free offering is strictly for open source projects which must provide useful code on a valid project management site such as SorceForge or Github, and must license all their code under a valid free license such as GPL or MIT. Organic Design qualifies for this and I went through the process to set up a certificate for this site which was all reasonably straight forward. It does look like it's only free for the first year though so may also not really count as a free SSL provider, I'll update this after a year when I know for sure. I was sure to disable "auto-renew" in the certificate settings in case it automatically charges for the next year!

CaCert is a very interesting project which uses a web of trust based on physical meetings as it's means on providing identity validation backing their certificates. But unfortunately their certs are not supported by any major browsers, so at the end of the day there's no real benefit over a self-signed certificate.

The real game changer in the free certs arena though is LetsEncrypt which is hopefully launching very soon (mid 2015). Their aim is to replace the whole complicated certificate requesting and signing process with a simple apt-get installation on the server, and their system is apparently supported by all major browsers!

See also