OS X hosting, Xserves, Mac Minis, G4’s, G5s

Here for all your hosting and support.

mod_ssl on a mac

with one comment

Using mod_ssl on Mac OS X

Web development requires the hardware and software to accommodate a wide variety of client needs and web technologies. Apple has provided web developers with an enormously flexible development environment in Mac OS X. By including Apache, the world’s most widely used web server, along with a host of related technologies (PHP, OpenSSL, SSI, etc) Apple has provided a perfect compliment to popular tools such as BBEdit, Adobe Photoshop, and Macromedia Dreamweaver.

This tutorial will show you how to enable one of the most important technologies included with the standard installation of Apache on Mac OS X, mod_ssl. The mod_ssl module lets Apache use OpenSSL, thereby enabling cryptographically protected connections to web servers via the Secure Sockets Layer (SSL) and Transport Layer Security. Though this is not a comprehensive tutorial on system security, if you enable mod_ssl you will add a layer of security to a Mac OS X machine’s Web Sharing feature.

For more on security in Mac OS X, see An Introduction to Mac OS X Security.

Why SSL?

Adding Apache support for mod_ssl is a great development step. You will be able to test scripts and applications in the most realistic environment possible prior to deployment to a staging or production server. This will help cut development time. It also permits access to your computer that is encrypted. Web applications served off of your Macintosh will be accessible in a secure way. So passwords passed to your machine via web-based forms will be hidden from packet sniffers. Data transmitted to a browser will also be encrypted during transit.

Definition of SSL

The Draft Specification for the SSL Protocol contains a good definition of SSL.

… Secure Sockets Layer(SSL V3.0) protocol [is] a security protocol that provides communications privacy over the Internet. The protocol allows client/server applications to communicate in a way that is designed to prevent eavesdropping, tampering, or message forgery.

In other words, SSL enables client/server communications that are encrypted, providing security and privacy in communications. Additionally, with SSL, every server has a “fingerprint”, a means of identifying a specific server as being the source of any information returned through an SSL request.

SSL uses Public Key Cryptography, which uses Key Pairs — one private key, kept on the server, and one public key, distributed to clients requesting it. Data encrypted or “locked” with one key can only be decrypted, or “unlocked” with the matching key in the key pair.

What’s There and What’s Needed

To establish secure communications over the web via SSL you need the Apache server compiled with the Enhanced Apache API (EAPI), OpenSSL, and the mod_ssl module. Thankfully, Apple has provided all of the needed ingredients in Mac OS X. Moreover, you can find documentation for these products on a standard Mac OS X installation:

The one item you need to add is the sign.sh script that is distributed with the mod_ssl distribution. You can find more information on this on the FAQ.

If you know how to start the Terminal, run sudo, and edit the httpd.conf file that configures Apache, you’ll be in good shape. I like using emacs for editing text files, and have included the commands needed for working with emacs. Feel free to use pico, TextEdit, BBEdit, or whatever you know how to use.

The sudo command lets you temporarily become a “superuser”. Using it requires that you know the password of a member of the admin group. You can see the members of the admin group by checking NetInfo Manager (under /groups/admin).

Finally, as cryptography is an acronym-rich subject, it might be helpful to keep a good glossary of terms used in cryptography close at hand. In this article, you’ll come across the following acronyms:

  • RSA: A commonly used Public Key encryption system developed by Rivest, Shamir, and Adelman.
  • DES: Data Encryption Standard. A cipher commonly used in commerce. Triple DES (3DES) describes the process of encrypting data three times with two or three DES keys.
  • PEM: Privacy Enhanced Mail. An e-mail cryptography protocol from the IETF.

Configuring SSL

The first thing you need to do is generate the keys and certifications for the server. This requires using the Terminal. For sanity’s sake, create a directory (Folder) on the desktop called KeyGen and change into that directory.

cd ~/Desktop/KeyGen

You can now create an RSA private key and a CSR (Certificate Signing Request) for your server. An important part of private key cryptography is making sure that the parties involved in a transaction are who they say they are. This is accomplished through a third party — a trusted Certificate Authority (CA). The CA issues certificates that identify the parties, and confirms that the keys are correct and are cryptographically “signed.” Generating the CSR is the cryptographical equivalent to filling out a passport application. The CA will return the certificate (like a passport) which is used for identification and authentication.

