Who is using your Network?
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:
- The network is large one, like a campus-wide network. The network administrator has no knowledge of or control over all the different computers that are connected to the LAN.
- A typical wireless network where everyone in your neighbourhood can use your internet link.
- You are in a cut-throat corporate office (perhaps this applies to some academic departments as well) where you do not really trust your colleagues—and all of them wear black-hats.
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:
- 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 liketsocks
that can “teach” any TCP application to use SOCKS. - 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:
- The key distribution mechanism is complex.
- It is not a great idea to tunnel TCP over TCP as explained in an article by Olaf Titz.
- 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:
- 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.
- 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:
- Use the “transport” mode for IPsec rather than the “tunnel” mode.
- 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
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.