# $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-.tar.gz cd ssltunnel- ./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/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-.tar.gz cd ssltunnel- ./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/ file containing "noauth", so that you do not try to authenticate the server. must then be specified in the configuration file: peer If the remote system also asks you a PAP or CHAP authentification, you must also specify the user name to be sent: user And also fill /etc/ppp/pap-secrets or /etc/ppp/chap-secrets * 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] 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 :) : 7. To do ======== See TODO.