Secure Virtual Hosts under apache - using https

This is enough of a pain in the arse, that, after a handful of colleagues ran into the same issue (forgetting how we had done it once, 10 years ago) I decided to google a bit, to find something concise to explain the process. Here it is. -pbr

transcript:

Hello and welcome.

The apache webserver makes it easy to create an SSL secured virtual host on any installation. In this tutorial I will show how to create your own self-signed ssl certificate and configure your webserver to serve it on its own port.

The prerequisites packages are simply openssl and an apache installation with mod_ssl either compiled as a module or directly into the apache server. If you have mod_ssl compiled into apache, it will appear on the list generated when you run httpd -l. If you have it compiled as a module, you should have a file called mod_ssl.so in your apache modules directory. If you don't know where the modules directory is located, you can look for clues in your httpd.conf file.

To find your httpd.conf file, run httpd -V. Your configuration file is the concatenation of the HTTPD_ROOT directory and the SERVER_CONFIG_FILE directory if the SERVER_CONFIG_FILE does not begin with a slash, or just the SERVER_CONFIG_FILE otherwise. Mine as you can see is located in /etc/httpd/httpd.conf. If I take a look at that file, there are two lines that are important in discovering my modules directory. The first is the ServerRoot directive, and the second is the last argument of the LoadModule lines. The concatenation of these directories is the modules directory, which for me is /usr/lib/httpd/modules. If I grep through this directory, I can see I have mod_ssl.so right here. If you don't have the modules compiled in or compiled as a dynamic module, you will need to recompile your webserver or get a package that includes mod_ssl.

The first thing we are going to need is a server key and certificate that will be used to encrypt and decrypt the data to and from our webserver. And before we do that we are going to help openssl's random number generator a bit by producing some randomish files to seed the generator. First, I have a one-liner python script that produces some randomish strings of alphanumberic characters. Feel free to copy it if you'd like.

#! /usr/bin/env python import string from random import Random import sys for x in range(10000): sys.stdout.write( Random().sample(string.letters + string.digits, 1)[0]

Then, I'm going to run this script 3 times and redirect the output each time to a new file. We now have 3 randomish files that we are going to feed to openssl. To generate our server key, use the following command:

openssl genrsa -des3 -rand file1:file2:file3 -out server.key 1024

You will be prompted for a password, and you may choose any password you like. Now, if you don't mind entering this password every time the apache server is started, you should choose a strong password and omit this next step. If you do not want to authenticate the server key every time the server is started, you can remove the password from the server key with this command:

openssl rsa -in server.key -out server.pem

It will prompt you for the password you entered in the previous step. server.pem now contains the unencrypted server key. Now, even though we are going to be signing the certificate ourselves, we still need a certificate signing request. To generate one based on the unencrypted server key, use the following line:

openssl req -new -key server.pem -out server.csr

You can choose how much information you want to include in your certificate signing request. Since it is not going to be signed by a legitimate authority anyway, you can choose how detailed you want to make it. For the sake of time I will leave all the information blank.

Now, we are going to sign our own certificate signing request with our own server key. Any time someone visits our secure server, they will see a warning that the certificate is invalid. There will be no guarantee to visitors that they are not a victim in a man-in-the-middle attack, but otherwise the encyption will be strong.

The command to sign your certificate is:

openssl x509 -req -in server.csr -signkey server.pem -out server.crt

Now, we are going to copy the files to the httpd configuration directory, and make sure that they are only readable by root, which is especially important if you chose not to keep the password on your server key.

Now, we will need to configure apache to set up the secure server.

Your apache installation should have come with a directory of extra configuration files, including one called httpd-ssl.conf, that contains reasonable defaults. We will only need to alter it slightly to fit our needs.

In the main httpd.conf file, you will need to make only two alterations. One is you have to make sure the mod_ssl modules is loaded, if it's not compiled into your server already.

Add a LoadModule directive, with ssl_module as the first argument and the path to the mod_ssl.so file you found earlier. It should be a path relative to your ServerRoot directory. You can look at the other LoadModule lines for guidance.

Then, down towards the bottom of the file, you need to uncomment the line that includes the httpd-ssl.conf file. Simply remove the # sign in the front and you are done.

Now, in the httpd-ssl.conf file, you need to make the following adjustments. Go to the first VirtualHost block. Make sure the DocumentRoot is set to where you want to house your secure web pages. The default is the main htdocs folder. If you want to make your secure pages separate from your regular pages, you should specify a different document root. I will change the path to htdocs_ssl for this reason.

Next, look down at the line that begins SSLCipherSuite. This is a list of allowed and disallowed encryption standards, and in which order they are prefered. If we had a public site, we would probably want an inclusive list, so even people with old browers or otherwise weak encryption could still connect if they wanted to. For a home intranet or some other private use, a more exclusive policy is preferable. I will change this line to only allow medium to string encryption standards. You can copy my line if you'd like.

SSLCipherSuite RSA:!EXP:!NULL:+HIGH:+MEDIUM:-LOW

Next, go down to SSLCertificateFile and SSLCertificateKeyFile, and make sure they are paths to the files we created earlier. If you are using the unencrypted server key, you should change that file name from server.key to server.pem.

Finally, if you have your secure pages in a separate directory, you will need to create a set of permissions for it so the users to want can access it. My Directory block is very permissive. You can of course change this however you need to.

AllowOverride AuthConfig Order Allow,Deny Allow from all

Now that everything is set up, all we need to do is restart the web server. I put a test file in the htdocs_ssl directory already so we can test it out.

I am connected to my webserver through an ssh tunnel, which is why I'm accessing it on a strange port. If you did not change the https port from 443, then you won't need a port qualification at all. Make sure you access your page at https and not http. As you can see, the browser comes up with a warning that the certificate for the site is not valid. This is because we signed it ourselves. The warning is particularly dire on firefox 3, as it should be, but we can ignore it because we were expecting it. Never visit a site where you get this warning where you will need to divulge personal information, like a credit card number. It could be you are a victim of a man in the middle attack.

And the secure web server is now working. The is a small lock in the bottom of the browser to show that the connection is encrypted. Thanks for watching.

Topic revision: r2 - 2008.12.24 - PaulReiber
 
Copyright © is by author. All material on this collaboration platform is the property of its contributing author.