[ Main / Projects / Docs / Files / FAQ / Links ]

Introduction

Nowadays, it's a well known fact that WEP is not sufficient for securing wireless networks. Many approaches have been used to securely communicate over the inherently insecure wireless networks that have recently become so popular, but IPsec is probably one of the most sophisticated and cross-platform approaches available and has gained a great deal of popularity in UNIX circles. Methods of using Linux 2.4's FreeS/WAN and [Free|Net|Open]BSD's KAME-derived IPsec implementations have become fairly well documented, but Linux 2.5's new IPsec layer has remained rather poorly documented. This document will attempt to provide an example of a working 2.5-based IPsec configuration that secures a real wireless network.

Prerequisites

In my personal network, I have one computer that I use as a gateway for my wireless network. I equip this machine with a dedicated NIC that plugs directly into my wireless access point. Another NIC is dedicated to my internal network. Both networks take advantage of the private address space and do not use publically routable IPs. A client machine on my network is equipped with a single wireless NIC and is given an address on the wireless subnet.

Diagram of example network:


<->   == NIC
<-w-> == Wireless NIC
[]    == Network

 Internet <-> OUTSIDE|10.0.1.1 <-> [10.0.1.0/24] <-> 10.0.1.2|10.2.0.1 <-> [10.2.0.0/24] <-w-> 10.2.0.2  
                 mastergw                                wirelessgw                        notebook

Recent versions of Linux 2.5 must be used; I've used Linux 2.5.71-mm1 for my configuration. The kernel networking should be built to include PF_KEY sockets (CONFIG_NET_KEY), IP: AH transformation (CONFIG_INET_AH), IP: ESP transformation (CONFIG_INET_ESP), IP: IPComp transformation (CONFIG_INET_IPCOMP), and IPsec user configuration interface (CONFIG_XFRM_USER). Netfilter should be configured for use as a firewall on the gateway machine. The Linux cryptographic API should be enabled to include HMAC support, MD5, SHA1, Triple DES, AES, and Deflate compression. Other cryptographic ciphers and hashes may be enabled at the user's discretion. The kernel should be compiled and installed as usual.

The necessary userspace utilities must be compiled and installed as well. setkey and racoon are the essentials. Also, if you haven't done so recently, it may be a good idea to make sure that your iptables is up-to-date.

Certificates

X.509 certificates must be generated for the wireless gateway and for all machines that will be connecting to it. Ralf Spenneburg's IPsec-HOWTO does an excellent job of explaining the process, so I will simply direct you to his site for this step. For my configuration, I placed certificates in /etc/certs on each machine. I will assume that you do the same.

ipsec.conf

The gateway machine's /etc/ipsec.conf should look something like this:

#!/usr/local/sbin/setkey -f

flush;
spdflush;

spdadd 0.0.0.0/0 10.2.0.2 any -P out ipsec
        esp/tunnel/10.2.0.1-10.2.0.2/require
        ah/tunnel/10.2.0.1-10.2.0.2/require;

spdadd 10.2.0.2 0.0.0.0/0 any -P in ipsec
        esp/tunnel/10.2.0.2-10.2.0.1/require
        ah/tunnel/10.2.0.2-10.2.0.1/require;

The matching client configuration would be:

#!/usr/local/sbin/setkey -f

flush;
spdflush;

spdadd 10.2.0.2 0.0.0.0/0 any -P out ipsec
        esp/tunnel/10.2.0.2-10.2.0.1/require
        ah/tunnel/10.2.0.2-10.2.0.1/require;

spdadd 0.0.0.0/0 10.2.0.2 any -P in ipsec
        esp/tunnel/10.2.0.1-10.2.0.2/require
        ah/tunnel/10.2.0.1-10.2.0.2/require;

Notice the symmetry. Also note that the server configuration would require a pair of entries for each machine connected to the wireless network as they are all independent 'networks' and act as tunnel endpoints only for themselves. Each client needs only to be aware of the gateway.

/etc/ipsec.conf should be set as executable, as it is nothing more than a script. The necessary setkey information may then be communicated to the kernel by simply invoking /etc/ipsec.conf. SA and SPD information may be cleared from the kernel with setkey -F.

racoon.conf

Since we are using dynamic keying, we will next need to configure racoon, the program that handles IKE. The gateway's /usr/local/etc/racoon/racoon.conf would look like:

path certificate "/etc/certs";

remote anonymous {
        exchange_mode main;
        certificate_type x509 "gateway_cert.pem" "gateway_key.pem";
        verify_cert on;
        generate_policy on;
        my_identifier asn1dn;
        peers_identifier asn1dn;
        proposal {
                encryption_algorithm 3des;
                hash_algorithm md5;
                authentication_method rsasig;
                dh_group modp1024;
        }
}

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

Our client's racoon.conf would be:

path certificate "/etc/certs";

