# $Id: LISEZ-MOI,v 1.5 2003/09/10 22:07:39 ducamp Exp $

1. C'est quoi ?
===============

ssltunnel permet de monter une session PPP encapsule dans SSL. 
Cela permet de faire un VPN du pauvre entre deux machines Unix
ou entre deux rseaux, sans ncessiter de mettre en place une 
technologie IPsec.

2. Pourquoi ?
=============

Pour une raison simple : je me dplace souvent, et je n'ai bien
souvent, dans un htel ou dans un rseau d'entreprise, qu'un accs
limit  Internet, c'est  dire :
  .  travers de la traduction d'adresse (NAT)
  . ou pire,  travers uniquement un relais applicatif HTTP ou
    HTTPS.

Dans toutes ces situations, il est impossible d'utiliser un 
protocole comme IPsec, qui sera impitoyablement filtr  
la sortie du rseau.

J'ai pendant longtemps utilis PPP sur SSH, mme en passant au travers d'un
relais HTTPS (en utilisant un programme comme corkscrew ou 
https-relay (http://www.rominet.net/https-relay),
mais SSH a plusieurs problmes : 

  . ce n'est pas du SSL, et certains relais HTTPS commencent 
    vrifier que ce qui les traverse est bien du SSL.
  . il demande forcment d'avoir un compte Unix  l'autre bout,
    ce qui n'est pas forcment idal pour la gestion des
    authentifications

J'ai donc dcid d'crire un tunnel "PPP dans SSL", en utilisant 
bien videmment OpenSSL. J'aurais pu faire une bidouille avec
stunnel, mais j'ai prfr faire quelque chose de propre.

3. Comment ?
============

Le principe est d'utiliser les certificats clients SSL, comme dans
HTTPS :

  - le serveur coute sur le port 443 de la machine destination ; 
  - le client se connecte (si besoin, au travers d'un relais
    comme Squid, ISA-Server, le proxy n'a *AUCUN* moyen de 
    vrifier si c'est une session navigateur <-> serveur Web HTTPS, car
    le dbut de la session non chiffre et la ngociation SSL sont 
    exactement identiques) ; 
  - A l'tablissement de la connexion, le serveur "forke" ;
  - le serveur envoie son certificat, le client vrifie qu'il
    est bien sign par une autorit  laquelle il fait confiance ;
  - le client envoie son certificat ;
  - le serveur vrifie ce certificat et cherche s'il correspond
     un certificat dclar dans sa base ;
  - la session chiffre commence ;
  - le serveur envoie sa bannire avec son numro de version et sa 
    version de protocole ;
  - le client reoit la bannire, vrifie et envoie la sienne ;
  - le client "forke", ouvre un pty, lance pppd en mode client sur ce pty,
    sans prciser quelle adresse IP il veut ;
  - le serveur rcupre les paramtres PPP dans le fichier
    utilisateurs, change d'identit, ouvre un pty, "forke" et lance pppd
    sur ce pty avec les options donnes par le fichier ;
  - la session PPP s'tablit entre les deux extrmits, le programme
     chaque bout chiffre/dchiffre et lit/envoie les donnes dans le pty
    connect  pppd.

4. Installation du serveur
==========================

Le programme est connu pour compiler et fonctionner au moins sur Linux,
FreeBSD et MacOSX (serveur non test).  Le client semble fonctionner
galement correctement sur Solaris 2.8.

Je vous conseille fortement d'avoir OpenSSL 0.9.7a, ce programme est
trs sensible en termes de scurit (la ngociation SSL s'effectue 
sous root) et OpenSSL a dj connu quelques vulnrabilits, dont 
certaines srieuses.

Vous pouvez choisir de ne compiler que le client (--disable-server),
que le server (--disable-client) ou les deux (par dfaut).

4.1. Compilation du serveur

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

  Les seules options disponibles dans "configure" sont les spcifications des
  rpertoires de base de OpenSSL et de la librairie iconv :

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

  cherchera les bibliothques et enttes dans /usr/local/lib et
  /usr/local/include

  make install

  Installe les fichiers suivants :

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

  Vous trouverez galement dans la distribution :

  - un script server/pppserver.sh qui est  copier dans les rpertoires
    d'initialisation (/etc/rc.d/init.d par exemple sur Redhat) et
     activer (chmod +x, et chkconfig toujours pour Rehdat).
    Sur FreeBSD, le copier dans /usr/local/etc/rc.d

  - un fichier *exemple* du fichier "users",  diter et recopier
    dans /usr/local/etc/ssltunnel/

4.2 Cration des certificats

Je ne veux pas faire un cours SSL ici, il vous faut :

. le certificat public de l'autorit de certification
. un certificat et une cl prive pour le serveur
. un certificat et une cl prive par client.

Tous ces certificats doivent tre des certificats RSA.

Je vous renvoie par exemple  ces sites :
http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/doc/myownca.html
http://www.aboveground.cx/~rjmooney/projects/misc/clientcertauth.html

ou au cours PKI de mon collgue Franck Davy :

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

Leur gnration ne doit pas poser de problmes pour ceux qui ont dj
manipul OpenSSL, notamment avec mod_ssl.

Vous devez avoir 3 fichiers au format PEM du cot serveur :

. Un fichier contenant les CA de confiance ("trusted") : trusted.pem
. Un fichier contenant la cl priv du serveur (server.key)
. Un fichier contenant la cl publique certifie du serveur (server.crt)

4.3 Configuration du serveur

- diter le fichier /usr/local/etc/ssltunnel/tunnel.conf
  . ajuster les chemins des certificats (attention, il est trs important que 
    la cl secrte du serveur ne soit pas lisible par d'autres que root !),
  . ajuster le chemin du fichier users
  . changer l'adresse IP sur laquelle le serveur doit couter (si
    la ligne est commente, il coutera sur toutes). 
  . changer ventuellement le port (non conseill car vous aurez 
    des soucis ensuite pour traverser des relais).

- Le fichier "users" contient les dfinitions des utilisateurs. Chaque bloc
  dfinissant un utilisateur commence par la ligne "user" et se 
  termine par une ligne vide.

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

    ==> contient le DN *COMPLET* du certificat client.
    Ce doit tre la sortie de la commande :
    openssl x509 -nout -subject < client.cert

    ATTENTION : selon les versions d'OpenSSL, la syntaxe du DN peut tre
    lgrement diffrente, surtout pour la partie "Email" (emailAddress dans
    les versions anciennes < 0.9.7).

    Si cela ne fonctionne pas, vrifiez les journaux syslog, la plupart de vos
    ennuis viendront de l. Le nom du certificat client prsent apparat dans
    les journaux.

  . fingerprint : cette ligne est optionnelle et doit contenir l'empreinte
    du certificat client. Si elle est prsente, le certificat client sera
    vrifi contre cette empreinte.

    L'empreinte d'un certificat peut tre obtenu avec la commande : 

    openssl x509 -noout -fingerprint < certificat_client

  . command : /usr/sbin/pppd

    C'est l'emplacement de pppd. 

  . pty 1

    Permet de lancer la cration d'un pty, laisser  1 pour le cas de pppd

  . args

    ventuellement sur plusieurs lignes, contient les arguments passs  pppd.

    Il faut imprativement prciser l'adresse IP locale (avant le :) et 
    celle du client (aprs le :).

    Vous pouvez rutiliser l'adresse d'une autre interface pour l'adresse
    locale, c'est mme conseill. ATTENTION : Vous ne devez pas utiliser
    l'adresse sur laquelle se connecte le client, sinon vous avez un
    problme de poule et d'oeuf, puisque les paquets encapsulant le tunnel
    vont vouloir passer dans le tunnel...

    Si vous faites juste du point  point pour atteindre la machine, deux
    192.168.x.y au hasard iront bien.

    Si vous ne connaissez pas bien pppd, je vous conseille de ne pas toucher
    les autres options. Il peut tre intressant d'ajouter "debug", au moins
    au dmarrage.

    Si vous n'utilisez ni PAP ni CHAP, il faudra mettre l'option "noauth"
    dans /etc/ppp/options, ou crer un fichier /etc/ppp/peers/incoming,
    contenant "auth", et ajouter "call incoming" dans les options PPP.

  . uid et gid

    Permettent de changer d'identit Unix avant de lancer pppd : cela permet
    de rduire les privilges. Attention, il faudra que les utilisateur
    et groupe utiliss aient le droit de lancer pppd ! videmment, cela
    implique aussi que pppd soit setuid root, afin qu'il puisse mettre
    en place les routes, manipuler la table ARP, etc...

    Si ces lignes ne sont pas prsentes, tout s'excutera sous root.

4.4. Lancement du serveur

Pour essayer : 

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

Vrifier que le programme s'est bien lanc, et *LISEZ LES JOURNAUX SYSLOG*.

Par dfaut, pppserver journalise dans local6.* : 

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

La plupart des erreurs vont venir des certificats et du lancement 
de pppd, donc pensez bien  lire les journaux, tout sera dedans.

Vous ai-je dit qu'il fallait lire les journaux ?

4.5 pppwho

Le serveur maintient au format utmp(3) la liste des utilisateurs
connects et la trace des sessions dans /var/log/ssltunnel.wtmp.

Vous pouvez consulter la liste des utilisateurs connects avec la 
commande "pppwho". L'option "-n" permet d'viter la rsolution inverse
des adresses IP des clients, l'option "-a" affiche toutes les sessions, 
y compris celles termines.

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)

La premire colonne est le CN du certificat, la seconde le pid du serveur
grant la connexion, la 3me l'adresse IP du client, et les suivantes la date et
l'heure de dbut de connexion, avec le temps total de la session entre
parenthses.

5. Installation du client
=========================

5.1 Compilation

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

  make install
  installera seulement /usr/local/bin/pppclient

  Si vous aimez les Unix o tout se retrouve dans /usr/bin et
  o find voisine avec Quake, vous pouvez essayer :

  ./configure --prefix=/usr

  (pas de polmique).

  Si vous disposez de la bibliothque iconv dans la libc (systmes GNU) 
  ou installe ailleurs, vous pourrez utiliser des relais authentifiant
  l'utilisateur avec le protocole NTLM (Microsoft ISA Server). Il vous
  faut galement OpenSSL 0.9.7 ou suprieure pour cette fonctionnalit.

  Sous FreeBSD, vous devez installer libiconv et lancer configure avec
  l'option suivante :

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


5.2 Certificats

 Il vous faut :

 . la cl prive du client (client.key)
   Je vous conseille de faire une cl *avec* passphrase, afin
   que le vol de votre portable/machine/serveur ne compromette pas le rseau
   distant.

   Pour gnrer une nouvelle cl avec un mot de passe  partir d'une autre : 

   openssl rsa -out client.key.pass -in client.key -inform pem -passout stdin
   (taper le mot de passe)

   Le mot de passe de la cl sera demand au dmarrage du client.

 . la cl publique certifie du client (client.crt)

 . la liste des CA de confiance (trusted.pem)

5.3 Configuration

Le client (pppclient) possde quelques options sur la ligne de commande,
mais le gros de la configuration s'effectue dans un fichier de 
configuration.

Celui donn en exemple (tunnel.conf) est comment, vous devez changer au
minimum :

. l'adresse IP ou le nom du serveur
. le chemin des certificats sauf si vous avez un login "at" sur 
  votre machine.

Si vous utilisez un relais, vous devez renseigner son adresse IP, son
port, les login et mot de passe ventuels, et ne pas oublier de mettre
le paramtre "userproxy"  1. Si vous utilisez un relais NTLM, le nom
de l'utilisateur doit probablement tre du type "DOMAINE\user".

Je ne vous conseille pas de changer les paramtres "echoint" et "echofail", ils
doivent tre  peu prs les mmes que sur le serveur, sinon il y a un risque
que le serveur continue  fonctionner aprs que le client se soit arrt, en
cas de coupure rseau. En se reconnectant, a peut marcher, mais le serveur
aura probablement des problmes de routage.

Vous pouvez demander au client de se reconnecter automatiquement en cas de
coupure (option autoreconnect), et de travailler en arrire-plan et, dans ce
mode, de journaliser dans un fichier plutt que dans syslog (paramtre
logfile). Tomasera prtend que cette option ne marche pas sous Linux-PPC :)

