# $Id: README,v 1.2 2003/09/10 22:07:39 ducamp Exp $

1. What is it?
==============

ssltunnel allows to mount a PPP session encapsulated into SSL. That allows
to make a poor man's VPN between two Unix machines or two networks, without
requiring to set up an IPsec technology.

2. Why?
=======

For a simple reason: I often move, and I very often have, in a hotel or in a
corporate network, only a limited access to Internet, i.e.:
  . through address translation (NAT)
  . or worse, through only an HTTP or HTTPS relay.

In all these situations, it is impossible to use a protocol like IPsec,
which will be pitilessly filtered at the exit of the network.

I for a long time used PPP over SSH, even while passing through HTTPS relay
(by using a program like corkscrew or https-relay
(http://www.rominet.net/https-relay), but SSH has several problems:

  . it isn't SSL, and some HTTPS relays start to check that what cross-piece
    them is definitely SSL.
  . it inevitably asks to have an Unix account at the other end, which is
    not inevitably ideal for the management of the authentications

I thus decided to write a "PPP over SSL" tunnel, by obviously using OpenSSL.
I could have made a "do-it-yourself" with stunnel, but I preferred to do
something clean.

3. How?
=======

The principle is to use the SSL client certificates, as in HTTPS:

  - the server listens on port 443 of the destination machine;
  - the client connects himself (if need be, through a relay like Squid,
    ISA-Server, the proxy does not have *ANY* mean to check if it is a
    navigator < - > HTTPS Web server session, because the beginning of the
    not crypted session and the SSL negotiation are exactly identical);
  - at the establishment of the connection, the server forks;
  - the server sends its certificate, the client checks that it is well
    signed by an authority it trusts;
  - the client sends his certificate;
  - the server checks this certificate and seeks if it corresponds to a
    certificate declared in its base;
  - the crypted session starts;
  - the server sends its banner with its version number and its protocol
    version;
  - the client receives the banner, checks and sends his;
  - the client forks, opens a pty, launches pppd in client mode on this pty,
    without specifying which IP address it wants;
  - the server gets PPP parameters from the user file, changes its identity,
    opens a pty, forks and launches pppd on this pty with the options given
    by the file;
  - the PPP session is established between the two ends, the program at each
    end cyphers/uncyphers and reads/sends the data in the pty connected to
    pppd.

4. Server installation
======================

The program is known to compile and work at least on Linux, FreeBSD and
MacOSX (server not tested). The client seems to work also correctly on
Solaris 2.8.

I strongly advise you to have OpenSSL 0.9.7a, this program is very sensitive
in terms of security (SSL negotiation is performed under root) and OpenSSL
already knew some vulnerabilities, some of which serious.

You can choose to compile only the client (--disable-server), only the
server (--disable-server) or both (by default).

4.1. Server compilation

  tar xvfz ssltunnel-<version>.tar.gz
  cd ssltunnel-<version>
  ./configure --disable-client
  make

  The only available options in "configure" are the specifications of the
  base directories of OpenSSL and the iconv library:

  ./configure --with-openssl=/usr/local --with-iconv=/usr/local

  will seek libraries and headers in /usr/local/lib and /usr/local/include

  make install

  Install the following files:

   - /usr/local/libexec/pppserver
   - /usr/local/etc/ssltunnel/tunnel.conf.default
   - /usr/local/sbin/pppwho

  You will also find in the distribution:

  - a server/pppserver.sh script which is to be copied in the initialization
    directories (/etc/rc.d/init.d for example on Redhat) and to activate
    (chmod +x, and chkconfig always for Rehdat).
    On FreeBSD, copy it into /usr/local/etc/rc.d

  - an *example* file of the "users" file, to edit and copy into
    /usr/local/etc/ssltunnel/

4.2 Certificates creation

I don't want to make an SSL course here, you need:

. the public certificate of the certificate authority
. a certificate and a private key for the server
. a certificate and a private key for each client.

All these certificates must be RSA certificates.

I refer you for example to these sites: 
http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/doc/myownca.html
http://www.aboveground.cx/~rjmooney/projects/misc/clientcertauth.html

or to the PKI course by my colleague Franck Davy:

http://www.hsc.fr/ressources/cours/pki/index.html.fr

Their generation should not pose problems for those which already used
OpenSSL, in particular with mod_ssl.

You must have 3 files in PEM format at the server side:

. A file containing trusted CA: trusted.pem
. A file containing the private key of the server (server.key)
. A file containing the certified public key of the server (server.crt)

4.3 Server configuration

- Edit the /usr/local/etc/ssltunnel/tunnel.conf file
  . adjust paths of certificates (attention, it is very important that the
    secret key of the server isn't readable by others than root!),
  . adjust the path of the "users" file
  . change the IP address on which the server must listen (if the line is
    commented out, it will listen on all).
  . change the port if necessary (not advised because you'll have concerns
    then to cross relays).

- The "users" file contains definitions of users. Each block defining a user
  begins with the "user" line and ends with an empty line.

  . user /C=FR/ST=75/L=Paris/O=Alain Thivillon/CN=Alain Thivillon/Email=at@rominet.net

    ==> contains the *COMPLETE* DN of the client certificate.
    It must be the output of the command:
    openssl x509 -nout -subject < client.cert 

    ATTENTION: depending on OpenSSL versions, the syntax of the DN can be
    slightly different, especially for the "Email" part (emailAddress in the
    old versions < 0.9.7).

    If this doesn't work, check the syslog files, the majority of your
    troubles will come from there. The name of the offered client
    certificate appears in the log files.

  . fingerprint: this line is optional and must contain the fingerprint of
    the client certificate. If it is present, the client certificate will be
    checked against this fingerprint.

    The certificate fingerprint can be obtained with the command:

    openssl x509 -noout -fingerprint < certificat_client

  . command: /usr/sbin/pppd

    It is the path to pppd.

  . pty 1

    Permits to run the creation of a pty, let be 1 in the case of pppd

  . args

    Possibly on several lines, contains the arguments passed to pppd.

    It is imperatively necessary to specify the local IP address (before
    the :) and the client one (after the :).

    You can re-use the address of another interface for the local address,
    it is even advised. ATTENTION: You should not use the address on which
    the client connects to, else you have an egg and chicken problem, since
    the packets encapsulating the tunnel will want to go into the tunnel...

    If you just make point-to-point to reach the system, two random
    192.168.x.y will be well.

    If you don't know pppd well, I advise you not to touch the other
    options. It can be interesting to add "debug", at least at starting.

    If you don't use PAP nor CHAP, it will be necessary to put the "noauth"
    option in /etc/ppp/options, or to create a /etc/ppp/peers/incoming file,
    containing "auth", and to add "call incoming" in the PPP options.

  . uid and gid

    Allows to change Unix identity before running pppd: permits to reduce
    the privileges. Attention, it will be necessary that used user and group
    have the right to run pppd! Obviously, that also implies that pppd is
    setuid root, so that it can set up routes, handle ARP table, etc...

    If these lines aren't present, everything will be executed as root.

4.4. Server starting

To test:

/usr/local/libexec/pppserver /usr/local/etc/ssltunnel/tunnel.conf

Verify that the program ran ok, and *READ SYSLOG FILES*.

By default, pppserver logs into local6.*:

touch /var/log/ssltunnel.log
echo "local6.debug<tab>/var/log/ssltunnel.log"
killall -1 syslogd

The majority of errors will come from certificates and the pppd running,
therefore think well about reading logs, all will be inside.

Do I have said to you that the logs have to be read ?

4.5 pppwho

The server maintains in utmp(3) format the list of connected users and the
trace of sessions in /var/log/ssltunnel.wtmp.

You can consult the list of connected users with the "pppwho" command. The
"-n" option allows to avoid the reverse resolution of client IP addresses,
the "-a" option displays all the sessions, including those finished.

Alain Thivillon    75454 khany.rominet.net          05/30 21:19 21:34 (00:15)
Alain Thivillon    21531 XXXXXXXXXXXXXX             06/02 09:19 18:20 (09:00)

First column is the certificate CN, the second the pid of the server
managing the connection, the 3rd the client IP address, and following the
date and the hour of connection beginning, with the total time of the
session between brackets.

5. Client installation
======================

5.1 Compilation

  tar xvfz ssltunnel-<version>.tar.gz
  cd ssltunnel-<version>
  ./configure --disable-server
  make

  make install
  will only install /usr/local/bin/pppclient

  If you like Unixes where all is found in /usr/bin and where find is side
  by side with Quake, you can test:

  ./configure --prefix=/usr

  (no polemic).

  If you have the iconv library in the libc (GNU systems) or installed
  elsewhere, you will be able to use relays authenticating the user with the
  NTLM protocol (Microsoft ISA Server). You also need OpenSSL 0.9.7 or
  higher for this functionality.

  Under FreeBSD, you must install libiconv and launch configure with the
  following option:

  ./configure --with-iconv=/usr/local


5.2 Certificates

 You need:

 . the client private key (client.key)
   I advise you to make a key *with* passphrase, so that the theft of your
   portable/machine/server doesn't compromise the remote network.

   To generate a new key with a password from another one:

   openssl rsa -out client.key.pass -in client.key -inform pem -passout stdin
   (type the password)

   The password of the key will be requested at the client start.

 . the certified public key of the client (client.crt)

 . the list of trusted CA (trusted.pem)

5.3 Configuration

The client (pppclient) has some options on the command line, but the largest
part of the configuration is made in a configuration file.

The one given in example (tunnel.conf) is commented, you must change at
least:

. the IP address or the server name
. the path of certificates except if you have a login "at" on your machine.

If you use a proxy, you must inform his IP address, its port, possible login
and password, and don't forget to set the "userproxy" parameter to 1. If you
use a NTLM proxy, the name of the user must probably be of the type
"DOMAINE\user".

I do not advise you to change the "echoint" and "echofail" parameters, they
must be roughly the same as on the server, else there is a risk the server
continues to run after the client stopped, in the event of network cut.
While reconnecting, that can work, but the server will probably have routing
problems.

You can ask the client to automatically reconnect itself in the event of cut
(option autoreconnect), and to work in background and, in this mode, to log
into a file rather than to syslog (parameter logfile). Tomasera claims that
this option doesn't work under Linux-PPC :)

In foreground, the client displays the size of emitted and received packets
on the terminal.

Notes:

  . It is necessary that the program has the right to run pppd. On the
    majority of Unixes, it is necessary to be member of a "dialer" or
    "network" group.

  . It is necessary that pppd is setuid root so that routes are set up. 
    Alternatively, you can run pppclient as root.

  . If you don't want to/can't put a "noauth" option in /etc/ppp/options,
    you must create a /etc/ppp/peers/<peername> file containing "noauth", so
    that you do not try to authenticate the server.

    <peername> must then be specified in the configuration file:

    peer	<peername>

    If the remote system also asks you a PAP or CHAP authentification, you
    must also specify the user name to be sent:

    user	<remoteuser>

    And also fill /etc/ppp/pap-secrets or /etc/ppp/chap-secrets

    <remoteuser>	*	<password>

    Think about looking into pppd logs if it can't be run or the negotiation
    fails.

5.4 Starting

To start the program:

pppclient [-options] <configuration_file>

If no file is given, the client reads ~/.ssltunnelrc.

A successful run must display something like that:

pppclient version 1.04 using OpenSSL 0.9.7a Feb 19 2003
Using configuration file : /home/at/.ssltunnelrc
verbose                         1
remotehost                      192.XX.XXX.YY
port                            443
localppp                        /usr/sbin/pppd
ipparam                         tunnel
localproxyarp                   0
localechoint                    10
localechofail                   10
localdebug                      0
timeout                 20
useproxy                        0
proxy                           192.XX.TTT.ZZ
proxyport                       8080
proxyuser                       
proxypass                       
useragent                       Mozilla/4.73 (Win95;I)
keyfile                         /home/at/certs-hsc/khany.key
certfile                        /home/at/certs-hsc/khany.crt
cacertfile                      /home/at/certs-hsc/ca-cert.pem
autoreconnect           1
daemon                  0
Enter PEM pass phrase:
23:07:21 Connecting to 192.XX.XXX.YY
23:07:21 Connected
23:07:21 SSL connect sucessful
23:07:21 Server version : 1.04
23:07:21 Server Protocol version : 1.0
23:07:21 forking ppp
23:07:21              -----> 34
23:07:21 46 <-----
23:07:21              -----> 46
23:07:21 34 <-----
23:07:21              -----> 37
23:07:21 51 <-----
23:07:21              -----> 37
23:07:21 32 <-----
23:07:21              -----> 23
23:07:21 19 <-----
23:07:21 32 <-----
23:07:22 13 <-----
23:07:22 26 <-----
23:07:22              -----> 14

In theory, you have a ppp0 interface which is up, test to ping the other
end.

You have the possibility to set up routes automatically, to execute
actions... when the PPP interface is up, by using the /etc/ppp/ip-up script
run by pppd, to which is given in 6th argument the content of the "ipparam"
parameter.

Here is for example the script that I use under FreeBSD (the syntax of the
route command can vary).

#!/bin/sh
if [ $6 = 'tunnel' ]; then
  /sbin/route add -host 192.XX.YYY.TT -iface $1
  /sbin/route add -host 192.XX.YYY.UU -iface $1
else if [ $6 = 'road' ]; then
  /sbin/route add -net 192.168.230.0/24 -iface $1
else if [ $6 = 'wifi' ]; then
  /sbin/route add default -iface $1
fi
fi
fi

For the other arguments given to ip-up, see the pppd man.

Some options are available in the command line, which allow to override the
options from the configuration file.

-h finalhost: change the final destination
-p finalport: change the final port
-r proxyname: change the proxy name
-p proxyport: change the proxy port
-a user-proxy:pass-proxy: authentication on the proxy
-c 0/1: automatic reconnection no/yes
-d 0/1: change into daemon mode no/yes
-l logfile: name of the log file in daemon mode

6. Bugs
=======

 Send them (with the patch :) : <ssltunnel@rominet.net>

7. To do
========

  See TODO.

