June 12, 2006

Creating virtual private networks with tsocks and VTun

Author: Marc Abramowitz

Virtual private networks (VPN) let remote users connect back to corporate networks over encrypted links. Many VPNs are built with proprietary technology and can be tricky and expensive to set up. For a small business or an individual who needs a simple way to securely access remote networks, setting up a true VPN might be prohibitively expensive in terms of both money and time. Let's look at two simple approaches that bring you transparency without the cost. All you need is Secure Shell (SSH) access to a server on the network you're trying to access.

SSH, a simple and common way to access remote networks without a VPN, can be used to get a command prompt on a remote machine. Through SSH extensions such as Secure File Transfer Protocol (SFTP) and Secure Copy (SCP), you can transfer files to and from a remote machine.

A technique known as port forwarding or SSH tunneling opens up even more possibilities. For example, you could set up a port forward for accessing an Internet Message Access Protocol (IMAP) server, Virtual Network Computing (VNC) server, or Web proxy that is behind a firewall. OpenSSH even allows you to create a DynamicForward, which essentially acts as a SOCKS proxy. The nice thing about this feature is that you can tunnel a variety of services over a single secure port and connection. The drawback, however, is that the proxying is not transparent to the client. All client programs that need access to services behind the firewall need to be configured to use the proxy. That means that you have to go into all of your Web browsers, email clients, VNC clients, and so on and configure them to use the proxy -- and not necessarily all programs support proxies. For example, recently I tried to use Evolution on my home Linux machine to access my IMAP server at work and found that I could not get it to work through a proxy. Furthermore, once you've set up all your programs to use a proxy, what do you do when the proxy is no longer available? You have to disable that proxy in all your client programs.

Ideally, you'd have a transparent way to securely access services on a protected remote network. You don't want to have to configure every client program separately. The beauty of VPNs is that they do exactly that -- once you're connected, applications just work, with no extra configuration.

The Transparent SOCKS proxying library

The Transparent SOCKS (tsocks) proxying library is a simple piece of software that builds on the SOCKS proxy approach with some clever tricks to make access more transparent and easy. It allows non-SOCKS-aware applications to use SOCKS proxies by intercepting the calls that applications make to networking code and routing the traffic through a SOCKS server as necessary. You don't need to understand exactly how this is accomplished, but if you're interested and you understand a bit about Unix programming, the short explanation is that tsocks provides a shared library with alternative implementations of the BSD socket functions, and it uses the LD_PRELOAD environment variable to force applications to use the new socket functions.

Before you try to use tsocks, you need to fire up an SSH tunnel for tsocks to use:

 $ ssh -D 1080 remoteuser@host1.firewalleddomain.net 

This creates a SOCKS 4 server on the remotehost.com, which you can access at port 1080 on the local machine. You could simplify this previous command by putting directives in your ~/.ssh/config file; check out the man page for ssh_config for more details.

Installing and using tsocks on my Ubuntu Linux machine was a snap. First, I installed the package using apt-get, then edited my /etc/tsocks.conf file:

path {
        reaches =
        server =
        server_type = 4
        server_port = 1080

This simple configuration tells tsocks to route all traffic destined for 207.126.239.x to a SOCKS 4 server on (the localhost, port 1080). Of course, you will have to change the "reaches" parameter to match the IP address and netmask of the network you're trying to access.

If you have a more complex setup, chances are that tsocks can handle it. You can specify multiple paths in the tsocks.conf file, as well as a default SOCKS server, for addresses that don't match any of the listed paths. You can also provide a "local" directive that specifies local networks that tsocks should never use a proxy for. For example, a suitable "local" specification for my home network (and many other home networks) would be local =

You can use tsocks in two ways. The simplest way is to simply preface your commands with "tsocks":

$ tsocks ssh host1.firewalleddomain.net
$ tsocks evolution
$ tsocks firefox

However, this method is not exactly transparent, and you can easily forget. The following alternative way of using tsocks is more convenient:

$ source /usr/bin/tsocks on
$ ssh host1.firewalleddomain.net
$ evolution
$ firefox
$ source /usr/bin/tsocks off

While tsocks is turned on, you can access the remote network transparently and run applications as you usually do.

Virtual Tunnel

Virtual Tunnel (VTun) is a more complex solution, but it creates more of a VPN-like experience. Whereas tsocks relies on environment variables that are local to each process on the system, using VTun involves loading a kernel module and modifying the system IP routing table. Using VTun, you can create a virtual network interface through which IP traffic destined for the remote private network is routed. Individual applications need to know nothing of the virtual network interface or the system IP routing tables.

To illustrate, I'll show you how I set up VTun to securely access my home network. Only the SSH port (port 22) is open to the outside. All traffic is tunneled through SSH encrypted.

First, I opened an SSH tunnel to my home Linux server. Both the VTun client and server were configured to use port 9000, so I set up port 9000 on the client machine to forward (through SSH) to port 9000 on my home Linux server:

 client:$ ssh -L 9000:localhost:9000 marc@server 

Then I started a VTun server on my home Linux server:

 server:$ sudo vtund -n -s -f vtund-server.conf 

The vtund-server.conf file that I used is here.

The -n option tells vtund not to daemonize, which makes debugging easier since messages will be logged to the console. The -s option tells vtund to act as a server. The -f option specifies that vtund-server.conf is the configuration file to use. If you get an error about the "tun" kernel module not being loaded, then you may need to load the module using modprobe or insmod on a Linux system or kldload on a FreeBSD system.

Then I started a VTun client on the client machine:

 client:$ sudo vtund -n -f vtund-client.conf my_tunnel localhost 

The vtund-client.conf file that I used is here.

Again, if the "tun" kernel module is not loaded, you may need to preface this by loading the kernel module, as mentioned in the previous paragraph.

The effect of all of this is that I created a sort of virtual private peer-to-peer network with an address of 10.3.0 and these mappings:

Address Hostname server client

Each machine still belongs to the physical network(s) that they belonged to before. They now also belong to this additional private network. Ordinarily, a machine with one network adapter can only belong to one network. However, in this case, VTun makes use of a virtual "tun" adapter that the "tun" kernel module creates. This allows each machine to simultaneously exist on a physical network (via the physical network adapter) and a virtual network (via the "tun" virtual network adapter). A machine that exists on more than one network is in effect a router, and thus directing traffic properly requires modifying the network route tables. Lines in the VTun configuration files automatically create the routes when the VTun client connects to the VTun server. You can see the evidence of this by looking at the network route tables on both machines:

client:$ netstat -r | grep tun            UH          0       78   tun0
server:$ netstat -r | grep tun        *      UH        0 0          0 tun0

The minor differences in the format of the netstat output between the two machines are due to the fact that my client is running FreeBSD and my server is running Linux.

At this point, the two machines are connected and act as if they are on the same network. Thus, on the client you can connect to the server:

 client:$ ssh 

You can also connect from the server to the client:

 server:$ ssh 

If you run into problems, good commands to use for troubleshooting are netstat -r, route, tracepath, and traceroute.

I've only discussed connecting two machines, one on each network. If more machines are involved, then things get a bit more complex, because all of the involved machines will need proper entries in their route tables, and the VTun machines will need to act as gateways, forwarding network traffic between their interfaces and doing network address translation. Configuring gateways is beyond the scope of this article -- the following resources might be helpful:

Tsocks and VTun are by no means the only programs available that do virtual private networking. Other programs that you may want to have a look at include OpenVPN and Hamachi.

Click Here!