Table of Contents
Introduction
Server Name Indication (SNI) is a feature of the TLS protocol which enables setting up multiple SSL certficates on a single IP address.
Lighttpd must already be setup and running. Read these articles to get it up.
Setup
Two domains will be used for this tutorial. Both will use self-signed SSL certificates.
__Domain 1:__ example.com
__Common Name:__ *.example.com
__Domain 2:__ www.progressiverobot.com
__Common Name:__ www.progressiverobot.com
SSL setup needs a default certificate just like a default virtual host. We will use the first domain's certificate for this.
Create private keys
Create a directory inside the /etc/lighttpd to place the keys and certificates.
mkdir /etc/lighttpd/certs
Create a private key and enter a passphrase. The second command is for removing the passphrase.
cd /etc/lighttpd/certs
openssl genrsa -des3 -out example.com.key 2048
openssl rsa -in example.com.key -out example.com.key
Do the same for the second domain too.
openssl genrsa -des3 -out www.progressiverobot.com.key 2048
openssl rsa -in www.progressiverobot.com.key -out www.progressiverobot.com.key
If the passphrase isn't removed, Lighttpd will prompt for it each time it starts or restarts.
Create a Certificate Signing Request
Create a CSR for both the domain names.
cd /etc/lighttpd/certs
openssl req -new -key www.progressiverobot.com.key -out www.progressiverobot.com.csr
openssl req -new -key example.com.key -out example.com.csr
Fill in the details and enter a dot . if you wish to leave a field blank.
—–
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:NYC
Organization Name (eg, company) [Internet Widgits Pty Ltd]:the cloud provider Inc
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:www.progressiverobot.com
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
When filling the __Common Name__ field for example.com make sure to enter *.example.com.
—–
Country Name (2 letter code) [AU]:IN
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Chennai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:*.example.com
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
We have entered a different country and city for this CSR so that it is easy to distinguish which certificate is presented.
Sign your SSL Certificates
Here again, we will set a different validity length (-days argument) for both the certificates so that we can easily differentiate between them.
cd /etc/lighttpd/certs
openssl x509 -req -days 100 -in example.com.csr -signkey example.com.key -out example.com.crt
openssl x509 -req -days 200 -in www.progressiverobot.com.csr -signkey www.progressiverobot.com.key -out www.progressiverobot.com.crt
Create a .pem file from the certificates and their private keys.
cat example.com.{key,crt}> example.com.pem
cat www.progressiverobot.com.{key,crt}> www.progressiverobot.com.pem
Secure the files in this directory by only allowing the root user to read these files.
chmod -R 400 /etc/lighttpd/certs/
The Lighttpd daemon starts with root privileges before coming down to _www-data_ so this should not be a problem.
Configure Lighttpd for SSL
Edit the /etc/lighttpd/lighttpd.conf file and add the following lines at the end.
$SERVER["socket"] == "0.0.0.0:443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/lighttpd/certs/example.com.pem"
$HTTP["host"] =~ "(^|www.)www.progressiverobot.com" {
ssl.pemfile = "/etc/lighttpd/certs/www.progressiverobot.com.pem"
}
}
Since the ceritifcate of example.com is the default one, we do not place it inside a host condition.
Restart the Lighttpd daemon.
service lighttpd force-reload
The service should successfully restart if you have not made errors in the certificate paths or when creating the .pem file.
Testing HTTPS
The easy way of testing this without editing the __hosts__ file is to use curl.
This command has a --resolve argument which maps domains with IP addresses. Replace __1.1.1.1__ with the IP address of your Droplet.
curl -k -o /dev/null –resolve "www.progressiverobot.com:443:1.1.1.1" -s -v https://www.progressiverobot.com/
This will give a verbose output. The -o redirects all HTML output as we do not need it. This is the snippet we are interested in.
- SSL connection using AES256-SHA
- Server certificate:
- subject: C=US; L=NYC; O=the cloud provider Inc; CN=www.progressiverobot.com; [email protected]
- start date: 2014-03-26 18:39:25 GMT
- expire date: 2014-10-12 18:39:25 GMT
- common name: www.progressiverobot.com (matched)
- issuer: C=US; L=NYC; O=the cloud provider Inc; CN=www.progressiverobot.com; [email protected]
- SSL certificate verify result: self signed certificate (18), continuing anyway.
Examine the next domain.
curl -k -o /dev/null –resolve "www.example.com:443:1.1.1.1" -s -v https://www.example.com
Cert details from output:
- SSL connection using AES256-SHA
- Server certificate:
- subject: C=IN; L=Chennai; CN=*.example.com; [email protected]
- start date: 2014-03-26 18:39:20 GMT
- expire date: 2014-07-04 18:39:20 GMT
- common name: *.example.com (matched)
- issuer: C=IN; L=Chennai; CN=*.example.com; [email protected]
- SSL certificate verify result: self signed certificate (18), continuing anyway.
Notice the differences between both the certificates in the __subject:__ and __expire date:__ fields.
Try accessing the IP address directly.
user@droplet~$ curl -k -o /dev/null -s -v https://1.1.1.1
- SSL connection using AES256-SHA
- Server certificate:
- subject: C=IN; L=Chennai; CN=*.example.com; [email protected]
- start date: 2014-03-26 18:39:20 GMT
- expire date: 2014-07-04 18:39:20 GMT
- common name: *.example.com (does not match '128.199.206.19')
- issuer: C=IN; L=Chennai; CN=*.example.com; [email protected]
- SSL certificate verify result: self signed certificate (18), continuing anyway.
This should return the certificate of __example.com__.