...making Linux just a little more fun!

Who is using your Network?

By Kapil Hari Paranjape

1  The Evil That Lurks Within

Securing a local network (LAN) usually means creating firewall rules, host access rules and proper configuration of Mail, DNS and web servers. All these methods are primarily based on the assumption that the threat to your network is from the big bad internet. In this article I will take a reverse point of view—that is, users of the local network who are (possibly) the bad guys.

Such an assumption may be justified in the following contexts:

Although I spoke about “users” above, the real actors in a computer network are computers. By making the (often false!) assumption that each computer is doing exactly what its user wants it to do, I will reduce the question to the following:

How can computer Abdul that wants to talk to computer Chin be reasonably confident that computer Betaal is not able to intercept the conversation and/or impersonate Chin?

2  Not a telephone network

In order to understand why a slightly sophisticated solution is required, we need to realise that a LAN is a not like a telephone network and an IP address is not an identifying label in the same sense that a telephone number is.

The more sophisticated reader will know about “hardware” addresses (also known as Ethernet or MAC addresses) which are built into the hardware unlike IP addresses. However, the description of the network given in the paragraph below is equally appropriate if you replace “IP address” with “MAC address”.

A typical LAN is a packet based network. Each computer is always “connected” to all other computers. Conversations are based on packets which are sent “via the wire” and are “heard” by all the computers on the network. Each packet is labelled by the recipient's IP address so that the relevant party can “listen to it” (in other words, copy it to its memory). The packet also contains sender's IP address so that the recipient knows where to send replies.

Computer Betaal (as the ghost in the machine) can collect (copies of) packets meant for any destination and can also inject packets with any label(s) desired.

So, Abdul must (digitally) sign every packet sent out and encrypt it so that only Chin can read it. If Abdul only signed the packets, then Betaal (still) could collect them. Since there are a lot of packets that make up any conversation, Betaal could re-send the packets later in a more profitable order—thus delivering a blow to Chin. If Abdul only encrypted the packets then Betaal could inject his own encrypted packets of gobble-de-gook (illegible/undecipherable data) and disrupt the conversation between Abdul and Chin.

Let me re-state this in jargon. "In a packet based network, secrecy and authenticity go hand in hand."

3  Secure Shell

When Tatu Ylonen originally wrote ssh it was thought of as a replacement for telnet and rsh which are programs/protocols for remote logins (for remote shell access). However, ssh is a network protocol, so it can be used to create secure conversations between computers.

Each SSH server has a private key—usually located at /etc/ssh/ssh_host_rsa_key. Often, there is a second private key in /etc/ssh/ssh_host_dsa_key. Network administrator's job is to collect public keys associated to each of these private keys (in the same place, with a .pub extension) and distribute them to all computers on the network.

The simplest way to do this is to go to each computer and copy these files to a USB stick:

   cp /etc/ssh/ssh_host_rsa_key.pub /media/usb/<ip_addr>.rsa.pub
   cp /etc/ssh/ssh_host_dsa_key.pub /media/usb/<ip_addr>.dsa.pub

