the fast, reliable localhost tunneling solution


Using TLS client authentication with PageKite

By Bjarni RĂșnar Einarsson 2012-11-08, 21:10

Note: The pagekite.net service does not require TLS client authentication, so this HowTo is only useful to folks who are running their own front-end relays.

Version 0.5.4a and later of pagekite.py are capable of providing a client SSL certificate for authentication in addition to the native PageKite protocol challenge-response methods. However, at the moment there is no native support for checking client certificates. This means that in order to restrict access by certificate it is necessary to use a TLS proxy such as stunnel (pound may also work) in combination with pagekite.py. The proxy will then handle the TLS authentication and encryption work.

This how-to provides one example of how to configure pagekite.py back- and front-ends, using stunnel for authentication and openssl to generate certificates. Note that this document only goes through the steps required to get things "up and running", proper system integration is left as an exercise for the reader.

Generating certificates

This is a rough transcript of the commands used to generate a local certificate authority (for signing keys), a certificate for the front-end relay and a certificate for the back-end. This was tested on a Debian system, paths may differ on yours. Output has been omitted.

# Create a working directory
mkdir clientauth
cd clientauth

# Creates a new certificate authority in the subdirectory demoCA
$ /usr/lib/ssl/misc/CA.sh -newca
...

# Generate backend key and certificate signing request
$ openssl genrsa -out backend.key 1024
...
$ openssl req -new -key backend.key -out backend.csr
...

# Do the same for the front-end.  Note that in the second step,
# the answer to the common name question is important, as it will
# be checked for validity by the pagekite.py backend.
#
$ openssl genrsa -out frontend.key 1024
...
$ openssl req -new -key frontend.key -out frontend.csr
...

# Sign backend certificate, combine into single .pem
$ cp backend.csr newreq.pem
$ /usr/lib/ssl/misc/CA.sh -sign
...
$ mv newcert.pem backend.crt
$ cat backend.key backend.crt | tee be-cert.pem

# Sign frontend certificate:
$ cp frontend.csr newreq.pem
$ /usr/lib/ssl/misc/CA.sh -sign
...
$ mv newcert.pem frontend.crt
$ cat frontend.key frontend.crt | tee fe-cert.pem

# Make a copy of the CA cert, for convenience
$ cp demoCA/cacert.pem ca-cert.pem

Now you should have three .pem files, one for the backend, one for the frontend, and one containing the certificate authority's public key.

Configuring the front-end relay

First, we start stunnel in a shell:

$ sudo stunnel -f -v 2 \
     -A /path/to/ca-cert.pem \
     -p /path/to/fe-cert.pem \
     -P /path/to/stunnel.pid \
     -d 0.0.0.0:443 \
     -r localhost:80

Note we are assuming port 80 for pagekite.py and 443 for stunnel, replace with whatever values you deem appropriate. You don't need sudo if you are using non-privileged ports.

In another shell, we start pagekite.py:

$ sudo pagekite.py --clean --isfrontend \
     --ports=80 --protos=http,raw \
     --domain=http,raw:EXAMPLE.COM:yourpassword \
     --tunnel_acl=allow:localhost

This configures pagekite.py to only accept tunnel requests originating from localhost, which hopefully means they come from an authenticated stunnel session or some other trusted source. Other flags you may find useful for restricting access include --host and --client_acl, for debugging check out --logfile=stdio and --debugio.

Once things are working, you can save the configuration by appending these arguments: --savefile=/path/to/frontend.rc --save

Configuring the back-end

The backend can be run like so:

$ pagekite.py --clean \
     --ca_certs=/path/to/ca-cert.pem \
     --frontend=EXAMPLE.COM:80 \
     --proxy=ssl:/path/to/be-cert.pem@EXAMPLE.COM,commonName:443 \
     --backend=http:EXAMPLE.COM:localhost:80:yourpassword

Note that debugging why connections fail is much easier if you also add the following arguments: --logfile=stdio --debugio

Once things are working, you can save the configuration by appending these arguments: --savefile=/path/to/backend.rc --save

A word about proxies

Note that pagekite.py will obey the http_proxy environment variable if it is set, connecting via. that proxy before chaining through to the SSL proxy on the command line. If you need to connect through a longer chain of proxies, this is also possible by listing multiple --proxy lines, they will be chained in the order listed.

One potential point of confusion, is that pagekite.py treats SSL/TLS as a seperate proxy hop. This means if you are connecting through an SSL-secured HTTP proxy, you will need two --proxy lines to connect through it, first the SSL hop and then the HTTP proxy hop, like so:

$ pagekite.py --clean \
     --ca_certs=/path/to/ca-cert.pem \
     --frontend=EXAMPLE.COM:80 \
     --proxy=ssl:/path/to/be-cert.pem@EXAMPLE.COM,commonName:443 \
     --proxy=http:EXAMPLE.COM:443 \
     --backend=http:EXAMPLE.COM:localhost:80:yourpassword

This is unnecessary with stunnel as described above, as it is not an HTTP proxy, it simply forwards all connections directly to pagekite.py for processing.

Comments

  1. bob said on 2015-07-16, 13:16
    I have set up a front and back end and have everything working except I can not get SSL/TSL working. I have tried everything I can find in the man pages and Pagekites's site but am missing something. Regards your back end configuration statement above, "--proxy=ssl:/path/to/be-cert.pem@EXAMPLE.COM,commonName:443 \" , what is meant by "commonName". It is probably something obvious, but not to me. Any help would be appreciated. Thanks for the great open source product, Bob.
    Permalink
  2. Bob said on 2015-07-16, 13:26
    It is amazing but after I posted the comment it dawned on me, "commonName" is from the input when generating the certificate. After the light bulb went on I re-read the above section on generating certificates and it is there in plain sight. Hopefully I'll now be able to get SSL/TSL working. Thanks again for the great open source product, Bob.
    Permalink
  3. bob said on 2015-07-16, 13:26
    I have set up a front and back end and have everything working except I can not get SSL/TSL working. I have tried everything I can find in the man pages and Pagekites's site but am missing something. Regards your back end configuration statement above, "--proxy=ssl:/path/to/be-cert.pem@EXAMPLE.COM,commonName:443 \" , what is meant by "commonName". It is probably something obvious, but not to me. Any help would be appreciated. Thanks for the great open source product, Bob.
    Permalink

Leave a comment

( (Please leave these blank: )

We use Gravatar for commenter's photos. Get your own, it's free!