# $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 encapsulée dans SSL. Cela permet de faire un VPN du pauvre entre deux machines Unix ou entre deux réseaux, sans nécessiter de mettre en place une technologie IPsec. 2. Pourquoi ? ============= Pour une raison simple : je me déplace souvent, et je n'ai bien souvent, dans un hôtel ou dans un réseau d'entreprise, qu'un accès 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 réseau. J'ai pendant longtemps utilisé PPP sur SSH, même 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 problèmes : . ce n'est pas du SSL, et certains relais HTTPS commencent à vérifier que ce qui les traverse est bien du SSL. . il demande forcément d'avoir un compte Unix à l'autre bout, ce qui n'est pas forcément idéal pour la gestion des authentifications J'ai donc décidé d'écrire un tunnel "PPP dans SSL", en utilisant bien évidemment OpenSSL. J'aurais pu faire une bidouille avec stunnel, mais j'ai préféré 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 vérifier si c'est une session navigateur <-> serveur Web HTTPS, car le début de la session non chiffrée et la négociation SSL sont exactement identiques) ; - A l'établissement de la connexion, le serveur "forke" ; - le serveur envoie son certificat, le client vérifie qu'il est bien signé par une autorité à laquelle il fait confiance ; - le client envoie son certificat ; - le serveur vérifie ce certificat et cherche s'il correspond à un certificat déclaré dans sa base ; - la session chiffrée commence ; - le serveur envoie sa bannière avec son numéro de version et sa version de protocole ; - le client reçoit la bannière, vérifie et envoie la sienne ; - le client "forke", ouvre un pty, lance pppd en mode client sur ce pty, sans préciser quelle adresse IP il veut ; - le serveur récupère les paramètres PPP dans le fichier utilisateurs, change d'identité, ouvre un pty, "forke" et lance pppd sur ce pty avec les options données par le fichier ; - la session PPP s'établit entre les deux extrémités, le programme à chaque bout chiffre/déchiffre et lit/envoie les données 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 très sensible en termes de sécurité (la négociation SSL s'effectue sous root) et OpenSSL a déjà connu quelques vulnérabilités, dont certaines sérieuses. Vous pouvez choisir de ne compiler que le client (--disable-server), que le server (--disable-client) ou les deux (par défaut). 4.1. Compilation du serveur tar xvfz ssltunnel-.tar.gz cd ssltunnel- ./configure --disable-client make Les seules options disponibles dans "configure" sont les spécifications des répertoires de base de OpenSSL et de la librairie iconv : ./configure --with-openssl=/usr/local --with-iconv=/usr/local cherchera les bibliothèques et entêtes 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 répertoires 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 Création 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é privée pour le serveur . un certificat et une clé privée 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 collègue Franck Davy : http://www.hsc.fr/ressources/cours/pki/index.html.fr Leur génération ne doit pas poser de problèmes pour ceux qui ont déjà 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 certifiée 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 très important que la clé secrète 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 commentée, 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 définitions des utilisateurs. Chaque bloc définissant 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 légèrement différente, surtout pour la partie "Email" (emailAddress dans les versions anciennes < 0.9.7). Si cela ne fonctionne pas, vérifiez les journaux syslog, la plupart de vos ennuis viendront de là. Le nom du certificat client présenté apparaît dans les journaux. . fingerprint : cette ligne est optionnelle et doit contenir l'empreinte du certificat client. Si elle est présente, le certificat client sera vérifié 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 création d'un pty, laisser à 1 pour le cas de pppd . args Éventuellement sur plusieurs lignes, contient les arguments passés à pppd. Il faut impérativement préciser l'adresse IP locale (avant le :) et celle du client (après le :). Vous pouvez réutiliser l'adresse d'une autre interface pour l'adresse locale, c'est même conseillé. ATTENTION : Vous ne devez pas utiliser l'adresse sur laquelle se connecte le client, sinon vous avez un problème 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 intéressant d'ajouter "debug", au moins au démarrage. Si vous n'utilisez ni PAP ni CHAP, il faudra mettre l'option "noauth" dans /etc/ppp/options, ou créer 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 réduire les privilèges. Attention, il faudra que les utilisateur et groupe utilisés 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 présentes, tout s'exécutera sous root. 4.4. Lancement du serveur Pour essayer : /usr/local/libexec/pppserver /usr/local/etc/ssltunnel/tunnel.conf Vérifier que le programme s'est bien lancé, et *LISEZ LES JOURNAUX SYSLOG*. Par défaut, pppserver journalise dans local6.* : touch /var/log/ssltunnel.log echo "local6.debug/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 connectés et la trace des sessions dans /var/log/ssltunnel.wtmp. Vous pouvez consulter la liste des utilisateurs connectés avec la commande "pppwho". L'option "-n" permet d'éviter la résolution inverse des adresses IP des clients, l'option "-a" affiche toutes les sessions, y compris celles terminées. 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 première colonne est le CN du certificat, la seconde le pid du serveur gérant la connexion, la 3ème l'adresse IP du client, et les suivantes la date et l'heure de début de connexion, avec le temps total de la session entre parenthèses. 5. Installation du client ========================= 5.1 Compilation tar xvfz ssltunnel-.tar.gz cd ssltunnel- ./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 polémique). Si vous disposez de la bibliothèque iconv dans la libc (systèmes GNU) ou installée 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 supérieure 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é privée 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 réseau distant. Pour générer 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 démarrage du client. . la clé publique certifiée du client (client.crt) . la liste des CA de confiance (trusted.pem) 5.3 Configuration Le client (pppclient) possède 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 paramètre "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 paramètres "echoint" et "echofail", ils doivent être à peu près les mêmes que sur le serveur, sinon il y a un risque que le serveur continue à fonctionner après que le client se soit arrêté, en cas de coupure réseau. En se reconnectant, ça peut marcher, mais le serveur aura probablement des problèmes de routage. Vous pouvez demander au client de se reconnecter automatiquement en cas de coupure (option autoreconnect), et de travailler en arrière-plan et, dans ce mode, de journaliser dans un fichier plutôt que dans syslog (paramètre logfile). Tomasera prétend que cette option ne marche pas sous Linux-PPC :) En avant-plan, le client affiche la taille des paquets émis et reçus 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 créer un fichier /etc/ppp/peers/ contenant "noauth", afin que vous ne tentiez pas d'authentifier le serveur. doit alors être spécifié dans le fichier de configuration : peer Si le système distant vous demande également une authentification PAP ou CHAP, vous devez également préciser le nom de l'utilisateur à envoyer : user Et remplir également /etc/ppp/pap-secrets ou /etc/ppp/chap-secrets * Pensez à regarder les journaux pppd s'il ne se lance pas ou que la négociation échoue. 5.4 Lancement Pour lancer le programme : pppclient [-options] Si aucun fichier n'est donné, le client lit ~/.ssltunnelrc. Un lancement réussi 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 théorie, vous avez une interface ppp0 qui est montée, essayez de "pinger" l'autre extrémité. Vous avez la possibilité de mettre en place des routes automatiquement, d'effectuer des actions... quand l'interface PPP est montée, en utilisant le script /etc/ppp/ip-up lancé par pppd, auquel est passé en 6ème argument le contenu du paramètre "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 passés à 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 démon non/oui -l logfile : nom du fichier journal en mode démon 6. Bogues ========= Les envoyer (avec le patch :) : 7. À Faire ========== Voir TODO.