Lukas Z's Blog

The Circle of Knowledge (a Poem)

Stumbled over this poem reading Slashdot:

The Circle of Knowledge

All philosophy is anthropology;
All anthropology is psychology;
All psychology is biology;
All biology is chemistry;
All chemistry is physics;
All physics is math;
All math is philosophy. :-)

Written by Paul Fernhout.

Client Certificates With Apache on OSX

It’s possible to authenticate a user on a website using client certificates instead of a username and a password. The webserver, in my case Apache, uses a server certificate and only clients with the correct client certificate are able to connect to it.

Last night, for an experiment, I’ve created such a setup on OS X 10.8.4 Mountain Lion using the Apache that is pre-installed on OS X.

To save others some headache, here’s the walkthrough on how to go about it. Please keep in mind that I am not an Apache2 config expert or an ssl-guru. There’s probably room for improvement in the configuration files and process listed below.

Make sure you check out the link I’ve pasted at the very bottom of this article. It was a huge help to make this work!

TODOs

  • Set up some small app to serve the protected content
  • Configure Apache to act as a proxy for that app, SSL Only
  • Create Certificate Authority so I can sign my self-made certs
  • Create certificates
  • Configure Apache to only accept (and proxy) clients that present the right client certificate
  • Profit

So let’s get to work.

1. Set up some small app to server the protected content

For me this was a minimal Rails app that is serving a static webpage. In my case I was using thin and I’ve just started it listening to port 9090.

thin start -p 9090

2. Configure Apache to act as a proxy for that app, SSL Only

The default Apache on OSX has its config files in the folder /etc/apache2/ which in fact is /private/etc/apache2. It has a subfolder users that has configs for each user on the system. So in my case, I edited /etc/apache2/users/lukas.conf.

/etc/apache2/users/lukas.conf
  <VirtualHost localhost:443> # -- already using SSL port here
    ServerName localhost
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:9090/
    <Location />
            ProxyPassReverse /
            Order deny,allow
    </Location>
  </VirtualHost>

This just means that every connection that comes in on port :443 will be forwarded to port :9090. Replace :443 with :80 and restart Apache and you should be able to see the app from Step 1. when typing http://localhost in your browser.

To restart apache you can type

sudo apachectl -k restart

Now, because we said “SSL Only” in the task description, we have to ensure that only SSL connections are accepted. So here’s what my lukas.conf looks like if we do that:

/etc/apache2/users/lukas.conf
  Listen 443

  <VirtualHost *:80>
          <Location />
            SSLRequireSSL
          </Location>
  </VirtualHost>

  <VirtualHost localhost:443>
    ServerName localhost
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:9090/
    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
    SSLEngine on
    SSLCertificateFile /etc/apache2/certs/web.crt
    SSLCertificateKeyFile /etc/apache2/certs/web.key
    <Location />
            ProxyPassReverse /
            Order deny,allow
    </Location>
  </VirtualHost>

The config mentions two files, web.crt and web.key. It’s time to create those.

Note: If this doesn’t work, then take a look at the apache config in /etc/apache2/httpd.conf and ensure that the Proxy and SSL modules are being loaded. (That the appropriate lines are not commented out.)

3. Create Certificate Authority so I can sign my self-made certs

I think a CA (and all certs) can be created using the keychain tool that is included in OS X. However, I prefer the command line approach with openssl. It also has the nice side-effect that the guide will be (mostly) valid on a Linux-machine.

I’ve created two directories, /etc/apache2/certs/ and /etc/apache2/certs/ca. And then I’ve used the shell script from here to create the CA. I’ve pasted the contents into create_ca.sh in /etc/apache2/certs.

/etc/apache2/certs/create_ca.sh
#!/bin/bash
CAROOT=/etc/apache2/certs/ca
mkdir -p ${CAROOT}/ca.db.certs   # Signed certificates storage
touch ${CAROOT}/ca.db.index      # Index of signed certificates
echo 01 > ${CAROOT}/ca.db.serial # Next (sequential) serial number

# Configuration
cat>${CAROOT}/ca.conf<<'EOF'
[ ca ]
default_ca = ca_default

