Hack #105. Tunnel PPP

Use PPP and SSH to create a secure VPN tunnel.

There are so many options to choose from when creating a VPN or tunneled connection that it’s mind-boggling. You might not be aware that all the software you need to create a VPN—namely, PPP and SSH daemons—is probably already installed on your Unix machines.

If you used PPP back in the day to connect to the Internet over a dial-up connection, you might be wondering how the same PPP can operate over SSH. Well, when you used PPP in conjunction with a modem, it was talking to the modem through what the operating system presented as a TTY interface, which is, in short, a regular terminal device. The PPP daemon on your end sent its output to the TTY, and the operating system then sent it out via the modem; it then traveled across the telephone network until it reached the remote end, where the same thing happened in reverse.

The terminals on which you run shell commands (e.g., the console or an xterm) use pseudo-TTY interfaces, which are designed to operate similarly to TTYs. Because of this, PPP daemons can also operate over pseudo-TTYs. So, you can replace the serial TTYs with pseudo-TTYs, but you still need a way to connect the local pseudo-TTY to the remote one. Here’s where SSH comes into the picture.

You can create the actual PPP connection in one quick command. For instance, if you want to use the IP address 10.1.1.20 for your local end of the connection and 10.1.1.1 on the remote end, run a command similar to this:

# /usr/sbin/pppd updetach noauth silent nodeflate \ 
            pty "/usr/bin/ssh root@colossus /usr/sbin/pppd nodetach notty noauth" \ 
            ipparam 10.1.1.20:10.1.1.1
root@colossus's password:
local  IP address 10.1.1.20
remote IP address 10.1.1.1

The first line of the command starts the pppd process on the local machine and tells it to fork into the background once the connection has been established (updetach). It also tells pppd to not do any authentication (noauth), because the SSH daemon already provides very strong authentication, and turns off deflate compression (nodeflate).

The second line of the command tells pppd to run a program and to communicate with it through the program’s standard input and standard output. This is used to log into the remote machine and run a pppd process there. Finally, the last line specifies the local and remote IP addresses that are to be used for the PPP connection.

After the command returns you to the shell, you should be able to see a ppp interface in the output of ifconfig:

$ /sbin/ifconfig ppp0
ppp0      Link encap:Point-to-Point Protocol  
          inet addr:10.1.1.20  P-t-P:10.1.1.1  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:58 errors:0 dropped:0 overruns:0 frame:0
          TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3 
          RX bytes:5372 (5.2 Kb)  TX bytes:6131 (5.9 Kb)

Now, try pinging the remote end’s IP address:

$ ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=4.56 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=4.53 ms
64 bytes from 10.1.1.1: icmp_seq=3 ttl=64 time=5.45 ms
64 bytes from 10.1.1.1: icmp_seq=4 ttl=64 time=4.51 ms

--- 10.1.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3025ms
rtt min/avg/max/mdev = 4.511/4.765/5.451/0.399 ms

And finally, the ultimate litmus test—actually using the tunnel for something other than ping:

$ ssh 10.1.1.1
The authenticity of host '10.1.1.1 (10.1.1.1)' can't be established.
RSA key fingerprint is 56:36:db:7a:02:8b:05:b2:4d:d4:d1:24:e9:4f:35:49.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.1.1.1' (RSA) to the list of known hosts.
andrew@10.1.1.1's password: 
[andrew@colossus andrew]$

Before deciding to keep this setup, you might want to generate login keys to use with ssh [Hack #97], so that you don’t need to type in a password each time. In addition, you might want to create a separate user for logging in on the remote machine and starting pppd. However, pppd needs to be started as root, so you’ll have to make use of sudo [Hack #6]. Also, you can enable SSH’s built-in compression by adding a -C to the ssh command. In some circumstances, SSH compression can greatly improve the speed of the link. Finally, to tear down the tunnel, simply kill the ssh process that pppd spawned.

Although it’s ugly and might not be as stable and full of features as actual VPN implementations, the PPP and SSH combination can help you create an instant encrypted network without the need to install additional software.