Admin then creates a “known hosts” file:

   for type in rsa dsa 
   do
       for i in /media/usb/*.$type.pub
       do
         addr=$(basename $i .$type.pub)
         (echo -n "$addr "; cut -f1-2 -d' '< $i)>> known_hosts
       done
   done

This known_hosts file is then copied to /etc/ssh/ssh_known_hosts on each computer. Finally, we set configuration parameters

   echo "StrictHostKeyChecking yes" >> /etc/ssh/ssh_config

on each computer. (Users on each computer may also need to modify the configuration file $HOME/.ssh/config if it exists and remove/edit $HOME/.ssh/known_hosts if it exists).

After this (admittedly) long-winded (but not difficult) procedure, Abdul and Chin have each other's public keys. So, Abdul can encrypt packets which only Chin can read and Chin can verify signatures made by Abdul. (The actual SSH protocol is more complex and doesn't concern us here).

So, now, on Abdul one can do ssh Chin and be confident that it is Chin who is answering. Chin will still ask for the password unless all servers enable HostBasedAuthentication in /etc/ssh/sshd_config. This procedure might be risky for Chin, unless the root user on Abdul is to be considered equivalent to the root user on Chin.

What about other (than SSH) types of data exchange? Luckily, this too has been thought of. If Abdul wants to open TCP port (say) 80 on Chin now, then Abdul runs

   ssh -q -f -N -L 8080:localhost:80 Chin

Now, opening http://localhost:8080 on Abdul gives Chin's web server.

What about securing all of data exchange? This has been thought of as well. In fact, SSH provides at least two ways:

  1. Applications that can use the SOCKS protocol (like Mozilla and Thunderbird) can use a tunnel created by this command:
             ssh -q -f -N -D 1080 Chin
    
    There are also wrapper libraries like tsocks that can “teach” any TCP application to use SOCKS.
  2. One can also create a TCP tunnel between the hosts:
             ssh -q -f -N -w 0:any Chin
    
    With some additional network configuration at each end, this tunnel can be used by all TCP applications, but not by applications that use UDP instead of UDP for their transport.

Despite these efforts, SSH is not always adequate for the problem we set out to solve for the following reasons:

  1. The key distribution mechanism is complex.
  2. It is not a great idea to tunnel TCP over TCP as explained in an article by Olaf Titz.
  3. We need to setup tunnels between each pair of hosts in the network; and this is a pain.

4  OpenVPN

OpenVPN can be thought of as SSH with a solution to all three problems noted above.

One machine is configured as the openvpn server and all of the other boxen - as clients. Server passively waits for the client to initiate a connection. Once the connection is established, roles of the two computers in the conversation are completely symmetric.

The server (respectively, client) can be configured using the sample server.conf (client.conf for the client) file that comes with the openvpn package (sample config files should be located at /usr/share/doc/openvpn-<version>/sample-config-files, if you're using a prepackaged version. Otherwise, they're located at sample-config-files directory in the source tarball). In client's configuration file one needs to edit only one line starting with remote and put in the correct server to connect to. In server's configuration file line that starts with server can to be edited to put in some random network in form of 10.a.b.0 (you could also use 172.16-32.a.0 or 192.168.a.0) instead of the default. Since we want clients to talk with each other, we also enable the client-to-client option in server's configuration file. In addition, we will edit these files to put in appropriate names like host.key and host.crt for certificate and key files (see below).

One nice feature of openvpn is that it can use certificates. This completely simplifies key distribution — we no longer need to distribute public key(s) of a new host to all other hosts. This gain comes at the “pain” of setting up a Certificate Authority.

4.1  The Stamp of Authority

First, we have to set up a Certificate Authority (CA) on one computer (network administrator's personal computer, for example). There are a number of ways to do this.

A simple way to setup a CA is provided with openvpn. We begin by copying the “Easy RSA 2.0” directory to a suitable place.

   mkdir /root/openvpn_CA
   cd /root/openvpn_CA
   cp -a /usr/share/doc/openvpn/examples/easy-rsa/2.0 .

Next, we have to edit last few lines of the vars file in this directory to reflect our organisation. The relevant lines:

   export KEY_SIZE=2048
   export KEY_COUNTRY=
   export KEY_PROVINCE=
   export KEY_CITY=
   export KEY_ORG=
   export KEY_OU=
   export KEY_EMAIL=

Then, we generate key of the Certificate Authority.

   . ./vars
   ./clean-all
   ./pkitool --initca 

Once all queries from the last command have been properly answered, we have a bunch of files in the keys subdirectory.

4.2  Give us a sign

Having set up the certificate authority, we have to sign keys of each host. First, each host generates a signing request:

   ln -s /etc/ssh/ssh_host_rsa_key.pub /etc/openvpn/host.key
   cd /etc/openvpn
   openssl req -new -extensions v3_req \
         -key host.key -out host.csr

All of the queries should be answered carefully. In particular, it is a good idea to use the fully qualified domain name for the common name (CN) entry. Then, host.csr is copied to the keys directory, where the certificate authority was installed with a name like <hostname>.csr. The CA then verifies and signs the key with the following commands:

   . ./vars
   ./pkitool --interact --sign <hostname>

Then, ca.crt and <hostname>.crt files from the keys directory of CA are copied back to the original host's /etc/openvpn; we also rename (or symlink) <hostname>.crt to host.crt.

4.3  Getting it all together

Now, to start the tunnel, we run

   /etc/init.d/openvpn start <config>

where the <config> is server or client as appropriate. We can start multiple client versions which are directed to the same server. Since we want the clients to talk with each other, we enable the client-to-client option in the server's configuration.

So, let us say that Octavio is the server and Abdul and Chin are two clients. When Abdul and Chin have a conversation over openvpn (which is ensured by Abdul by opening a connection to the 10.a.b.x address assigned to Chin) they can be reasonably confident that no one—not even Octavio—can intercept this conversation. Since openvpn asks for the certificate at the start of the conversation, Abdul is also confident that it is Chin at the other end of the conversation. At the very least Abdul is certain that this has been certified by the Certificate Authority.

4.4  Problems

Have Abdul and Chin solved their problem? Can they communicate without worrying about Betaal?

Some problems remain:

  1. All the parties depend on Octavio who is at the center of the (virtual) network. This may be appropriate for some situations, like a wireless network, where the natural shape (topology) of the network is star-like, but is inappropriate in a campus-wide network.
  2. Though routing is automated, it is still complex. Each pair of machines is connected by the underlying local network as well as the virtual network. To make the conversations secure, we must ensure that all data is exchanged over the virtual network.

5  Repeat

The solution to these two problems has essentially been described by Rene Pfeiffer in his article I and article II on IPsec. We will vary from his prescription in two respects:

  1. Use the “transport” mode for IPsec rather than the “tunnel” mode.
  2. Use the “use” policy for IPsec rather than the “require” policy.

The first ensures that routing is “automatic”. The second allows us to migrate to an IPsec network without disrupting existing connections. Once all machines that need to speak securely to each other are configured we can switch to the “require” mode to ensure that all conversations are encrypted.

One difference between IPsec and openvpn is, that, in IPsec, a separate daemon handles the key exchange and authentication. In GNU/Linux, this is racoon. We configure the /etc/racoon/racoon.conf file as follows. First of all, we put in the path to the certificates. This can be the same as certificates generated for OpenVPN. Next we configure authentication.

   remote anonymous {
      exchange_mode main;
      certificate_type x509 "$HOST_CERT" "$HOST_KEY";
      verify_cert on;
      my_identifier asn1dn;
      proposal {
            encryption_algorithm aes;
            hash_algorithm sha1;
            authentication_method rsasig;
            dh_group modp1024;
      }
   }

Here we have to replace $HOST_CERT and $HOST_KEY with certificate and key locations, respectively. The next section in the configuration file describes the encryption used after successful authentication.

   sainfo anonymous {
        pfs_group modp768;
        encryption_algorithm 3des;
        authentication_algorithm hmac_md5;
        compression_algorithm deflate;
   }

Next, we instruct the kernel to use IPsec whenever possible. To do this, we ensure that the following directives are loaded by command setkey. Flush the security associations and security policies.

   flush;
   spdflush;

The policy is to use the ESP protocol and AH protocol for all packets between this host and any other host on the network if possible. In commands below, one needs to put in the correct $IP_ADDR and $NETMASK values

   spdadd $IP_ADDR $NETMASK any -P out ipsec
      esp/transport//use
      ah/transport//use;

   spdadd $NETMASK $IP_ADDR any -P in ipsec
      esp/transport//use
      ah/transport//use;

This means that all hosts will use encrypted and authenticated traffic for every host in the LAN which supports encrypted traffic. This allows one to enable this configuration on all hosts in LAN one host at the time without disrupting the existing network in the process. Once all hosts are configured for IPsec, this can be replaced with

   spdadd $IP_ADDR $NETMASK any -P out ipsec
      esp/transport//require
      ah/transport//require;

   spdadd $NETMASK $IP_ADDR any -P in ipsec
      esp/transport//require
      ah/transport//require;

6  Conclusion and Acknowledgements

Now, it is relatively easy to configure machines to use encryption and authentication in a local area network. Today, computers and networks are fast enough, so extra calculations and extra network packets, that are required for this, do not cause noticeable delays. Also, it is quite easy to implement such a solution without bringing down the entire network until all machines are reconfigured.

So! What are you waiting for? Choose a solution that is appropriate for your use and put it into use!

In the IMSc network we have tested and implemented the openvpn solution. A number of my colleagues here helped debug various aspects of this. I thank them all for their help. The documentation of ssh and openvpn is also very good. There is a number of great articles on IPsec including those from LG that have been mentioned above. I thank the authors of these documents for their assistance.


This document was translated from LATEX by HEVEA.

Talkback: Discuss this article with The Answer Gang


Bio picture Kapil Hari Paranjape has been a ``hack''-er since his punch-card days. Specifically, this means that he has never written a ``real'' program. He has merely tinkered with programs written by others. After playing with Minix in 1990-91 he thought of writing his first program---a ``genuine'' *nix kernel for the x86 class of machines. Luckily for him a certain L. Torvalds got there first---thereby saving him the trouble (once again) of actually writing code. In eternal gratitude he has spent a lot of time tinkering with and promoting Linux and GNU since those days---much to the dismay of many around him who think he should concentrate on mathematical research---which is his paying job. The interplay between actual running programs, what can be computed in principle and what can be shown to exist continues to fascinate him.

Copyright © 2007, Kapil Hari Paranjape. Released under the Open Publication License unless otherwise noted in the body of the article. Linux Gazette is not produced, sponsored, or endorsed by its prior host, SSC, Inc.

Published in Issue 141 of Linux Gazette, August 2007

Tux