SSL Apache Howto

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 10

Introduction

I recently had a need to setup a private directory on my web server that could only be
accessed by a handful of selected people. The content also needed to be encrypted in transit.
This mini-HOWTO details how I did this on a Red Hat 8.0/Apache 2.0.40 server using
mod_ssl and OpenSSL (0.9.6b and higher). Here are the goals of this small project:

 Require HIGH or MEDIUM level SSL/TLS encryption at the transport (TCP) layer
 Browser must use SSLv3 or TLSv1, not SSLv2
 Require username/password authentication for some subdirectories
 Learn about TLS certificates
 Be a mini-CA (Certificate Authority)
 Use a non-standard port to keep most of the port-scanning riffraff away
 Create client certificates, and require them for specific directories

The key to this whole system is the SSL/TLS protocol. SSL stands for Secure Sockets Layer,
and it was developed by Netscape to enable secure transactions over the Web. It operates
between the TCP layer and the HTTP application layer. TLSv1 is the IETF standard
implementation, based on SSLv3. TLS stands for Transport Layer Security.

Assumptions/Prerequisites

First and foremost, this document assumes that you are using some flavor of Linux, Apache
2.0.x, and that you have OpenSSL installed. These particular instructions were generated
using Red Hat 8.0. You should also check out the excellent documentation at Apache.Org.
Other assumptions:

 This will be used over the Internet


 Your DNS configuration is correct (hostname=FQDN, PTR records O.K., etc.)
 Your firewall is setup to allow connections on the chosen https:// port
 You have a second machine with Mozilla or another modern browser for testing
purposes
 In these examples, my FQDN and hostname is:    mars.vanemery.com

Most client tests were performed with the Mozilla web browser. Mozilla is the "reference
platform".

Step 1: Setup your own CA (Certificate Authority)

In order to run a secure (SSL/TLS encrypted) web server, you have to have a private key and
a certificate for the server. For a commercial web site, you will probably want to purchase a
certificate signed by a well-known root CA. For Intranet or special-purpose uses like this, you
can be your own CA. This is done with the OpenSSL tools.

Here, we will make a private CA key and a private CA X.509 certificate. We will also make a
directory for the certs and keys:

[root]# mkdir /root/CA


[root]# chmod 0770 /root/CA
[root]# cd /root/CA

[root]# openssl genrsa -des3 -out my-ca.key 2048


Generating RSA private key, 2048 bit long modulus
.....................................................+++
...................................................+++
e is 65537 (0x10001)
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:

