Securing 802.11b

Recently it has come to light that the WEP encryption that usually comes with 802.11b equipment is totally insecure. If you have been hiding under a rock and are not aware of the issue, you might go check out AirSnort, which is a utility designed to discover a WEP key merely through passive monitoring.

So now that we've decided that WEP isn't enough, what do we do about it?

There are 3 solutions that spring immediately to mind:

  1. PPPoE with encryption
  2. PPTP with encryption
  3. IPSEC
Of these options, I have set up both PPPoE and PPTP. I have not tried IPSEC because one of my requirements was support for Win9x clients, which I could not find for win9x.

PPPoE

This method, it turns out, is the less effective solution for Windows clients, but works best for FreeBSD machines.

The fundamental issue is the way MPPE works. MPPE is the encryption subprotocol for the PPP session. There are two modes for MPPE -- Stateless and Stateful. Let's examine for a moment how these work. But first, a bit about encryption. The encryption engine used for MPPE (and most other things too) has three properties that matter for our discussion:

  1. If you are decrypting an encrypted stream and lose a chunk out of the middle, any encrypted data that arrives after the missing chunk is irrecoverable. The two sides must reinitialize the encryption engines to resynchronize.
  2. Resynchronizing the encryption engines is (slightly) computationally expensive, certainly compared to simply running the engine on a stream of data
  3. Every time you resynchronize, you have to use a new key derived from the shared secret material for the session. Every time one side resynchronizes, the other side must do so in order for the resynchronizations to themselves be in sync
So given these basic constraints, Microsoft (who invented MPPE) came up with two ways to do it -- Stateful and Stateless.

Stateless MPPE works like this: Every packet is sent by itself. Both sides then resynchronize immediately. Each packet is sent with a sequence number and if the receiver sees a gap, he will simply run extra resyncs to make up for the drops. This is an expensive mode, but as we shall see, it is really the only option for lossy media.

Stateful MPPE works like this: At the start of the session, the two engines are synchronized. Then the sender runs one packet after another through the encryption engine without resyncing. Each has a sequence number. If the receiver sees a gap in the sequence numbers, he must throw away any subsequent packets that arrive and send back a request that the sender resynchronize. Stateful mode is designed for media where packet loss is very unlikely. It costs much less because you aren't constantly resynchronizing the two sides. A lossy media, however, is terrible for stateful mode. Every time a packet is dropped, another must be thrown away before the reciever can detect the desync and request a reset. If there is latency, then even more packets may be in the pipeline that will have to be thrown away before the reset arrives at the receiver. Each of these packets must also generate a reset request which will end up resulting in more resyncs.

Clearly when contemplating running MPPE over 802.11b, stateless mode will be required. Here, we run into a problem.

The way you run PPPoE on Microsoft is to add RASPPPoE. This makes your network cards look like modems for dialup networking.

The issue that is a show-stopper is that Windows' dialup networking refuses to negotiate stateless encryption (unless you're using PPTP, as we shall see).

FreeBSD's user level PPP is quite happy to use stateless mode, so if you have no Windows hosts to support, PPPoE is the easiest choice, since everything you need (for both server and client) is built-in to the operating system.

Here's a good server-side PPPoE setup:


pppoe:
 set ifaddr 192.168.0.1 192.168.0.2-192.168.0.254 255.255.255.255
 enable proxy
 disable utmp
 disable passwdauth
 enable lqr
 set cd 5!
 accept dns
 enable mschapv2 mppe
 disable deflate pred1
 deny deflate pred1
 set mppe 128 *
 set timeout 0
 set mru max 1400
 set mtu max 1400
 set speed sync

Here's a client side configuration:

pppoe:
 set device PPPoE:wi0
 add! default HISADDR
 set timeout 0
 set cd 5!
 set dial
 set login
 set authname NAME
 set authkey PASS
 enable dns
 enable mppe
 set mppe 128 stateless

Setup

To set up the server, you need to set up a pppoe server configuration in /etc/ppp/ppp.conf, set up some usernames/passwords in /etc/ppp/ppp.secret, and run /usr/libexec/pppoed.

To set up clients, you simply need to set up a pppoe client configuration in /etc/ppp/ppp.conf.

This configuration is secure because the server has no addresses configured on the PPPoE interface, so no IP traffic can be received. Watch out, however, if you have other protocols (particularly IPv6) configured. You may need to add some firewalls to keep the interface from being useful to anyone not running PPPoE.

PPTP

This configuration is a bit more work.

You first need to set up a private network on the interface for the wireless LAN. You will also need to provide DHCP service on this interface, and set up a firewall to keep this network from being useful for anything but PPTP.

Here is a suitable ipfw script:


wif="fxp1"
wip="10.0.0.1"

${fwcmd} add pass gre from any to ${wip} via ${wif}
${fwcmd} add pass gre from ${wip} to any via ${wif}
${fwcmd} add pass tcp from any to ${wip} 1723 in recv ${wif}
${fwcmd} add pass tcp from any to any established via ${wif}
${fwcmd} add pass udp from any 67 to any 68 out xmit ${wif}
${fwcmd} add pass udp from any 68 to any 67 in recv ${wif}

This setup will allow clients connected to fxp1 to DHCP and start PPTP sessions to 10.0.0.1, which is all we want them to do.

At this point, you have two choices for the server: One is the mpd-netgraph port, but the simpler route is the poptop port.

The FreeBSD clients will need the pptpclient port. One trick I found in seting up pptpclient on FreeBSD is that if the PPP session will be adding or changing the default route, it is important to set up a host route for the pptp server address before you start up pptpclient. This host route will route the tunnel itself. Without it, the tunneled traffic would attempt to re-enter the tunnel (like a truck driving up its own tailpipe).

Windows clients will need no additional software. PPTP VPN functionality is built-in to win98 and above (win95 clients can get a downloadable DUN upgrade). You need to simply set up the clients to first DHCP for an IP address, then bring up a PPTP connection to 10.0.0.1.

You may want to consider checking out Microsoft Knowledge Base article Q162847 if you are running Windows NT or 2000. The registry setting it mentions may help keep your TCP sessions alive better when using PPTP.

The server side ppp config is the same as the PPPoE setup except that you must not set sped to sync (the framing will be all wrong), and you will want to 'set mppe 128 stateless' to make sure stateless mode is negotiated in both directions.

The client side ppp config for FreeBSD is the same as the PPPoE client side setup, with the exception of the 'set device' line (which you can leave out).