Using the GNU Virtual Private Ethernet

Providing a secure communication conduit implies many different issues and problems, such as how you provide an effective communication channel that is capable of handling multiple streams of information. Using the GNU Virtual Private Ethernet (GVPE) provides an alternative to the normal single or multiple channel solutions by effectively emulating the entire network stack and allowing you to build TCP, UDP and other network technologies on top of the virtual environment. This article examines ways of using GVPE with your applications to provide communication, and of using GVPE with your Web sites to provide secure connectivity over private and public networks. In particular you'll learn about using GVPE with distributed infrastructure projects, such as Amazon EC2, clouds, or public/private web performance deployments.

Martin Brown (mc@mcslp.com), Freelance Writer, Author

Martin Brown has been a professional writer for over eight years. He is the author of numerous books and articles across a range of topics. His expertise spans myriad development languages and platforms - Perl, Python, Java, JavaScript, Basic, Pascal, Modula-2, C, C++, Rebol, Gawk, Shellscript, Windows, Solaris, Linux, BeOS, Mac OS/X and more - as well as web programming, systems management and integration. Martin is a regular contributor to ServerWatch.com, LinuxToday.com, IBM developerWorks and a regular blogger at Computerworld, The Apple Blog, and other sites. He is also a Subject Matter Expert (SME) for Microsoft. He can be contacted through his website at http://www.mcslp.com.



01 February 2011

Also available in Chinese

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
Illustration of a 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
Illustration of a 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
Creating a virtual network over public and private networks VPN solution using GVPE

For convenience, the configuration information for all the hosts within the virtual network is shared, making setup and extension of the configuration very easy.


GVPE security

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 installation

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 mingw or 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:

  1. Download the gvpe package.
  2. Extract the gvpe package:
    • $ tar zxf gvpe-2.2.tar.gz
  3. Change into the gvpe-2.2 directory:
    • $ cd gvpe-2.2
  4. Run configure to set the options you want to use:
    • $ configure --prefix=/usr/local --enable-digest=sha512 --enable-cipher=aes-256
  5. Compile:
    • $ make
  6. Install:
    • $ 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.

  1. Setup the configuration for the entire network
  2. Create the public/private keys
  3. Create a script to setup the network on each host
  4. Copy the GVPE configuration to each machine
  5. Set the hostkey for each machine
  6. Start GVPE

Each step will be described individually.

Configuration script

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.

Start gvpe

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: $ gvpe.

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 = 129.168.23.47
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: Listen 10.0.2.1:80.

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.


Conclusion

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.

Resources

Learn

Get products and technologies

  • Innovate your next open source development project with IBM trial software, available for download or on DVD.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into AIX and Unix on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=AIX and UNIX
ArticleID=620639
ArticleTitle=Using the GNU Virtual Private Ethernet
publish-date=02012011