You’re going to be self-signing the keys, so you’ll also be creating a CA key for the signature. The keys and certificates you create are purely for testing purposes. If you need to set up a production server, you should send your CSR to a proper CA, such as Verisign, for signing.

To create the RSA private key, issue the following command:

openssl genrsa -des3 -out server.key 1024

You will be asked for a passphrase in the creation of this key. Do not forget this passphrase! You’ll have to do this all over if you forget the passphrase. You will need this passphrase later on in the process.

You have just created the “SSLCertificateKeyFile”, as it is called in the httpd.conf — a 1024 bit RSA key encrypted with Triple-DES in PEM format. You’ll be plugging this into the configuration file for Apache soon.

Now you’re ready to create a CSR (Certificate Signing Request), which is what you would normally send to a CA for signing. You’re going to sign it yourself.

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

You’ll be asked for some information when you start this. Most of it is pretty self explanatory, but one item, in particular, is not. Here’s what you’ll be asked for:

Country Name (2 letter code) [AU]: (enter your country code here)
State or Province Name (full name) [Some-State]: (Enter your state here)
Locality Name (eg, city) []: (enter your city here)
Organization Name (eg, company) [Internet Widgits Pty Ltd]: (enter something here)
Organizational Unit Name (eg, section) []: (enter something here)
Common Name (eg, YOUR name) []: (this is the important one)
Email Address []: (your e-mail address)

The entry for “Common Name” is the one that seems like it should be one thing, but is, in fact, another. For this entry, you want to enter your “Server Name” as it appears in your httpd.conf (which you’ll be modifying soon). As this is just a development environment, you can enter, which is the default IP for “localhost”. Now, keep in mind that using is not the same as using “localhost”. The strings either match, or they don’t — Unix is like that.

Looking at your KeyGen directory, you should have this:

[localhost:~/Desktop/KeyGen] bob% ls -la
total 12
drwxr-xr-x    5 bob      staff         126 Sep 14 17:01 .
drwx------   38 bob      staff        1248 Sep 14 16:57 ..
-rw-r--r--    1 bob      staff         729 Sep 14 17:01 server.csr
-rw-r--r--    1 bob      staff         963 Sep 14 16:59 server.key

Now you need to create a CA for signing the key. The process is similar to what you’ve just done, but there are some differences.

The first thing you need to do is create a key for your CA. It’s just like your server.key – a Triple-DES encrypted, 1024 bit RSA key.

openssl genrsa -des3 -out ca.key 1024

Again, you’ll be asked for a passphrase, which, again, you should not forget.

Now you will create a self-signed CA Certificate using the RSA key you just made.

openssl req -new -x509 -days 365 -key ca.key -out ca.crt

You’ll be asked for the passphrase for the key you just made, and, again, you’ll be asked to enter information about yourself. The main difference is that here, when you are asked for your “Common Name”, you want to enter your name — not the server name or IP address. This certificate is not associated with your server — it’s associated with you. It should look something like this:

Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Texas
Locality Name (eg, city) []:San Antonio
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bogus CA
Organizational Unit Name (eg, section) []:Bogus CA for Dev
Common Name (eg, YOUR name) []:Bob Davis
Email Address []:bobdavis@mac.com

Now you have 4 files in your directory — a CA key and certificate, and a server key and certificate signing request.

The next step is the important one. This is where you sign the server.key with your ca.crt. This will provide the security assurance that browsers need to establish a secure connection. It provides the identification and verification part of the public key encryption system where the keys themselves provide the mechanism for the encryption and decryption.

The easiest way to do this is to use the sign.sh script contained in the mod_ssl source you downloaded (it’s in the pkg.contrib sub-directory) or wherever you put.

Copy the script to your working directory, make it executable, and then run it by issuing the following commands:

chmod +x sign.sh
./sign.sh server.csr

You should get something like this, but with the information you entered for the server.csr:

CA signing: server.csr -> server.crt:
Using configuration from ca.config
Enter PEM pass phrase:
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'Texas'
localityName          :PRINTABLE:'San Antonio'
organizationName      :PRINTABLE:'Testing'
commonName            :PRINTABLE:''
emailAddress          :IA5STRING:'bobdavis@mac.com'
Certificate is to be certified until Sep 14 23:09:20 2002 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
CA verifying: server.crt <-> CA cert
server.crt: OK

For the questions “Sign the certificate?” and “1 out of 1 certificate requests certified, commit?”, you just need to type “y” (without quotes) and hit enter/return.

Looking at your working directory now, you’ll see that you have a number of new files and directories in KeyGen.

