Hi – Welcome back to the Ubuntu Apache LAMP Server Quick Howto. This second part of the series will cover configuring SSL for use with Apache for securing website content. SSL stands for Secure Sockets Layer, and is a method of providing transport layer encryption or TLS (transport layer security). SSL typically uses X.509 digital certificates to perform authentication and encryption functions. X.509 is based on public key infrastructure or PKI. PKI is beyond the scope of this article (sounds like a good topic for a future article), but we will at least create a self-signed certificate for instructional purposes here.
SSL adds a few caveats to Apache configuration. One of those is name based virtual hosting. SSL does not allow the use of name based virtual hosts. From the apache SSL/TLS Strong Encryption Guide:
“Why is it not possible to use Name-Based Virtual Hosting to identify different SSL virtual hosts?
Name-Based Virtual Hosting is a very popular method of identifying different virtual hosts. It allows you to use the same IP address and the same port number for many different sites. When people move on to SSL, it seems natural to assume that the same method can be used to have lots of different SSL virtual hosts on the same server.
It comes as rather a shock to learn that it is impossible.
The reason is that the SSL protocol is a separate layer which encapsulates the HTTP protocol. So the SSL session is a separate transaction, that takes place before the HTTP session has begun. The server receives an SSL request on IP address X and port Y (usually 443). Since the SSL request does not contain any Host: field, the server has no way to decide which SSL virtual host to use. Usually, it will just use the first one it finds, which matches the port and IP address specified”
My experience is that Apache will reject the configuration if you attempt to use named based virtual hosts with SSL.
So, with this in mind, if I have multiple “sites” to serve with SSL, I either use different IP addresses for each site, or I serve one site with multiple directories of content that can be referenced by http://<site fqdn>/directory. For example, if I had a site called www.stuff.com and it used SSL, I would add content for different functions/site at https://www.stuff.com/systeminfo or http://www.stuff.com/shopping.
Anyway, so, how do we set up SSL? First thing is to make sure its enabled on your LAMP server. To turn on SSL use the following command:
sudo a2enmod ssl
followed by
sudo /etc/init.d/apache2 restart
Also – we should create a specific document root directory for the SSL Apache to use. This way, if you have both SSL and non-SSL sites on the same server, not all the non-ssl sites will be published automatically by the SSL definition.
sudo mkdir /var/www-ssl
Creating a self signed certificate:
In order to use SSL with Apache you must have a certificate. Here is how to make a self signed certificate. Note: Self Signed certs are fine for testing and lab servers, but are not recommended for production environments or internet facing servers.
First, you will need to create a private key file:
sudo openssl genrsa 1024 > host.key
sudo chmod 400 host.key
Next, you will need to create the certificate:
sudo openssl req -new -x509 -nodes -sha1 -days 365 -key host.key > host.cert
After hitting enter, you will be prompted for several pieces of information that will be encoded into the certificate. Here is an example output:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Kansas
Locality Name (eg, city) []:Topeka
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Test.com
Organizational Unit Name (eg, section) []:IT
Common Name (eg, YOUR name) []:www.test.com
Email Address []:admin@test.com
Note, the Common Name should be the fully qualified domain name of your web server. Your cert and key will be in the current directory, and will be called host.cert (cert) and host.key (key). Both of these files will be needed for the next step. As root or using sudo, copy the key file to the /etc/ssl/private directory on your LAMP server, and copy the cert file (host.cert) to the /etc/ssl/certs directory.
Next go to the /etc/apache2/sites-available and edit the default-ssl file. This file controls the default SSL virtual host configuration. We will be modifying the following some the lines in the file. As root, find the beginning stanza in the file (with your favorite editor) and it will look something like this:
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerAdmin webmaster@localhost
DocumentRoot /var/www
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
Change the webmaster@localhost to an email address of the person responsible for the server (this isn’t required, but is probably good practice).
Also, you should probably add a ServerName directive right after the ServerAdmin directive. The ServerName directive should reflect the fully qualified domain name as the server.
The DocumentRoot directive should be changed to /var/www-ssl – the directory we made earlier. Lastly, the Directory /var/www directive should be changed to Directory /var/www-ssl.
Here is the same code snip, modified for a server called www.test.com:
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerAdmin admin@test.com
ServerName www.test.com
DocumentRoot /var/www-ssl
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www-ssl>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
Next, lets find the following couple of lines:
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
These lines tell Apache where to find the SSL certificate to use for the site. We are going to replace these with the certificate and private key we created earlier. We will change them to read:
SSLCertificateFile /etc/ssl/certs/host.cert
SSLCertificateKeyFile /etc/ssl/private/host.key
Ok – make sure you save your default-ssl file with the changes we have detailed above. After the file is saved, run the following command:
a2ensite default-ssl
followed by:
/etc/init.d/apache2 restart
Now, its time to test to see if you can connect to the server with SSL. You might want to create an index.html file at the /var/www-ssl directory first though. To do this simply create a file with “It works, SSL!” in it as root and save it to the /var/www-ssl directory with the name of index.html. Afterwards, open Firefox, and go to https://<server name or IP address>. You probably get a certificate error, since we created a self-signed cert for our tutorial. You should tell Firefox to trust the certificate. If all goes well, you should see: It works, SSL! at the top of the page.
If all went well, we should have a working Apache server with SSL. At this point, you can place content directly under /var/www-ssl or in folders under that directory. If you have some folders under the non-ssl Document root (normally /var/www) simply sim-linking those directories to /var/www-ssl will publish them via SSL as well.
So, what if it doesn’t work? Generally, this is the result of either SSL not being enabled, or an errror in your default-ssl file. Double check that you have enabled SSL with the a2enmod command, and make sure the default-ssl file is correct, and that it has been enabled with the a2ensite command. Also note, that when enabling SSL for the first time, make sure you restart Apache with the command:
/etc/init.d/apache2 restart
To make sure SSL support is enabled. You can check that Apache is listening for SSL connection by doing a
netstat -tan
and looking for an entry like this:
Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
If that line is not present, then double check your configuration.
Next time we will focus on the Mysql portion of a LAMP server – look for it soon.
thanks you ):
” Lastly, the Directory /var/www directive should be changed to Directory /var/www-ssl.”
Are you sure that this is so?
The reason I suggest doing this is so that you will have control over what gets published via SSL. Without changing this directive, everything in the default web root (/var/www/) could get published inadvertently. I like to create the /var/www-ssl directory and then symlink the virtual directories that I want published via SSL to this directory.
““Why is it not possible to use Name-Based Virtual Hosting to identify different SSL virtual hosts?” Such a simple sentence but holy hell did I struggle to make those name based vhosts work. I had no idea… Thank you so much.. I would have spent days banging my head if not for you pointing that out….