[ ca_default ]
dir = REPLACE_LATER
certs = $dir
new_certs_dir = $dir/ca.db.certs
database = $dir/ca.db.index
serial = $dir/ca.db.serial
RANDFILE = $dir/ca.db.rand
certificate = $dir/ca.crt
private_key = $dir/ca.key
default_days = 365
default_crl_days = 30
default_md = md5
preserve = no
policy = generic_policy
[ generic_policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
EOF

sed -i "s|REPLACE_LATER|${CAROOT}|" ${CAROOT}/ca.conf

cd ${CAROOT}

# Generate CA private key
openssl genrsa -out ca.key 1024

# Create Certificate Signing Request
openssl req -new -key ca.key  \
                 -out ca.csr       

# Create self-signed certificate
openssl x509 -req -days 10000 \
              -in ca.csr      \
              -out ca.crt     \
              -signkey ca.key

As you can see, it (amongst other files) creates the ca.conf in /etc/apache2/certs/ca with the contents of everything between the two occurrences of EOF. Afterwards it creates a key, a signing request, and finally the singing certificate ca.crt in the ca-folder.

So now just run this shell script with bash create_ca.sh.

It will ask you to enter details for your CSR. Make sure you enter localhost when it asks for the FQDN. (Or your domain should you be following these steps for anything else than localhost.) Whatever it is, it should match what you have entered in the apache config as ServerName.

When it’s done make sure you open /etc/apache2/certs/ca/ca.conf and replace the string REPLACE_LATER with /etc/apache2/certs/ca.

Voila, we have our own GoDaddy now. Just a pity that no browser in the world, not even our own, will trust our certificates!

Let’s move on.

4. Create certificates

We need two certificates. The before mentioned web.crt and a client.crt that will be imported into the OS X-keychain so the browsers can access it.

Creating a certificate is straightforward. Here are the basic steps:

  1. Create a private key
  2. Use private key to generate a Certificate Signing Request
  3. Sign CSR with own CA and create the certificate.

So first let’s create the server certs (these will have passphrases that you must type and remember):

openssl genrsa -des3 -out web.key # create key
openssl req -new -key web.key -out web.csr # create csr
openssl ca -config ca/ca.conf -in web.csr -cert ca/ca.crt -keyfile ca/ca.key -out ./web.crt # sign and create certificate

When you now restart Apache it will ask for the passphrase. You should also be now able to connect to https://localhost in your browser. (Your browser will display an ugly, scary warning that you can ignore since it’s just your local box and you won’t scare away any users..)

Okay, now let’s create the client certificate. The one our browser will have to show to get access to the webapp.

openssl genrsa -des3 -out client.key 1024 # create key
openssl req -new -key client.key -out client.csr # create csr
openssl ca -config ca/ca.conf -in client.csr -cert ca/ca.crt -keyfile ca/ca.key -out client.crt # sign and create certificate

For the CN you can enter your own name, since the certificate is issued for you, the user that wants to access the webapp.

Finally, let’s convert the cert to pkcs#12.

openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

It may ask for an export password. You will need it when you (or the user you issued this for) later import the cert into the keychain.

Before we move on to the last step, let me just mention that the whole CA-business doesn’t have to be in a subfolder of your apache config. It can be on a completely different machine. It’s just a few files that help with issuing certificates and they haven’t got anything to do with Apache. It’s in this folder here for convenience (you would only need the ca.crt file in this setup, btw.), but I would probably put them in an entirely different (and very safe) place if I for example was GoDaddy..

Now the grand finale:

5. Configure Apache to only accept (and proxy) clients that present the right client certificate

Back to the Apache config! We have to tell Apache to disconnect everyone with an SSL-error that doesn’t present the right client certificate.

/etc/apache2/users/lukas.conf
  Listen 443

  <VirtualHost *:80>
          <Location />
            SSLRequireSSL
          </Location>
  </VirtualHost>

  <VirtualHost localhost:443>
    ServerName localhost
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:9090/
    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
    SSLEngine on
    SSLCertificateFile /etc/apache2/certs/web.crt
    SSLCertificateKeyFile /etc/apache2/certs/web.key
    SSLVerifyClient require # <--- here we go, client must show his cert
    SSLCACertificateFile /etc/apache2/certs/ca/ca.crt # <--- the ca-cert
    <Location />
            ProxyPassReverse /
            Order deny,allow
    </Location>
  </VirtualHost>

Restart apache. You should no longer be able to connect to https://localhost.

6. Profit

In order to be able to connect again you must import the client certificate into the keychain.

Simply open client.p12 and keychain should automatically open and ask you to import the key. Now refresh your browser, you should be able to connect.

Finally, especially in case of any problems, don’t miss this post on garex.net. It’s a fantastic guide on how to make this work and I would probably still be scratching my head if it wasn’t for this text.

NSHipster

I am currently having a good time programming an iOS app at my current project. While searching for information about a certain topic I’ve stumbled over NSHipster, written by Matt Thompson. The tagline reads: “NSHipster is a journal of the overlooked bits in Objective-C and Cocoa. Updated weekly.”

There’s great content there that I am recommending for every Objective-C programmer. In fact, I am putting it on my Bookmarks-page.

Oblique Strategies

In the 1970s two authors created a box of cards called “Oblique Strategies”. [1] They are supposed to help creative people (musicians) to break creative blocks. It works like this: You get stuck. You pull out a card from the box and ponder it’s meaning which hopefully will help you resolve your problem.

The suggestions are sometimes cryptic. But many suggest a change of perspective. [2] This is useful. Perhaps it is a good idea to start developing our own sets of cards, as well.

There is a website that will randomly give you one card from the original decks. [3] Try it out or read the whole list extracted from that website’s HTML:

  • (Organic) machinery

  • A line has two sides

Websocket-Chat With Rails 4

Couldn’t sleep last night, so I coded up a little web-app to get tired. It’s a simple chat that works with websockets with Rails and the websocket-rails gem.

It’s really not much, but if you want to see how to write such a thing, check out the Github repository.

Idea: A Kickstarter.com for Open Source Software

There’s software I’d like to have written. For example, a port of the Zenburn colorscheme [1] for Octopress. Or a real time map-matching algorithm in Ruby.[2] Or an up to date guide on securing a Linux webserver. And many things more.

I could of course sit down and tackle these problems one by one myself. But I’d run out of time. After all I have work for clients, my personal projects and everything that makes up my private life. So can’t others write it?

The open source software world is full of great things. Not just nice-to-have gimmicks, but truly essential software that often generates great value for startups and established companies. The days of Oracle and Microsoft licenses for libraries and developer tools are over. At least in the Web and mobile application world. [3]

But how much more could be developed and released for free if there was a way for open source devs to make a living from their contributions?

Sure, some do. An open source database can be financed by selling premium services such as hosting, teaching and tech-support. But many things, some small, but still significant, are made by individuals in their free time.

And then there’s Kickstarter.com which is spearheading a paradigm shift in how projects of all sizes can be financed online. Wouldn’t it be cool to have a site like this exclusively for open source software and related things? [4]

Let’s imagine how a site like this could work.

First, people could post requests of things they want to have developed. For example: “A streaming-webradio library written in Objective-C for use with iOS 6”.

Other people (and companies) could now vote to either express “Yes, I/we need this, too.” or they could agree it’s a worthwhile pursuit and say “Yes, and I am willing to pay 50USD to a developer who writes the software.”

At the same time developers could write responses like: “I can do this. It will take me one month and I want to be paid X dollars for it. I will develop it in this fashion: […insert implementation details here…]”

The idea is to not start a website where the cheapest developer wins, but rather someone who can layout his implementation idea and, possibly, back it up with references, such as his Github repository.

The users can then select which developer should be awarded the job. [5] After a developer is selected, a kickstarter-esque funding round begins. If the amount of Dollars is reached, the money is charged and put into escrow.

The money should be given to the developer in parts, for example as a weekly salary. Meanwhile others should be able to review his work. (And even join in to help him or her.)

If the project looks like it’s a failure it can be stopped, and the remaining funds can be transferred back to the backers. If it succeeds, the last payment goes to the developer.

The software (finished or not) is then released under an Open Source license.

I don’t know.. Perhaps this is a silly idea for many reasons I haven’t thought of. But I think it would be neat thing to have if it worked. Companies would of course benefit as well, and they would have the chance to help finance projects directly and get things that mean profit for their business in return.

Footnotes:

[1] Zenburn colorscheme

[2] This is something I work on for a side-project. The link is to my question on gis.stackexchange.com

[3] Okay, I guess you still need vendor specific libraries, if you develop for any phone platform. I just wanted to make a point that Open Source software changed where we get our tools and libraries from.

[4] Kickstarter.com - There might be many others. I should take some time to research similar sites..

[5] Instead of chosing an individual developer a team could be selected, as well. This team could even change in the future and money to individuals is given proportinately to their involvement.

Resume Scp Transfers

A quick tip that just worked beautifully on a 90GB file for me: It’s possible to continue scp transfers with rsync.

rsync --partial --progress --rsh=ssh user@host:remote_file local_file

taken from here. (Thanks!)

My Second Visit to the Apple Store

Replacement iPhone

There was a scratch on the glass that covers the lens of my iPhone. Once I knew it is there it became very annoying, because I noticed it on every photo I took. And since one of the benefits of having an iPhone is the excellent camera, (Excellent for a phone, anyway.) I felt like I’m not getting all the value for the money I’ve spent anymore.

So I went to the App Store again, this time in the early afternoon, and unlike the first time [1] it wasn’t as crowded. I got a service appointment within 30 minutes, and sure enough, when I returned an Apple store employee was with me on time.

Even though the scratch on the glass could have been caused by my own clumsiness (and maybe it was), I was given a brand new replacement phone. For free. I was told that this is was a case for the 2-year warranty.

He asked me if I have a backup of my phone. I told him I had synced the phone that morning. So he wiped my old one clean using the Reset-feature and told me to plug the new one into iTunes at home. I did and about 20 minutes later I had a phone that had the contents of my old phone, including all apps and configurations (except the internet-settings for my cell-provider).

You can bash Apple all you want, but everything they do is smooth. Their hardware is good, the software is good and their service is good. Why should I want to buy a competitor’s phone next time, provided Apple stays the way it is? I don’t see a reason to.

P.S.: There’s been some talk about Apple losing it’s edge since Steve Jobs died. I don’t think so. Check out this article [2]. They make more money with Macs, which are just a small part of their revenue, than the entire PC industry combined.

Links:

  • [1] My First Visit to the Apple Store
  • [2] Mac Makes More Profit Than the Entire PC Industry