remote anonymous {
        exchange_mode main;
        certificate_type x509 "client_cert.pem" "client_key.pem";
        verify_cert on;
        generate_policy on;
        my_identifier asn1dn;
        peers_identifier asn1dn;
        proposal {
                encryption_algorithm 3des;
                hash_algorithm md5;
                authentication_method rsasig;
                dh_group modp1024;
        }
}

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

3des and md5 are probably the most widely interoperable and common choices, so they are used in the example configuration. Added security (via sha1) and speed (via aes) may be obtained by using aes and sha1 in place of 3des and md5. Just be certain that the necessary kernel support is available on both the client and the gateway.

At this point, racoon should be run on both the gateway and the client. Check the logs to see if racoon starts cleanly. If not, try to look back at the earlier steps in the document, find the problem, and fix it (Google is your friend here, too!).

Testing

Now the ipsec configuration should be tested to be sure that it works before the firewall is instituted. Load the setkey information by invoking /etc/ipsec.conf. Then try to ping the gateway from the client and the client from the gateway. If both sides can ping each other, then everything is working fine so far.

Firewall

Now our traffic that travels from the gateway to the client and vice versa is authenticated by AH and encrypted by ESP; it will be very difficult for a wardriver to intercept traffic travelling between the two machines. However, we have done nothing so far to prevent a wardriver from being able to access services on the gateway or to use our upstream Internet connection. We will now make sure that wardrivers will be unable access our network with the help of an old friend, Netfilter.

The gateway machine should run a firewall script similar to the following:

#!/bin/sh

EXT_IF=eth1
EXT_IP=10.2.0.1
EXT_NET=10.2.0.0/24
IPT="/usr/local/sbin/iptables"

if [ "$1" = "start" ]
then
        echo "Starting firewall..."

        # deny input unless explicitly accepted
        $IPT -P INPUT DROP
        $IPT -P FORWARD DROP

        # we trust things that don't come from outside
        $IPT -A INPUT -i ! $EXT_IF -j ACCEPT
        $IPT -A FORWARD -i ! $EXT_IF -d 10.2.0.0/24 -j ACCEPT

        # if we initiate a connect, allow return packets on that connect
        $IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

        # Allow IKE auth on external interface
        $IPT -A INPUT -p udp -i $EXT_IF --sport ike --dport ike -m state \
                --state NEW -j ACCEPT

        # Allow and forward encrypted IPsec protocol traffic
        $IPT -A INPUT -i $EXT_IF -p 50 -j ACCEPT
        $IPT -A INPUT -i $EXT_IF -p 51 -j ACCEPT
        $IPT -A FORWARD -i $EXT_IF -p 50 -j ACCEPT
        $IPT -A FORWARD -i $EXT_IF -p 51 -j ACCEPT

        # must be ipsec protected by our setkey rules...
        $IPT -A INPUT -i $EXT_IF -s 10.2.0.2/32 -j ACCEPT
        $IPT -A FORWARD -i $EXT_IF -s 10.2.0.2/32 -j ACCEPT

        # Log suspicious traffic
        $IPT -A INPUT -i $EXT_IF -j LOG --log-prefix "eth1 INPUT DROP: "
        $IPT -A INPUT -i $EXT_IF -j LOG --log-prefix "eth1 FORWARD DROP: "

elif [ "$1" = "stop" ]
then
        echo "Stopping firewall..."
        $IPT -F
        $IPT -P INPUT ACCEPT
        $IPT -t mangle -F POSTROUTING
        $IPT -t nat -F

fi

If you're willing to deal with the extra administrative overhead and general annoyance, it's also possible to tell Netfilter to filter against client MAC addresses. Your reward will be a negligible security gain that may discourage neophyte wardrivers. Layers of security are a good thing, however.

This firewall will, with the help of our ipsec setkey rules, prevent any unauthorized clients from accessing anything but UDP port 500 (IKE) and protocols 50 and 51 (IPsec ESP and AH) on the gateway machine. Authorized IPs with associated setkey rules will be individually allowed access. Since these setkey rules require the IPs to send all traffic via AH/ESP, clients that do not correctly negotiate IPsec connections will be denied access to our network. Suspicious packets will be logged before they are dropped. Randoms are kept out and legitimate, authenticated users enjoy strong transport-level encryption and authentication.

Client security

If you're not confident of the security of the services on your client, it may be a good idea to run a standard deny-by-default stateful firewall on it, as client machines will not be protected from being probed by other clients without a firewall of their own.

Interoperability with other platforms

I haven't yet set up a WinXP client to communicate with the gateway, although it should be possible. I'll document the process once I get it working.

Links

Documentation on Linux 2.5's IPsec layer is a bit sparse, but here are the sites I found helpful while setting up my own network.

The Linux Advanced Routing and Traffic Control HOWTO
The official IPsec Howto for Linux

Nicholas J. Kain  | n i c h o l a s | a t | k a i n | d o t | u s |