Enabling SSL for Apache2: Difference between revisions
m (→SSL for your main protected website: certificates finished) |
m (small edits on ssl certs) |
||
Line 21: | Line 21: | ||
If you cannot implement either one of these two "solutions", then you're stuck with this: you can have ''one'' website behind SSL encryption with a matching SSL certificate; any other website that your Apache webserver is serving will have to do without SSL, or with a nasty error message for every visitor, every time they visit the site. | If you cannot implement either one of these two "solutions", then you're stuck with this: you can have ''one'' website behind SSL encryption with a matching SSL certificate; any other website that your Apache webserver is serving will have to do without SSL, or with a nasty error message for every visitor, every time they visit the site. | ||
==SSL for your main protected website== | |||
OK, let's assume you cannot employ either of the two offered "workarounds", or don't need multiple SSL sites to begin with. We can now determine which one of our virtual hosts (assuming you have multiple) we want to provide SSL for. We'll say that the website that this virtual host is serving is the main protected website. With www.saruman.biz as our example, let's implement SSL. | OK, let's assume you cannot employ either of the two offered "workarounds", or don't need multiple SSL sites to begin with. We can now determine which one of our virtual hosts (assuming you have multiple) we want to provide SSL for. We'll say that the website that this virtual host is serving is the main protected website. With www.saruman.biz as our example, let's implement SSL. | ||
We can start by obtaining the necessary SSL certificates. We determine that the site is located at URI www.saruman.biz, and request an SSL certificate for www.saruman.biz (or for *.saruman.biz) from a trusted Certificate Authority (CA) such as Thawte. Optionally, we generate our own SSL certificate, as has been described in the [[Certificate_fundamentals | certificate section]]. Note that we need the private key to be without passphrase | ===getting the SSL keys=== | ||
We can start by obtaining the necessary SSL certificates. We determine that the site is located at URI www.saruman.biz, and request an SSL certificate for www.saruman.biz (or for *.saruman.biz) from a trusted Certificate Authority (CA) such as Thawte. Optionally, we generate our own SSL certificate, as has been described in the [[Certificate_fundamentals | certificate section]]. Note that we need the private key to be without passphrase. | |||
Sidenotes: if you need to remove the passphrase from your private key, follow the instructions in the section [[Creating_digital_certificates_with_our_root_certificate#CA.sh_-_certificate_creation_made_easy | creating digital certificates with our root certificate]]. Optionally, you ''could'' leave the private key protected with a password ("apache2.sec.key" as it were), but then every time you restart your webserver ''and'' every time you (re)boot your server, Apache2 would have to ask you for the passphrase. Not practical for most solutions. Let's just agree to store the unsecured private key in a very secure fashion. | |||
We can store the two files (key and certificate) in what is | Let's suppose we have the certificates, and we have (re)named them "apache2.pem" and "apache2.unsec.key". | ||
We can store the two files (key and certificate) in what is considered the default SSL location (''/etc/ssl/'', in subdirectories ''certs'' and ''private''); however for Apache2 it seems to be common to store the key and certificate in directory ''/etc/apache2/ssl''. It is not really important what you choose, as long as you protect the unprotected key. In this example, we'll store the key and certificate in ''/etc/apache2/ssl''. | |||
Make absolutely sure that the key file is owned by ''root:root'' and ''chmod''ded to 400; and for neatness you might want to make it so that the certificate is owned by ''www-data:www-data'' and ''chmod''ded to 444. Thus: | |||
host:/etc/apache2/ssl# ls -l | host:/etc/apache2/ssl# ls -l | ||
total 12 | total 12 | ||
-r--r--r-- 1 www-data www-data 4624 2009-01-18 21:56 apache2.pem | -r--r--r-- 1 www-data www-data 4624 2009-01-18 21:56 apache2.pem | ||
-r-------- 1 root root 1675 2009-01-18 21:57 apache2.unsec.key | -r-------- 1 root root 1675 2009-01-18 21:57 apache2.unsec.key | ||
===Prepare Apache for SSL=== | |||
Next up, we can enable SSL for Apache2. There's a helper script under Debian to make it easy for you: | Next up, we can enable SSL for Apache2. There's a helper script under Debian to make it easy for you: | ||
a2enmod ssl | a2enmod ssl | ||
Line 42: | Line 49: | ||
</IfModule> | </IfModule> | ||
So now we're left to enable SSL with the right parameters for the main protected website itself. | So now we're left to enable SSL with the right parameters for the main protected website itself. | ||
===Enable SSL for your websites=== |
Revision as of 10:42, 25 January 2009
Apache2 and SSL
The problem with SSL and Virtual Hosting
To enable SSL for Apache2, you must first realise some important limitations. This section is meant to outline these limitations. First off: let's look at simple HTTP traffic, something that has nothing to do with SSL - but bear with me.
One Apache instance can run multiple websites on one server (one IP address), as so-called virtual hosts. First off, let's assume we have one single server, serving two websites. These can be found using two different DNS names, e.g. www.saruman.biz and www.iceditch.nl. Now suppose a visitor wants to visit one of these sites. The visitor types in a URI pertaining to any one of the websites (containing the DNS name www.saruman.biz or www.iceditch.nl). In both cases he gets the same IP number (212.238.151.172), so his browser sends the HTTP request there, on port 80. Apache receives the request, looks in it, notices the actual URI in it (say: http://www.iceditch.nl/index.htm or http://www.saruman.biz/wiki/index.php/Main_Page), and directs the request to the right website, the right virtual host. So far, no problem at all.
Now consider what happens if we introduce SSL: any request to the HTTPS-port of the server (port 443) gets encrypted using the public SSL-certificate of the server. However, before using it, this certificate is investigated by the browser of the visitor - one of the (sets of) things that must match, is the common name of the certificate (which must match the DNS-name of the website the visitor is visiting). Thus, a visitor for https://www.saruman.biz expects the SSL certificate to be in the name of www.saruman.biz, and so does his browser. But a visitor for https://www.iceditch.nl expects the certificate to be in the name of www.iceditch.nl. Reasonable, eh? But wait - the single Apache2 webserver can have multiple websites, but only one SSL certificate! And that'll be presented to the visitor at the setup of the HTTPS session, before Apache gets to hear which virtual host the visitor wants to visit.
This means that when multiple virtual hosts on a single Apache2 webserver are "put on SSL", they all share the same SSL certificate. And this means that if we have an SSL certificate for www.saruman.biz, that visitors to the HTTPS-version of www.saruman.biz will be presented the "right" SSL certificate, but visitors to the HTTPS-version of www.iceditch.nl will get a certificate for www.saruman.biz as well - leading to nagging warnings in the browser of each one of your visitors.
In effect, you can run only one virtual host, that's accessible over HTTPS, and gets no raised eyebrows on the certificate name issue. SO! Is this a totally unavoidable problem? For most situations: yes. But in some cases there are workarounds.
A solution for the problem of SSL Certificate names and Virtual Hosting
One workaround would be to have two IP numbers for your server, and have two instances of Apache2 listen on port 443: one instance on the IP of www.saruman.biz, and hosting virtual site www.saruman.biz, and using an SSL certificate for www.saruman.biz. The other instance could then listen on the IP number for www.iceditch.nl and use an SSL certificate signed correspondingly. Simple, effective - but requiring multiple IP numbers, and sort of defeating the reason for having virtual hosting in the first place. We hesitate to call this a true "workaround".
Another workaround would be to have multiple Apache2 instances listen on the same IP number, but on different ports: only one could sit behind the port that's default for HTTPS (443); any other site would have to sit behind another port (e.g. 444). This however would force users to type the port in with the URI. In our example: if www.saruman.biz sits behind 443, then www.iceditch.nl could have an SSL protected site behind port 444, but visitors would have to use the URI https://www.iceditch.nl:444/index.htm. Not the handiest or prettiest solution either.
A much better workaround, unfortunately of limited applicability, is to have all virtual hosts be hosted on URI's that are based on the same toplevel domain, e.g. www.saruman.biz, shop.saruman.biz, webmail.saruman.biz etcetera. When multiple virtual hosts share a common DNS domain, then the (single) SSL certificate for these (multiple) virtual hosts could be based on a wildcard SSL certificate name - in this case *.saruman.biz. The certificate would match all those virtual hosts. Alas, it still wouldn't match www.iceditch.nl...
If you cannot implement either one of these two "solutions", then you're stuck with this: you can have one website behind SSL encryption with a matching SSL certificate; any other website that your Apache webserver is serving will have to do without SSL, or with a nasty error message for every visitor, every time they visit the site.
SSL for your main protected website
OK, let's assume you cannot employ either of the two offered "workarounds", or don't need multiple SSL sites to begin with. We can now determine which one of our virtual hosts (assuming you have multiple) we want to provide SSL for. We'll say that the website that this virtual host is serving is the main protected website. With www.saruman.biz as our example, let's implement SSL.
getting the SSL keys
We can start by obtaining the necessary SSL certificates. We determine that the site is located at URI www.saruman.biz, and request an SSL certificate for www.saruman.biz (or for *.saruman.biz) from a trusted Certificate Authority (CA) such as Thawte. Optionally, we generate our own SSL certificate, as has been described in the certificate section. Note that we need the private key to be without passphrase.
Sidenotes: if you need to remove the passphrase from your private key, follow the instructions in the section creating digital certificates with our root certificate. Optionally, you could leave the private key protected with a password ("apache2.sec.key" as it were), but then every time you restart your webserver and every time you (re)boot your server, Apache2 would have to ask you for the passphrase. Not practical for most solutions. Let's just agree to store the unsecured private key in a very secure fashion.
Let's suppose we have the certificates, and we have (re)named them "apache2.pem" and "apache2.unsec.key".
We can store the two files (key and certificate) in what is considered the default SSL location (/etc/ssl/, in subdirectories certs and private); however for Apache2 it seems to be common to store the key and certificate in directory /etc/apache2/ssl. It is not really important what you choose, as long as you protect the unprotected key. In this example, we'll store the key and certificate in /etc/apache2/ssl.
Make absolutely sure that the key file is owned by root:root and chmodded to 400; and for neatness you might want to make it so that the certificate is owned by www-data:www-data and chmodded to 444. Thus:
host:/etc/apache2/ssl# ls -l total 12 -r--r--r-- 1 www-data www-data 4624 2009-01-18 21:56 apache2.pem -r-------- 1 root root 1675 2009-01-18 21:57 apache2.unsec.key
Prepare Apache for SSL
Next up, we can enable SSL for Apache2. There's a helper script under Debian to make it easy for you:
a2enmod ssl
Most howto's then tell you how you need to change /etc/apache2/ports.conf to include port 443, but with Debian 4.0 "Lenny" that's not necessary, since that file contains a section like this:
<IfModule mod_ssl.c> # SSL name based virtual hosts are not yet supported, therefore no # NameVirtualHost statement here Listen 443 </IfModule>
So now we're left to enable SSL with the right parameters for the main protected website itself.