[root]# openssl req -new -x509 -days 3650 -key my-ca.key -out my-ca.crt
Using configuration from /usr/share/ssl/openssl.cnf
Enter PEM pass phrase:
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) [GB]:US
State or Province Name (full name) [Berkshire]:Kentucky
Locality Name (eg, city) [Newbury]:Fayette County
Organization Name (eg, company) [My Company Ltd]:VanEmery.Com
Organizational Unit Name (eg, section) []:Certificate Authority
Common Name (eg, your name or your server's hostname) []:VanEmery.Com CA
Email Address []:[email protected]

[root]# openssl x509 -in my-ca.crt -text -noout

Notes:  The first OpenSSL command makes the key. The second command makes the X.509
certificate with a 10-year lifetime. The third command lets you view the completed certificate.
Make sure that you keep the password in a safe place, you will need this every time you sign
another certificate! You will probably also want to make backups of the cert and key and lock
them in a safe place.

Step 2: Make a key and a certificate for the web server:

Now, we have to make an X.509 certificate and corresponding private key for the web server.
Rather than creating a certificate directly, we will create a key and a certificate request, then
"sign" the certificate request with the CA key we made in Step 1. You can make keys for
multiple web servers this way. One thing to note is that SSL/TLS private keys for web servers
need to be either 512 or 1024 bits. Any other key size may be incompatible with certain
browsers.

[root]# openssl genrsa -des3 -out mars-server.key 1024


Generating RSA private key, 1024 bit long modulus
....++++++
.++++++
e is 65537 (0x10001)
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:

[root]# openssl req -new -key mars-server.key -out mars-server.csr


Using configuration from /usr/share/ssl/openssl.cnf
Enter PEM pass phrase:
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) [GB]:TW
State or Province Name (full name) [Berkshire]:Taipei County
Locality Name (eg, city) [Newbury]:Nankang
Organization Name (eg, company) [My Company Ltd]:VanEmery.Com
Organizational Unit Name (eg, section) []:Web Services
Common Name (eg, your name or your server's hostname) []:mars.vanemery.com
<=== This must be the real FQDN of your server!!!
Email Address []:[email protected]

Please enter the following 'extra' attributes


to be sent with your certificate request
A challenge password []:
An optional company name []:

# openssl x509 -req -in mars-server.csr -out mars-server.crt -sha1 -CA my-
ca.crt -CAkey my-ca.key -CAcreateserial -days 3650
Signature ok
subject=/C=TW/ST=Taipei County/L=Nankang/O=VanEmery.Com/OU=Web
Services/CN=mars.vanemery.com/[email protected]
Getting CA Private Key
Enter PEM pass phrase:

[root]# openssl x509 -in mars-server.crt -text -noout

Make sure that your server name is the same as the FQDN that your clients will use when
connecting to your site. Also, let's get in the habit of protecting our keys with appropriate
permissions:

[root]# chmod 0400 *.key

Now, we need to move the new keys and certs into the proper directories in the /etc/httpd
hierarchy:

[root]# cp mars-server.crt /etc/httpd/conf/ssl.crt


[root]# cp mars-server.key /etc/httpd/conf/ssl.key
[root]# cp my-ca.crt /etc/httpd/conf/ssl.crt

Step 3: Create directories and files for the secure web service

I do not want the secure branch of my webserver directory tree to be part of my "insecure"
branch that serves unencrypted files. My normal web root directory is /var/www/html . The
document root for the secure web server will be located at /var/www/SSL .

[root]# mkdir /var/www/SSL


[root]# chmod 0775 /var/www/SSL
[root]# cd /var/www/SSL
[root]# mkdir Passneeded
[root]# mkdir Certneeded
[root]# mkdir PassAndCert
For testing purposes, I added this very simple test SSL index file into /var/www/SSL . Save it
as index.html . Copy some JPEG files and text files into each directory, so that there will be
something to look at/retrieve in each directory.

Step 4: Configure the Apache web server

On a default Red Hat 8.0 install, there are two config files that concern us: httpd.conf and
ssl.conf. All of our changes will be made in the /etc/httpd/conf.d/ssl.conf file. It is
not necessary to modify the httpd.conf file to accomplish our goals on a stock Red Hat 8.0
server. Here are the changes/additions to ssl.conf :

DocumentRoot "/var/www/SSL"

# Note that the FQDN and server hostname must go here - clients will not be
able to connect, otherwise!
ServerName mars.vanemery.com:443
ServerAdmin [email protected]

# Here, I am allowing only "high" and "medium" security key lengths.


SSLCipherSuite HIGH:MEDIUM

# Here I am allowing SSLv3 and TLSv1, I am NOT allowing the old SSLv2.
SSLProtocol all -SSLv2

# Server Certificate:
SSLCertificateFile /etc/httpd/conf/ssl.crt/mars-server.crt

# Server Private Key:


SSLCertificateKeyFile /etc/httpd/conf/ssl.key/mars-server.key

# Server Certificate Chain:


SSLCertificateChainFile /etc/httpd/conf/ssl.crt/my-ca.crt

# Certificate Authority (CA):


SSLCACertificateFile /etc/httpd/conf/ssl.crt/my-ca.crt

# This is needed so that you can use auto-indexing for some directories in
the
# /var/www/SSL directory branch. This can be handy if you would like to
have
# a list of sensitive files for people to download.
<Directory "/var/www/SSL">
Options Indexes
AllowOverride None
Allow from from all
Order allow,deny
</Directory>

The working config file up to this point is located here.

Step 5: Start the web server and test

Run the following commands to start the the Apache web server:

[root]# /etc/init.d/httpd start


Starting httpd: Apache/2.0.40 mod_ssl/2.0.40 (Pass Phrase Dialog)
Some of your private key files are encrypted for security reasons.
In order to read them you have to provide us with the pass phrases.

Server mars.vanemery.com:443 (RSA)


Enter pass phrase:
Ok: Pass Phrase Dialog successful.
[ OK ]

Note that you will have to enter the password for your server key in order to start the server.
You will also have to do this during boot if you have httpd configured to start automatically.

Make sure that the web server is now listening on the SSL/TLS port, TCP port 443:

[root]# netstat -tna


Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN

In order to test that your SSL/TLS web server is running, you will now need to connect to it
with a browser. The URL you use should be https://yourservername.com. You will
probably get a warning prompt about the Certificate Authority (CA) being unknown. You can
view the certificate properties, which will look familiar because you created the cert yourself.
You can save the cert in your browser, or import the my-ca.crt file into your browser as a
new CA. How you do this will depend on which browser you are using. I had no problems
doing this with Mozilla.

Step 6: Require simple username/password auth for one of the directories:

We want to require a valid username and password for the /var/www/SSL/Passneeded


directory. The username and password will be encrypted in transit as part of the TCP stream.
We will need to setup the access control directives, as well as use the htpasswd command to
add the username/password pairs.

[root]# htpasswd -c -m /etc/httpd/.htpasswd joe


New password:
Re-type new password:
Adding password for user joe
[root]# htpasswd -m /etc/httpd/.htpasswd john
New password:
Re-type new password:
Adding password for user john

[root]# chown apache.root /etc/httpd/.htpasswd


[root]# chmod 0460 /etc/httpd/.htpasswd

Now, we need to tell Apache to require a username/password to access the Passneeded


directory. Here is what we will add to /etc/httpd/conf.d/ssl.conf file:

<Directory "/var/www/SSL/Passneeded">
AuthType Basic
AuthName "Username and Password Required"
AuthUserFile /etc/httpd/.htpasswd
Require valid-user
</Directory>
Now, restart the webserver with /etc/init.d/httpd restart. When you try to access the
Passneeded directory from a web browser, you should be prompted for a username and
password. If you enter incorrect information, you should be denied access.

The config file (up to this point) is located here.

Step 7: Change the TCP port that Apache SSL/TLS listens on:

Since this is a private, special-purpose secure web server, you may want to change the TCP
port from 443 to something else. This will make it just a little more difficult for crackers to
locate via automated network scans. For this excercise, we will change the port to TCP 444 by
editing three lines in the ssl.conf configuration file. Make the following changes to the
ssl.conf :

Listen 444

<VirtualHost _default_:444>

ServerName mars.vanemery.com:444

Now, restart Apache and look at the listening ports:

[root]# /etc/init.d/httpd restart

[root]# netstat -tna


Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:444 0.0.0.0:* LISTEN

Now, you should be able to connect to the server with this URL:

https://yourservername.com:444

The config file including this change is located here. If you are having any problems, you may
want to consult the ssl_* logfiles in the /var/log/httpd directory. These can be quite
useful for trouble-shooting.

Congratulations, you have now configured a basic SSL/TLS web server!

Creating Client Certificates for Authentication

Now, let's say that we want a stronger method of authenticating clients, one that is not as
susceptible to password guessing and shoulder-surfing. What can we do? We can create an
SSL/TLS client certificate. The certificate has to be digitally signed by a CA that the server
trusts, the user has to have the client loaded in his browser, and the user has to know a pass
phrase to use it. The certificate itself uses strong, public-key cryptography. We can make such
a certificate with our OpenSSL toolkit.
A note on certificate formats:   The server and CA certs that we have been using up to now
are encoded in PEM format, which uses ASCII characters. For some reason, the industry-
standard client certs used in web browsers are encoded in the PKCS#12 format, which cannot
be viewed as simple text. It is a binary file. We will now create a client cert by following
these steps:

 Create a new private key and certificate request


 Sign the certificate request, thereby creating the client certificate
 Generate the PKCS#12 cert file
 View information about the PKCS#12 cert
 Import the PKCS#12 client cert into your browser
 Test!

[root]# cd /root/CA
[root]# openssl genrsa -des3 -out van-c.key 1024
Generating RSA private key, 1024 bit long modulus
..++++++
........................................................................+++
+++
e is 65537 (0x10001)
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:

[root]# openssl req -new -key van-c.key -out van-c.csr


Using configuration from /usr/share/ssl/openssl.cnf
Enter PEM pass phrase:
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) [GB]:TW
State or Province Name (full name) [Berkshire]:Taipei County
Locality Name (eg, city) [Newbury]:Nankang
Organization Name (eg, company) [My Company Ltd]:VanEmery.Com
Organizational Unit Name (eg, section) []:Sales
Common Name (eg, your name or your server's hostname) []:Van Emery
Email Address []:[email protected]

Please enter the following 'extra' attributes


to be sent with your certificate request
A challenge password []:
An optional company name []:

# openssl x509 -req -in van-c.csr -out van-c.crt -sha1 -CA my-ca.crt -CAkey
my-ca.key -CAcreateserial -days 3650

[root]# openssl pkcs12 -export -in van-c.crt -inkey van-c.key -name "Van
Emery Cert" -out van-c.p12

[root]# openssl pkcs12 -in van-c.p12 -clcerts -nokeys -info

Note: The "export password" is all the end-user needs to know. This is what you will be
asked for when installing the certificate in a browser.
Now move the van-c.p12 file to your client machine and import it into your web browser.
This is usually done your browser's "Preferences" section under "Privacy and Security",
"Certificates", "Manage Certificates". You may be asked to input a Software Security Device
Master Password. DO NOT FORGET this password! You will also be asked for the client
certificate's export password.

Configure Apache to require client certificates for a specific directory:

In order to require client certificates for the /var/www/SSL/Certneeded directory, you will
need to add the following lines to the /etc/httpd/conf.d/ssl.conf configuration file:

<Directory /var/www/SSL/Certneeded>
SSLVerifyClient require
SSLVerifyDepth 1
</Directory>

Now, restart Apache with /etc/init.d/httpd restart. You can now connect from your
client machine browser to the secure webserver at https://yoursevername.com:444. You
should now be able to click on the "Client Certificate Required" link and view the files in that
directory. I successfully tested my client certificate with:

 Mozilla 1.4 and 1.2.1 on Linux


 Mozilla 1.4 on Windows 2000
 Internet Explorer 6 on Windows 2000
 Opera 7 on Linux
 Konqueror 3.0.5 on Linux
 Galeon 1.2.7 on Linux

If you connect from a different browser that does not have the certificate installed, you will
not be able to enter the directory at all. When you look in your
/var/www/httpd/ssl_error_log file, you will see this error:

[17:41:41] [error] Re-negotiation handshake failed: Not accepted by


client!?
[17:41:41] [error] SSL handshake failed (server mars.vanemery.com:444,
client 192.168.1.191)
[17:41:41] [error] SSL Library Error: 336105671
error:140890C7:lib(20):func(137):reason(199)

Here is the config file that includes all of the changes up to this point.

Configure Apache to require client certificates AND username/password for a


specific directory:

If you are super paranoid, you may want to require a client certificate AND
username/password. This is totally up to you, and it is easy to do.

For this simple example, we will use the .htpasswd file and usernames/passwords that have
already been created earlier. This will force clients to have a certificate and a valid
username/password pair in order to access the /var/www/SSL/PassAndCert. All we have to
do is add the following section to the /etc/httpd/conf.d/ssl.conf configuration file:

<Directory "/var/www/SSL/PassAndCert">
SSLVerifyClient require
SSLVerifyDepth 1
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/httpd/.htpasswd
Require valid-user
</Directory>

Now, restart Apache with /etc/init.d/httpd restart. Connect from your client machine
browser to the secure webserver. When you click the link for the "Client Cert AND Password
Required" directory, you should be prompted for a username and password. You should then
be able to view the directory contents. If you delete your client certificate from the browser,
you will be unable to access either directory that requires client certificates.

Final Config File   (The ssl.conf config file which incorporates ALL of the changes):

Complete Config with All Remarks


Complete Config with Minimal Remarks

Web Server Key Password:

You have probably noticed by now that every time you restart Apache or boot your server,
you are forced to enter the password for the server key. This is a security measure, but it can
be inconvenient. If you would like to make an insecure server key that will allow Apache to
start automatically at boot time, then there is a way to do this. In my case, I don't run an e-
commerce site and I'm not worried about someone else creating a fake VanEmery.Com secure
web site. It is more likely that a power outage will occur that will cause my server to reboot
while I am not around, so I want it to boot without requiring a password. The choice is
yours...

Here is how you do it:

[root]# cd /etc/httpd/conf/ssl.key
[root]# cp mars-server.key mars-server.key.org

[root]# openssl rsa -in mars-server.key.org -out mars-server.key

[root]# chmod 0400 mars-server*

Now, you should be able to restart Apache or boot your server without having to input the
password. This may also be a very good time to copy all the keys and certificates that you
made to floppy or CD. You can imagine what a pain it would be if you lost all of your keys
and certs due to a disk failure. You may even want to make paper copies of the PEM encoded
certificates and keys, which use ASCII text. Lock them in a secure place, along with any
passwords.
Conclusion/Final Comments

As you can see, setting up a secure web server for some specific function is not that difficult.
All the tools are included with a standard GNU/Linux distribution. OpenSSL is a fantastic
Open Source toolkit that can be used in a number of applications. For example, you can use it
to run files through different hashing functions, handle S/MIME encrypted mail, or encrypt &
decrypt files.

In order to use Apache as a high-volume e-commerce server with SSL/TLS, you will probably
need to do more configuration and hardware tuning. You may need to buy and configure a
hardware crypto accelerator card. You will almost certainly want to purchase a "real" server
certificate signed by Entrust, Thawte, or one of the other root-level CAs.

In any event, you now have a good feel for all the pieces, parts, and protocols that make it
work! If you have any comments or corrections, please zap me an e-mail here:     webmaster
[at] vanemery.com

Resources

 Apache 2.0 Documentation


 mod_ssl home page
 OpenSSL home page
 Dr. Henson's PKCS#12 FAQ
 IETF TLS Charter
 Van's List of Useful OpenSSL Tricks
 The following man pages:
o man openssl
o man genrsa
o man req
o man x509
o man pkcs12
o man htpasswd

You might also like