Archived | Using the GNU Virtual Private Ethernet
Secure connectivity over private and public networks
Traditional Virtual Private Network solutions
Most traditional VPN solutions work by supporting a single connection. That connection may be from your desktop computer to your office, which may then be limited to support only a select range of transport protocols, such as TCP and/or UDP based communication.
Supporting a single connection, or even a network and routed connection is fine, but the system gets more complicated as you try to add more hosts and/or more networks to the system. For example, providing a VPN solution that goes across multiple hosts and multiple networks, and that provides communication over a range of different underlying protocols can be both complicated and resource hungry, as well.
A simple example of this can be seen in Figure 1. When using a normal VPN solution, routing between VPN Client 1 and VPN Client 2 would only be possible by routing all of the network traffic through the VPN Host. This would be expensive, especially if the individual hosts were all on the same network, or communicating over public interfaces like the Internet.
Figure 1. Typical VPN solution
The protocol limits are fine if the applications that you want to use are TCP or UDP-based. For situations where you have to access the company intranet (HTTP), or mail service (IMAP, SMTP) these limitations are not an issue. But there are limitations to the routing and protocol support within a VPN solution.
Enter the GNU Virtual Private Ethernet
The GNU Virtual Private Ethernet enables you to configure and build an entirely virtual network over multiple hosts. Unlike the point-to-point approach of a typical VPN, with GVPE you can set up as many hosts as you like to be part of the virtual network, and hosts can be brought up and down whenever you like.
Although it won’t be covered in detail in this article, GVPE can also work through non-traditional connections methods. For example, you can route the network traffic that supports the virtual network over native IP, HTTP (including through a proxy), DNS and ICMP. You can use this to build a virtual network between computers that are limited internally to connect to the outside world through an HTTP proxy, through to devices outside the public network.
The network interface created by GVPE is also a generic network device, so you can route non-IP protocols over the connection. In addition, the information sent on the virtual network is automatically routed to the right host and configured within the virtual network, as shown here in Figure 2.
Figure 2. VPN solution using GVPE
In comparison to the traditional VPN, the routing and distribution of packets is much more flexible. More importantly, because the communication between the hosts can be over and through a variety of different transport protocols, GVPE can be used to create a virtual network that exists on hosts on public clouds, like Amazon EC2 and the IBM Cloud, internal cloud and grid solutions, and desktops and clients. You can see this in Figure 3.
Figure 3. Creating a virtual network over public and private networks
For convenience, the configuration information for all the hosts within the virtual network is shared, making setup and extension of the configuration very easy.
The security of GNU Virtual Private Ethernet is handled through the OpenSSL libraries, using the public/private key mechanism. Each host within the virtual network is provided with a unique host key and the public version is used to encrypt the communication channel.
Meanwhile, as the virtual private network is based around supporting and Ethernet-level network environment, each host is also provided with a unique MAC address, just as it would exist on a native Ethernet network. This means that you can verify the source of the information by using the MAC address of the sender (and the recipient, if necessary), providing an additional level of security.
However, for simplicity and speed, the authentication and set up of the secure network is handled only through the public/private keys, rather than through the a typical password or challenge response mechanism. This means that you can set up and enable a GPVE installation during boot time, allowing the virtual network to be recreated even in the event of a failure or reboot, without having to manually set up the connection.
GVPE works on Linux® and many UNIX® distributions, although you may need to install additional networking drivers required to support the creation of a dynamic network device. You can check the
gvpe.osdep man page for more information on enabling this service on various platforms, including Solaris, Mac OS X and Windows® (using
cygwin). For the purposes of this installation, we will use Linux.
Before you install GVPE, you must make sure that your kernel has been configured to include the TUN/TAP network kernel drivers. You’ll need to enable this in your kernel configuration. A number of desktop Linux installations, including Debian/Ubuntu and Fedora may already have the TUN/TAP drivers enabled.
You will also need to have OpenSSL and the OpenSSL headers/library installed for the installation to continue. In addition, before you install, you should make some decisions about the encryption and digest methods you want to use, and what is supported by your OpenSSL installation.
GVPE supports the aes-128, aes-192, aes-256 and bf (blowfish) ciphers, and the sha512, sha256, sha1, ripemd160, md5 and md4 digest algorithms.
You can determine the list of ciphers and message digest formats supported by using
openssl help, as shown here in Listing 1.
Listing 1. Help with OpenSSL
$ openssl help openssl:Error: 'help' is an invalid command. Standard commands asn1parse ca ciphers crl crl2pkcs7 dgst dh dhparam dsa dsaparam ec ecparam enc engine errstr gendh gendsa genrsa nseq ocsp passwd pkcs12 pkcs7 pkcs8 prime rand req rsa rsautl s_client s_server s_time sess_id smime speed spkac verify version x509 Message Digest commands (see the 'dgst' command for more details) md2 md4 md5 mdc2 rmd160 sha sha1 Cipher commands (see the 'enc' command for more details) aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb aes-256-cbc aes-256-ecb base64 bf bf-cbc bf-cfb bf-ecb bf-ofb camellia-128-cbc camellia-128-ecb camellia-192-cbc camellia-192-ecb camellia-256-cbc camellia-256-ecb cast cast-cbc cast5-cbc cast5-cfb cast5-ecb cast5-ofb des des-cbc des-cfb des-ecb des-ede des-ede-cbc des-ede-cfb des-ede-ofb des-ede3 des-ede3-cbc des-ede3-cfb des-ede3-ofb des-ofb des3 desx idea idea-cbc idea-cfb idea-ecb idea-ofb rc2 rc2-40-cbc rc2-64-cbc rc2-cbc rc2-cfb rc2-ecb rc2-ofb rc4 rc4-40 rc5 rc5-cbc rc5-cfb rc5-ecb rc5-ofb
Note that not all of the digest and ciphers here are supported, but your OpenSSL must support the cipher and digest that you want to use.
You set the digest by using the
--enable-digest option to the configure script, and the cipher to use for
--enable-cipher. If you don’t specify this, the
ripemd160 digest and
aes-128 cipher will be used.
You also need to decide where you want to install gvpe and the gvpe configuration files. The default prefix is /usr/local (this places commands in /usr/local/bin and looks for configuration in /usr/local/etc/gvpe).
Once you have made these decisions, do the following to compile and install GVPE:
- Download the gvpe package.
Extract the gvpe package:
$ tar zxf gvpe-2.2.tar.gz
Change into the gvpe-2.2 directory:
$ cd gvpe-2.2
Run configure to set the options you want to use:
$ configure --prefix=/usr/local --enable-digest=sha512 --enable-cipher=aes-256
$ make install
The installation copies over the commands and documentation. The configuration file needs to be setup uniquely for each system.
Setting up a virtual network
To set up a virtual network, you need to perform the following six steps. You can do this for as many machines as you like, although for the purposes of the demonstration, you will initially setup a solution for only two machines to share a virtual network.
- Configuration script
- Creating the public/private keys
- Create a script to setup the network on each host
- Copy the configuration to each machine
- Set the hostkey for each machine
- Start gvpe
Each step will be described individually.
The configuration file is the core for the entire configuration and structure. The configuration file will be shared by all the machines in the network, as it will be used by each machine to understand the layout and makeup of the virtual network.
For each host in the network you need to set only two values, the name of the node (which identifies the host within the virtual network) and the hostname or communication target that will be used as the public transport for communicating with that host. Initially, we’ll assume we have access to a standard TCP/IP network.
The first part of the file specifies global options that will be used by all the nodes, then you specify the options for each individual node. An example configuration file, which should be called gvpe.conf, is shown in Listing 2.
Listing 2. The gvpe.conf configuration file
# Specify the use of UDP and the default port enable-udp = yes udp-port = 407 # Set the name of the virtual device created ifname = vpn0 # Set the first node node = private1 hostname = 192.168.1.20 # Set the second node node = private2 hostname = remote.example.com
This sets the first node, private1, and specifies an IP address (in this case on a local network). For the second node, a hostname is used, and the IP address of the host is resolved when GVPE is started.
The global options set the use of UDP, the UDP port, and configure the name of the virtual device that will be created. For convenience, we’ve set the device name to be vpn0. This is the name that will exist in /dev or from the output from
ifconfig, and is needed to configure the virtual network device and routing.
Creating the public/private keys
The public/private keys need to be created for each host. They will be used both for encryption and identification of the hosts. You can do this automatically using the control command, gvpectrl:
$ gvpectrl -c /usr/local/etc/gvpe -g.
This creates two directories in the configuration directory. The hostkeys directory contains the hostkey (private) information for each host. The pubkeys directory contains the publickey for each host.
The pubkeys must be copied to every host in the virtual network, as each host will need them to communicate. The hostkeys are only needed on each specific host. That is, the private1 hostkey (which will be located in hostkeys/private1) will only need to be copied to the host that is acting as private1 in the virtual network.
Network initialization script
When the virtual network is created on each host, the newly created network device will need to be configured with an IP address, and the routing will need to be configured so that data can be routed from one machine to another.
When gvpe is started on each machine, it runs the if-up script (short for interface up) to set up the virtual interface. In doing so, it supplies some standard shell environment variables that can be used in the script to set the information (such as identifying the nodename, interface name, and the gvpe generated MAC address).
You can see a sample if-up script in Listing 3 below.
Listing 3. A sample if-up script
#!/bin/sh ip link set $IFNAME address $MAC mtu $MTU up [ $NODENAME = private1 ] && ip addr add 10.0.1.1 dev $IFNAME [ $NODENAME = private2 ] && ip addr add 10.0.2.1 dev $IFNAME ip route add 10.0.0.0/16 dev $IFNAME
The first line sets the MAC address for the interface, using the specified MTU. These variables are set by gvpe, so the command is actually expanded to something like:
ip link vpn0 address fe:fd:80:00:00:01 mtu 1500 up.
The second and third lines set the IP address of the virtual user. The inline test enables you to select which IP address is assigned to which host. Here is where you set the IP address of the virtual network. You should choose a network range that you are not already using (typical examples are the 10.0.0.0 range, or the 192.168.0.0 range).
In this case, the node assigned as private1 will be set at the IP address 10.0.1.1 and private2 at address 10.0.2.1.
The final line sets the default routing, redirecting all traffic for the 10.0.0.0 network through the newly created virtual interface.
Copy the configuration to each machine
Now that the scripts, configuration, and key information are in place, you need to copy the information to each machine. Since there is only one additional machine in our network, we need to copy the configuration over only once, but you could repeat the process for each machine in your network.
You can perform the copy either by using rsync or through a different protocol, such as scp, sftp, or even NFS. Remember that you only need to copy the gvpe.conf, if-up, and the public keys directory (pubkey) from the etc/gvpe directory.
For example, using rsync you could use the following command, which copies everything except the hostkeys directory to the new machine as shown in Listing 4.
Listing 4. Copy with rsync
$ rsync -avzessh /usr/local/etc/gvpe remote.example.com:/usr/local/etc/. --exclude hostkeys
Now on the node that is private1, copy the private key to /usr/local/etc/gvpe/hostkey. Assuming you have set up everything on that node:
$ cp /usr/local/etc/gvpe/hostkeys/private1 /usr/local/etc/gvpe/hostkey.
On the host that will be private2, copy the private2 hostkey from the generated directory. The scp command is used below on the remote.example.com host, shown in Listing 5.
Listing 5. Copy with scp
cd /usr/local/etc/gvpe scp 192.168.1.20:/usr/local/etc/gvpe/hostkeys/private2 /usr/local/etc/gvpe/hostkey
With the configuration in place, you can now start the gvpe service and connect the two machines together.
The gvpe process is simple and silent. It normally runs as a daemon in the background when started. Therefore, you can get away with simply running:
However, you may want to get some log information from the output. You can specify different levels of logging using the
-l parameter. For testing, you can also use the
-D parameter to prevent gvpe going into daemon mode. You also need to specify the node name, shown in Listing 6.
Listing 6. Specifying the node name
$ gvpe -D -l info private1 gvpe daemon 2.22 (Jun 13 2010 11:05:50) starting up.
Now on the host that will be the second virtual host in the network, run the command for starting the virtual network on private2. This should show that the connection has been established with the other host using UDP, shown in Listing 7.
Listing 7. Starting a private2 virtual network
$ gvpe -l info -D private2 gvpe daemon 2.22 (Jun 13 2010 08:30:01) starting up. private1(udp/192.168.1.20:407): connection established (direct), protocol version 0.1.
A similar line should have been output on private1, as shown in Listing 8.
Listing 8. Another private2 successful message
private2(udp/192.168.1.10:407): connection established (direct), protocol version 0.1.
You can test the network by using ping and specifying the remote IP address you set in the if-up script.
For example, from private1 you can ping to 10.0.2.1 (see Listing 9).
Listing 9. Pinging 10.0.2.1
$ ping 10.0.2.1 PING 10.0.2.1 (10.0.2.1) 56(84) bytes of data. 64 bytes from 10.0.2.1: icmp_seq=1 ttl=64 time=12.1 ms 64 bytes from 10.0.2.1: icmp_seq=2 ttl=64 time=1.62 ms ^C --- 10.0.2.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 1.629/6.891/12.154/5.263 ms
To monitor the status of the entire virtual network, use the
gvpectrl command with the
-s option, as shown in Listing 10.
Listing 10. Monitoring the status of the virtual network
$ gvpectrl -s Configuration # of nodes: 2 this node: <unset> MTU: 1500 rekeying interval: 0 keepalive interval: 0 interface: vpn0 primary rsa key: <default> rsa key size: 1280 ID# MAC Com Conmode Node Host:Port 1 fe:fd:80:00:00:01 Y always private1 192.168.1.20:407 2 fe:fd:80:00:00:02 Y always private2 www.example.com:407
You can kill the connection either by using the kill command with Control-C (if you’ve started up in non-daemon mode), but the best method is to use the
gvpectrl command shown in Listing 11.
Listing 11. Killing the connection gracefully
$ gvpectrl --kill preparing shutdown... private2(udp/192.168.1.10:407): connection lost exiting.
Of course, this is only a small internal network (which may not be entirely practical). More likely the virtual network will be used over public networks or to connect multiple hosts together into a single virtual network.
Deployment over public networks
When deploying over public networks, the basic setup and configuration is identical, even on a remote host. The keys that you set up will be used for authentication, and the encryption will be handled automatically through the public/private key.
A more significant consideration is the communication method that you use to communicate with each host. Unlike other VPN solutions, you can mix and match different underlying transports between different hosts while still supporting and creating the same basic virtual network environment.
To set a different protocol, you need only to configure the protocol of each virtual node within the configuration file. You can see this in Listing 12, where three new hosts (private3, private4 and private5) have been added to the configuration file.
Listing 12. Adding three new hosts
enable-udp = yes udp-port = 407 # Set the name of the virtual device created ifname = vpn0 # Set the first node node = private1 hostname = 192.168.1.20 # Set the second node node = private2 hostname = remote.example.com node = private3 hostname = ec2.amazon.com enable-tcp = yes tcp-port = 443 node = private4 hostname = 22.214.171.124 enable-rawip = yes node = private5 hostname = 192.168.100.20 udp-port = 20000
For private3, you are communicating with a host using Amazon EC2. When communicating with an external, public network like this there may be restrictions on your firewall that limit the communication. There are limits to what you can use, but for the purposes of this example you are using a direct TCP/IP communication on port 443, which is the port normally used for secure HTTP communication. This can be useful if other ports are normally blocked by your firewall. Remember that you must have network port access both ways for the virtual network to work.
With private4, you assume to have direct access to the host, not over a firewall, since you are using raw IP protocol. Most firewalls, including the Network Address Translation (NAT) environments used by most standard routers do not normally support this, so it can only be used when you have complete access.
With private5, you use the UDP protocol as used by default on private1 and private2, but you need to use a different port number. In this case, you’ve set a port number that is outside of the range that would normally need special privileges (below 1024), which means it could be run on a machine where the user does not have root access.
Configuring your applications
As demonstrated with the earlier ping example, the basics of the IP network are already running and services like ping are generally enabled by default on all interfaces on a host.
For other servers and applications, you will need to configure your application either to use the virtual network interface directly (vpn0 in our example), or, if it is a IP application you will need to configure and change the IP address that a particular server binds to, or that the client connects to when talking to the remote server.
For example, if you are configuring a system that will support and listen to connections through Apache to your web service environment, you should reset the Listen directive in the Apache configuration to your new virtual device IP address, for example:
Because GVPE is creating an entirely new network, you need only configure the server or client in the same way as you would configure any other application or service.
One trick that may be useful is for you to configure special situations when the virtual network is available. You can do this by using the node-up and node-down scripts, which should live in the etc/gvpe directory just like the if-up script.
These scripts are called whenever a node goes up or down. You can use this for a variety of different solutions, but a common one is to startup a service or register the server and service existence.
When used within a grid or cloud situation, for example, you might want to use the node-up command to call the script that registers the new host on the cloud or network so that other machines know that the machine is now available.
Creating virtual private networks is normally a complex process, and the result is not always as practical and flexible as you may want it to be. With GVPE you gain the ability to create an entire virtual network — not just a IP destination used to route and support some specific protocols. In addition, GVPE is also easy to setup and configure as a restartable and permanent service, while still retaining security.
In this article, you saw the main differences between GVPE and other VPN solutions. You also took a detailed look at the basic setup of a virtual network using the gvpe tools. You even discovered how to configure your gvpe configuration to work over public communication networks and how to work with your custom applications using the new virtual network.