En avant-plan, le client affiche la taille des paquets mis et reus sur le
terminal.

Remarques :

  . Il faut que le programme ait le droit de lancer pppd. Sur la plupart
    des Unix, il faut tre membre d'un groupe "dialer" ou "network"

  . Il faut que pppd soit setuid root afin que les routes soient mises en
    place. Alternativement, vous pouvez lancer pppclient sous root.

  . Si vous ne voulez/pouvez pas mettre une option "noauth" dans 
    /etc/ppp/options , vous devez crer un fichier /etc/ppp/peers/<peername>
    contenant "noauth", afin que vous ne tentiez pas d'authentifier le serveur.

    <peername> doit alors tre spcifi dans le fichier de configuration :

    peer	<peername>

    Si le systme distant vous demande galement une authentification PAP
    ou CHAP, vous devez galement prciser le nom de l'utilisateur  
    envoyer :

    user	<remoteuser>

    Et remplir galement /etc/ppp/pap-secrets ou /etc/ppp/chap-secrets

    <remoteuser>	*	<password>

Pensez  regarder les journaux pppd s'il ne se lance pas ou que la
ngociation choue.

5.4 Lancement

Pour lancer le programme :

pppclient [-options] <fichier_de_configuration>

Si aucun fichier n'est donn, le client lit ~/.ssltunnelrc.

Un lancement russi doit afficher quelque chose comme a :

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

En thorie, vous avez une interface ppp0 qui est monte, essayez
de "pinger" l'autre extrmit.

Vous avez la possibilit de mettre en place des routes automatiquement,
d'effectuer des actions... quand l'interface PPP est monte, en 
utilisant le script /etc/ppp/ip-up lanc par pppd, auquel est pass
en 6me argument le contenu du paramtre "ipparam".

Voici par exemple le script que j'utilise sous FreeBSD (la syntaxe
de la commande route peut varier).

#!/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

Pour les autres arguments passs  ip-up, voir le man de pppd.

Quelques options sont disponibles en ligne de commande, qui permettent
d'craser les options du fichier de configuration.

-h finalhost : change la destination finale
-p finalport : change le port final
-r proxyname : change le nom du relais
-p proxyport : change le port du relais
-a user-proxy:pass-proxy : authentification sur le relais
-c 0/1 : reconnexion automatique non/oui
-d 0/1 : passage en mode dmon non/oui 
-l logfile : nom du fichier journal en mode dmon

6. Bogues
=========

 Les envoyer (avec le patch :) : <ssltunnel@rominet.net>

7.  Faire
==========

  Voir TODO.

