Easy-to-Use
VPN Connections with vpnd
Bill Davidsen
Because I frequently work over network connections and have helped
various groups set up VPN installations over the open net, I have
been painfully aware that many examples of VPN are complex to install
and require patching the kernel to provide functionality. I was
therefore interested in the vpnd program that is included
with recent Red Hat releases and available in source for any UNIX
distribution. It runs in user mode without kernel patches and is
trivial to set up. In practice, it has proven reliable, even when
used by non-technical users.
Overview of vpnd
A VPN (Virtual Private Network) is a substitute for a dedicated
link between systems. If those connected nodes do routing, then
full seamless connectivity is available. vpnd provides this by sending
network packets in compressed and encrypted form over a socket.
Because it runs in user space without special kernel support, it
is inherently portable. Although I first used it as a Linux solution,
FreeBSD is also supported, and I think Solaris would support this
application as well.
How It Works
A vpnd process is started as a daemon on the server node. This
will listen for connections, by default on port 379. The client
node starts a vpnd process configured as a client, and the two processes
with matching configuration files will be able to connect.
The client and server daemon processes establish an SL/IP link
between the nodes. This link is used to communicate between the
nodes, transparently passing encrypted packets. With suitable routing
support, this can be used as a full connection between the local
networks of each vpnd node, allowing access as if the two local
networks were physically connected through a router.
Configuration Process
Configuration is easy -- only a few lines in a heavily commented
config file need be defined, and most of those have usable optional
values. The client and server configuration are almost identical,
and for each server a key must be generated once on the server and
installed on both the server and client machine(s). For the simple
case of one client connecting to one server, all the files may be
left in their default locations, and most of the default values
will work without change.
Server Configuration
For this example server, which is used in several ways, I changed
only nine values in the config file, and for some of those the default
value would have worked. The full list of changes, shown as a diff
file between the sample and what I actually run, is shown in Figure
1. Following is the list of things I changed on the server and a
discussion of each change. For quick reference, just the list of
parameters defined appears in Figure 2, showing how little configuration
is actually needed with this software.
This is what I changed:
+ pidfile /var/run/vpnds1.pid -- The pidfile is a file
containing the PID of the process running vpnd. If you don't define
this value, no file will be created. However, I wanted to be able
to track the daemon easily, so I specified a file in /var/run. This
file is deleted when the daemon terminates.
+ randomdev /dev/urandom -- This is the name of the device
that provides random numbers to the encryption. The default value
of /dev/random will work, but on a lightly used system may be very
slow, because it generates data based on system events. There is
a discussion of security and devices in both the documentation README
file and the config file comments (this software is very well documented).
+ keepalive 20 and + noanswer 6 -- These parameters
control how often the daemon sends a keepalive ping to the client
and how many pings must go unanswered before the connection is declared
dead. The client is expected to reestablish the connection when
(or if) it dies, and there is a discussion of this process in the
documentation as well. The default values may be appropriate for
a dialed connection between modems, but I felt they were overly
paranoid and might reset when network congestion introduced a temporary
problem.
The keepalive is the time in seconds between pings, and the noanswer
value is the number of unanswered pings that cause a connection
reset. This server has a dedicated connection and rarely goes away,
so I didn't want to dedicate much bandwidth to pings. When a failure
occurs, it's usually caused by broken lines or cars trying to climb
utility poles. In those cases, the outage will be hours rather than
seconds, so a speedy retry is unlikely to be beneficial.
+ mode server -- The mode setting must be either client
or server. This controls which branch of the setup code is used.
+ client 0.0.0.0 0 -- This setting is required, as is the
IP and port number of the client. If they are set to zero, any connection
is accepted. This setting allows the server to accept connections
from a single static IP address -- better than nothing if no firewall
is being used, and useful if a server is to be dedicated to a single
client. By setting the IP zero and the port to a known value, a
small degree of additional security is available even when the client
is using an unknown IP, such as DHCP-assigned connections.
+ server 0.0.0.0 24741 -- In this case, I have my server
listening on any IP address, on port 24741. The default port is
379, and in most cases is satisfactory; the port chosen is an example
only. It might be used to run the daemon as a non-privileged user;
I have not tested doing that, but it appears to be possible.
Note that if an IP is given, it is possible to listen on a single
address rather than on all configured IP addresses. This may be
useful if several servers are configured against IP addresses provided
by aliases on a single physical network device, or if there are
addresses on several subnets, each on a separate network interface.
+ keyfile /etc/vpnd/vpnd.conf-server1 -- The keyfile holds
the key used to start the connection. There is a default location,
and it is perfectly satisfactory for most applications. The server
I used for this article actually supports several vpnd configurations,
so all config files were moved to /etc/vpnd and given more descriptive
names.
+ local 192.168.202.2 -- This is the address of the local
end of the SL/IP link. It should be chosen to avoid conflict with
any other IP addresses in use at either end. If the connection is
made over a network connection, it should not be the IP configured
on an NIC at either end.
+ remote 192.168.202.1 -- This is the IP of the "other
end" of the SL/IP link. The local and remote IP addresses are swapped
between the client and server, since the client "local" is the server
"remote" and vice versa.
Routing on Startup
If the VPN connection is only to be used as a link between two
systems, the route to the remote system will be created by the kernel
(Linux 2.2 or later, or FreeBSD). If additional routing is needed,
up to nine additional routes may be specified in the configuration
file created when the link is established. Note that adding routes
requires root privilege; if you want to try running this as a normal
user, this feature will not be available. Also see the section on
startup scripts in the client configuration.
The format of a route directive is:
# route1 <destination-ip> <netmask-in-dot-notation> <gateway-ip>
where route1 to route9 commands may be included in the config file.
This can be used for individual hosts, or more commonly for a subnet.
In the case of the server used, for example:
route1 192.168.203.0 255.255.192.0 192.168.202.1
This says I routed through the VPN to 192.168.203.0 through 192.168.203.63,
a 6-bit subnet. If I want to route an entire class C (old nomenclature)
network, it might look like:
route2 192.168.202.0 255.255.255.0 192.168.202.1
Hosts with individual routes, such as the ends of the SL/IP link,
would still be routed individually.
Client Configuration
The client configuration can be almost identical to the server,
other than setting the mode to client and interchanging the
values of the local and remote IP address definitions.
The values defined for the example client configuration are shown
in Figure 3.
There are two differences between these client settings and the
server settings previously discussed, besides the required changes
already noted. The first change is that I now provide the IP of
the server to which I need to connect, instead of providing zeros.
The server IP value on the server itself is the IP on which the
server listens, with zeros meaning "any". On the client, however,
it is the IP to which the daemon connects. Note that the IP shown
has been munged to avoid accidental use of the example server.
The second change is the use of the linkup directive to
identify a script that needs to be run when the link starts. In
this case, the script contains a complex routing setup, which can't
be handled by the simple route statements I described earlier.
The linkup script can perform any initialization required, not
just routing. In the case of a "moving target", such as a laptop
going to various locations, the startup might involve fetching any
mail waiting and sending any mail queued for the home office. It
could also include some backup of critical files, updates of shared
calendars, or anything else needed. There is a corresponding linkdown
parameter used when the link is terminated.
Other Features
There are some advanced features that I should mention, which
make vpnd even more versatile. These are useful for applications
where the VPN cannot be established over an available network connection
and a dialed connection must be used, or where there are some other
special problems or data content on the link.
Use Between Dial-Up Sites
While connection via dialed circuit is growing less common, vpnd
does support dial or direct connected serial cable use. In the case
where a serial connection is used, with or without a modem, the
IP address in the client and server specifications is replaced with
a device name, which is the device name of the serial port.
These are most of the features needed for establishing a dialed
connection.
+ slipup <name> and + slipdown <name>
-- These are the names of scripts to be run when the connection
is established or terminated.
+ speed <serial bitrate> -- This sets the speed of
the serial line, which defaults to 115200. Clearly this isn't magic,
the hardware and driver must support the speeds selected.
+ localline and + nortscts -- These disable modem
control hardware signaling, and RTS/CTS flow control, respectively.
Use nortscts with care on a direct connect; data loss is
possible, particularly at speeds higher than 115200.
+ xfilter -- This escapes flow control characters XON and
XOFF. It's used primarily when a modem or other part of the communication
link responds to this as flow control.
+ modemchat <script> -- This defines a chat file
to be used to establish modem state. There is a well-commented example
file in the package, which should be adequate to provide connectivity
with many modems using the AT command set.
Tuning the Connection
There are a few parameters that allow tuning the connections to
optimize the behavior for various types of traffic. These are a
few of the parameters that are generally useful.
+ ipopts <type-of-service-and-precedence-flags> --
An optional specification. This is described in the comments as
a combination (sum of values used) of the following values:
1 high reliability type of service
2 high throughput type of service
4 low delay type of service
8 priority precedence
The comments also contain this warning: Please keep in mind that
nearly all routers do ignore these settings so except for very special
environments you won't gain anything.
+ sendbuf <size> -- The send buffer is used for data
compression. Making this buffer larger, perhaps 4K, will help throughput
if the connection is slow, such as a modem link. It is unlikely
to help if you are moving a lot of compressed data, because it won't
compress further in most cases. If you are running an X session
over a slow link, this may make a great improvement.
Security
All data is encrypted in the VPN. The common key is used only
to establish a session key, which is then used for the actual traffic.
The length of the key may be set by user option, and the encryption
is done using the blowfish algorithm.
By default, the shared key is stored unencrypted in a file readable
only by root. The author of the package notes that when someone
has root privileges, they can grab the unencrypted packets as well,
but there is an optional method that stores the key encrypted and
uses strong authentication between the client and server to establish
mutual trust. The drawback is that a transaction number is part
of the key, and it is possible for the client and server to have
different ideas of this value after a disconnect. Additionally,
it requires a separate server for each client, rather than allowing
multiple clients to connect to a single server.
Like everything else in this package, the theory of the encrypted
key method is described in detail a cryptographer could love. There
are also some options to drop the connection if certain delays are
noted and to control how often a new random key is generated. These
features, used with the encrypted shared key, appear to provide
protection against all but the most serious attacks.
Because interactive connections using ssh work through the VPN,
and other secure bulk transfers can be used, such as scp or encrypting
data before transmission, the security of the data in transit also
appears to be adequate for commercial use.
Experience and Warnings
I tried this setup because I was tired of patching things into
Linux kernels, and because I only needed to connect Linux machines
and didn't need to use some standard protocol to talk to Windows,
Cisco routers, or any of the other nodes that want a standard protocol
like PPPoE. In meeting those goals, this system has worked extremely
well. It has produced no unexpected behavior, even in the face of
very bad dialed connections. The transfer rate is acceptable, it
hasn't complained when moving compressed data, and it has no interaction
with ssh, which also encrypts its connection. I was able to run
PPPoE through such a connection, but only as a proof of concept,
so I can't speak to the throughput.
Setup has been easy. I have talked people through it over the
phone, which I would rather not do but occasionally must, and the
setup files are human readable. I recommend it for connections between
UNIX systems as a reliable and easy-to-install VPN solution.
Bill Davidsen has been doing systems programming and administration
since 1968, and was one of the founders of TMR Associates in 1979.
In addition to being "part-time CTO" at TMR, he works as a project
leader with a national ISP and writes an Internet column.
|