[localhost:~/Desktop/KeyGen] bob% ls -la
total 36
drwxr-xr-x   12 bob      staff         364 Sep 14 18:16 .
drwx------   38 bob      staff        1248 Sep 14 18:12 ..
-rw-r--r--    1 bob      staff        1298 Sep 14 17:55 ca.crt
drwxr-xr-x    3 bob      staff          58 Sep 14 18:09 ca.db.certs
-rw-r--r--    1 bob      staff         111 Sep 14 18:09 ca.db.index
-rw-r--r--    1 bob      staff           3 Sep 14 18:09 ca.db.serial
-rw-r--r--    1 bob      staff         963 Sep 14 17:52 ca.key
-rw-r--r--    1 bob      staff        2679 Sep 14 18:09 server.crt
-rw-r--r--    1 bob      staff         729 Sep 14 17:01 server.csr
-rw-r--r--    1 bob      staff         963 Sep 14 16:59 server.key
-rwxr-xr-x    1 bob      staff        1784 Sep 14 17:59 sign.sh

Now, make a directory in your /etc/httpd called ssl.key

sudo mkdir /etc/httpd/ssl.key

You’ll be prompted for your login password (you have to be in the admin group to use sudo), and the directory will be created.

Move all of the contents of your working directory to the ssl.key directory you just made. In a production system, it would be a very, very bad idea to keep your CA keys, certs and such on the server. If the security of the server is compromised, the ca.crt could be used to “sign” certificate signing requests on any machine. In other words, it gives anyone the power to impersonate you on the internet. Since you’re just using this for testing, and the certificates have bogus information in them, it’s not so terribly important. It is worth noting that this practice would be considered irresponsible on a server accessible to the outside world.

sudo cp -r * /etc/httpd/ssl.key/

One more step — and it’s another step that would not have a place in a production environment, but definitely makes life with your development system better: you’re going to remove the passphrase requirement from the server key by removing its encryption.

As things stand, when you start Apache, you will be prompted for a passphrase to read the private key. While this is fine for those who start and stop Apache manually from the command line every time, it does create some problems for those of us who have Apache (a.k.a. Web Sharing) start up automatically every time the system reboots. The system will hang on startup, patiently waiting for a passphrase that will never come — because there’s no way to enter the passphrase you’ve given the key! You’ll have to either boot into Mac OS 9 or boot into verbose mode to clear this problem if you forget.

Removing the pass phrase requirement is dangerous in a production environment, but acceptable for testing (especially if you enter information in your certificate request that makes it clear that this is a testing certificate, and not for production use).

Enter the following:

cd /etc/httpd/ssl.key
sudo cp server.key server.key.original
sudo openssl rsa -in server.key.original -out server.key

You’ll be asked for your passphrase for both the sudo command (your system passphrase) and the RSA command (the passphrase for the key). Comparing the two files server.key and server.key.original will show that they are now very different and that server.key.original contains a line stating, “Proc-Type: 4,ENCRYPTED”, that the decrypted file lacks.

Now, you have all of the files you need to make mod_ssl work with Apache. But you still need to configure the Apache server to use mod_ssl. Apple’s engineers have thoughtfully provided Apache compiled with EAPI, which allows modules to be included in Apache without recompiling the server. It makes it a lot easier to enable various modules as you need them.

Stop your web server if you haven’t already, either by using the Sharing control panel or through the command line using:

sudo apachectl stop

The file you want to edit is /etc/httpd/httpd.conf. The first thing you want to do is make a backup of the file. Keeping in mind that this directory is owned by root, you will have to use sudo for all of these commands. So, change directories to /etc/httpd and then make a copy of your httpd.conf.

cd /etc/httpd
sudo cp httpd.conf httpd.conf.backup

Now edit your httpd.conf file using the editor of your choice. I use emacs, so the instructions here are for emacs.

sudo emacs httpd.conf

First, you need to comment out the “Port” directive by placing a “#” in front of the line.

Port 80 should be changed to #Port 80. You will need to add the following just below where the Port directive was:

## SSL Support
## When we also provide SSL we have to listen to the
## standard HTTP port (see above) and to the HTTPS port

<IfModule mod_ssl.c>
		Listen 443
		Listen 80

Adding these lines tells the server to be aware of traffic on port 80 (the standard HTTP port) and port 443 (the HTTPS port). This allows your SSL aware Apache installation to serve non-secure documents on port 80, while it is serving secure documents on 443.

Continuing on in the httpd.conf file, find the lines that reads:

#LoadModule ssl_module         libexec/httpd/libssl.so

and a little further down:

#AddModule mod_ssl.c

You need to remove the comments (#) to activate these lines. You can quickly search for these lines by using CTRL + s (in emacs) and typing “ssl”.

The two lines should now look like this:

LoadModule ssl_module         libexec/httpd/libssl.so

AddModule mod_ssl.c

Now find the “ServerName” directive and make sure it has for it’s entry.


Finally, just below the last line of the current httpd.conf, enter the following information which covers some of the global SSL directives and the specific directives for the port based virtual hosts.

<IfModule mod_ssl.c>
# Some MIME-types for downloading Certificates and CRLs
  AddType application/x-x509-ca-cert .crt
  AddType application/x-pkcs7-crl .crl

# inintial Directives for SSL

  # enable SSLv3 but not SSLv2
  SSLProtocol all -SSLv2
  SSLPassPhraseDialog builtin
  SSLSessionCache dbm:/var/run/ssl_scache
  SSLSessionCacheTimeout 300
  SSLMutex file:/var/run/ssl_mutex
  SSLRandomSeed startup builtin
  SSLLog /var/log/httpd/ssl_engine_log
  SSLLogLevel info
## SSL Virtual Host Context
  #Just to keep things sane...
    DocumentRoot "/Library/WebServer/Documents"
    ServerAdmin bobdavis@mac.com
    SSLEngine off
  # General setup for the virtual host
    DocumentRoot "/Library/WebServer/Documents"
  #ServerName has to match the server you entered into the CSR
    ServerAdmin bobdavis@mac.com
    ErrorLog /var/log/httpd/error_log
    TransferLog /var/log/httpd/access_log
  # SSL Engine Switch:
  # Enable/Disable SSL for this virtual host.
    SSLEngine on
    # enable SSLv3 but not SSLv2
	SSLProtocol all -SSLv2
  # Path to your certificates and private key
    SSLCertificateFile /etc/httpd/ssl.key/server.crt
    SSLCertificateKeyFile /etc/httpd/ssl.key/server.key
    <Files ~ ".(cgi|shtml|phtml|php3?)$">
      SSLOptions +StdEnvVars
    <Directory "/Library/WebServer/CGI-Executables">
      SSLOptions +StdEnvVars
# correction for browsers that don't always handle SSL connections well
    SetEnvIf User-Agent ".*MSIE.*"
    nokeepalive ssl-unclean-shutdown
    downgrade-1.0 force-response-1.0
# Per-Server Logging:
# The home of a custom SSL log file. Use this when you want a
# compact non-error SSL logfile on a virtual host basis.
    CustomLog /var/log/httpd/ssl_request_log
    "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x "%r" %b"

At this point, save your document (CTRL-x CTRL-s) and close emacs (CTRL-x CTRL-c).

There are many directives you can add to the SSL configuration for your machine, including extended logging, restrictions on ciphers used, encryption levels, etc. Full documentation is included in the Apache documents provided with Mac OS X (/Library/Documentation/Services/apache_mod_ssl/index.html) or on-line at http://www.modssl.org/.

Now it’s time to start your SSL enabled web server. You have the option of using either the command line or the Sharing control panel to start your web server. Since you have removed the passphrase requirement from your server key, it’s very simple. Either start Web Sharing from the control panel, or type either of the following lines into the command line:

sudo httpd -D SSL
sudo apachectl start

You will be asked for your system password, and you’ll get the output of Apache starting. It’s that simple. If you have Web Sharing set to start at startup it will start normally (this is why we removed the passphrase requirement).

Now test your installation using the browser of your choice by trying to access Netscape 6 and Safari provide more information and allow you to accept unknown Certificate Authorities very easily. Microsoft’s Internet Explorer 5.x still has issues with unknown certificate issuers and will fail authentication.

Using Netscape, you’ll see the little open lock in the right corner has become a closed, illuminated lock. Success! You have enabled mod_ssl in your Mac OS X development environment.

Mention of non-Apple products or services is for informational purposes only. Apple assumes no responsibility with regard to the selection, performance, or use of these products.


Written by montanaflynn

March 3, 2008 at 6:51 pm

One Response

Subscribe to comments with RSS.

  1. […] mod_ssl on a mac (osxhosting.wordpress.com) […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: