Securing WLAN with OpenVPN

markus reichelt, December 2004

v1.1.1, last modified: 2006-05-01, status: unmaintained, kept for reference

stylesheet: [green] [black]

Content

  1. Abstract
  2. Network Layout
  3. Server Configuration
  4. Client Configuration Linux
  5. Client Configuration Windows XP
  6. Netfilter Rules
  7. Comments
  8. Changelog
  9. License & Contact

Abstract

This text is intended for linux users who already have installed OpenVPN (and OpenSSL) properly and want to use it to securely integrate WLAN into their private network. A succinct network layout is provided, as well as config examples for an OpenVPN server with static key on a linux box and client configurations with static key for both linux and Windows XP. The whole setup is DHCP-aware. Netfilter rules are given to securely integrate the WLAN connection into the the private network.

I'm happily using the Slackware 10+ distro as base system, both on my desktops and servers. The netfilter rules can be invoked standalone or added to MonMotha's Firewall script version 2.3.8.

This setup is known to work on Slackware 10.2 systems with OpenVPN 2.0.5 and OpenSSL 0.9.7i

.

[top]

Network Layout

My network layout is very similar to this one, so I'm re-using the layout mentioned there.

  ###  = Uplink to Internet Service Provider
  ---  = 100Mbit Fast Ethernet
  ///  = WLAN Connection
  ***  = VPN Connection

                  LINUX-SERVER
               +-----------------+
 +--------+    | +-------------+ |
 | I S P  |######|  eth0/ppp0  | |
 +--------+    | +-------------+ |
               |                 |
               |                 |      +-----------------+
               | +-------------+ |      | +-------------+ |
               | |    eth1     |----------|    SWITCH   | |
               | | 192.168.0.1 | |      | +-------------+ |
               | +-------------+ |      |  192.168.0.0/24 |
               |                 |      +-----------------+
               |                 |
               | +-------------+ |      +-----------------+
               | |    eth1:1   | |      | +-------------+ |
               | | 192.168.3.1 |----------| AccessPoint | |
               | +------******************|*******      | |
               |        *        |      | +------*------+ |
               |        *        |      |   192.168.3.2   |
               |        *        |      +-------/*/-------+
               | +------*------+ |              /*/
               | |  tap0(VPN)  | |              /*/
               | |  10.1.1.1   | |              /*/
               | |             | |              /*/
               | |  tap1(VPN)  | |              /*/
               | |  10.1.2.1   | |              /*/
               | +-------------+ |              /*/
               |                 |              /*/ 
	       +-----------------+              /*/
	                           /*************************/
				   /*/                     /*/
				   /*/                     /*/
                           +-------/*/---------+   +-------/*/---------+
                           | +---------------+ |   | +---------------+ |
                           | | VPN-EndPpoint | |   | | VPN-EndPpoint | |
                           | |    10.1.1.2   | |   | |    10.1.2.3   | |
                           | +---------------+ |   | +---------------+ |
                           | | Wireless LAN  | |   | | Wireless LAN  | |
                           | |    Client     | |   | |    Client     | |
                           | | slackware 10  | |   | |  windows xp   | |
                           | +---------------+ |   | +---------------+ |
                           |    192.168.3.3    |   |    192.168.3.4    |
                           +-------------------+   +-------------------+

You'll notice that I use the virtual ethernet device eth1:1 instead of one more NIC, just for efficiency. The other subnets of my network are irrelavant to the task at hand, hence they aren't listed.

[top]

Server Configuration

The linux box will be the OpenVPN server. Since this howto is using a static key, you need to create one in /etc/openvpn.

openvpn --genkey --secret /etc/openvpn/wireless-static.key

And when it comes to keys, don't forget to

chmod 0600 /etc/openvpn/wireless-static.key

Now it's time to create the config file which is located at /etc/openvpn/wireless-static.conf

#### SERVER /etc/openvpn/wireless-static.conf ####

#listen on this ip only
local 192.168.3.1

#we use tap device
dev tap

#set ip address and netmask of VPN tunnel server point
ifconfig 10.1.1.1 255.255.255.0

#tell openvpn where to find the static key
secret /etc/openvpn/wireless-static.key


#sometimes this is required
link-mtu 1544


#we want some log info 
verb 3

#use compression
comp-lzo

#give port number. if not given, 1194 is used.
port 1195

That's all, now you can start the OpenVPN server with the following command

openvpn --config /etc/openvpn/wireless-static.conf

and you should see a similar output to this:

#### SERVER ####

LZO compression initialized
TUN/TAP device tap0 opened
/sbin/ifconfig tap0 10.1.1.1 netmask 255.255.255.0 mtu 1467 broadcast 10.1.1.255
Data Channel MTU parms [ L:1544 D:1450 EF:45 EB:19 ET:32 EL:0 ]
Local Options hash (VER=V4): '007023e0'
Expected Remote Options hash (VER=V4): '007023e0'
UDPv4 link local (bound): [undef]:1195
UDPv4 link remote: [undef]

That's it, your server is up and listening on port 1195. Now copy wireless-static.key to the client, preferrably to /etc/openvpn.

[top]

Client Configuration Linux

It is assumed that OpenVPN and OpenSSL have been installed properly on the client. Then proceed and create the client configuration file /etc/openvpn/wireless-static-client.conf

#### CLIENT /etc/openvpn/wireless-static-client.conf ####

#we use tap device
dev tap

#address of openvpn server
remote 192.168.3.1

#set ip address and netmask of vpn client tunnel endpoint
ifconfig 10.1.1.2 255.255.255.0

#tell openvpn where to find the static key
secret /etc/openvpn/wireless-static.key


#route to server endpoint
route-gateway 10.1.1.1

#redirect traffic
redirect-gateway

#use compression
comp-lzo

#again
link-mtu 1544

#log info
verb 3

#give port number. if not given, 1194 is used.
port 1195

That's all, now you can start the OpenVPN client with the following command

openvpn --config /etc/openvpn/wireless-static-client.conf

and you should see a similar output to this:

#### CLIENT ####

LZO compression initialized
TUN/TAP device tap0 opened
Data Channel MTU parms [ L:1544 D:1450 EF:45 EB:19 ET:32 EL:0 ]
Local Options hash (VER=V4): 'fa340d5e'
Expected Remote Options hash (VER=V4): 'fa340d5e'
UDPv4 link local (bound): [undef]:1195
UDPv4 link remote: 192.168.3.1:1195
Peer Connection Initiated with 192.168.3.1:1195
Initialization Sequence Completed

Check the network, ping the tunnel endpoint from each side. Start with the client and enter

ping -c3 10.1.1.1

The output should be similar to this

#### CLIENT ####

PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=2.75 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=2.36 ms
64 bytes from 10.1.1.1: icmp_seq=3 ttl=64 time=2.40 ms

--- 10.1.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 2.369/2.511/2.756/0.173 ms

Now the server:

ping -c3 10.1.1.2

The output should be similar to this

#### SERVER ####

PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=2.86 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=3.16 ms
64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=2.73 ms

--- 10.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 2.733/2.921/3.168/0.187 ms

Got a Ping?! That's great! But what about routing? By default OpenVPN tries to adjust routes itself and in most cases it just works.Nevertheless we check it, starting from the server

/sbin/route -n

Only the important routes are listed here in this example, check for tap0

#### SERVER ####

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
[...]
192.168.3.1     0.0.0.0         255.255.255.255 UH    0      0        0 eth1
255.255.255.255 0.0.0.0         255.255.255.255 UH    0      0        0 eth1
255.255.255.255 0.0.0.0         255.255.255.255 UH    0      0        0 eth1
192.168.0.1     0.0.0.0         255.255.255.255 UH    0      0        0 eth1
217.5.xxx.xxx   0.0.0.0         255.255.255.255 UH    0      0        0 ppp0
192.168.3.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 tap0
10.1.2.0        0.0.0.0         255.255.255.0   U     0      0        0 tap1
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        0 lo
0.0.0.0         217.5.xxx.xxx   0.0.0.0         UG    0      0        0 ppp0
[...]

Experience shows that a big bunch of problems boil down to client routing troubles... Now let's hear what the client has to say.

/sbin/route -n

tap0 must be listed in the routing table as device and also as default gateway. If it's not listed as default gateway you must add the route on your own. The Fine Manual knows a lot about troubles, be sure to consult it.

#### CLIENT ####

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.3.1     192.168.3.1     255.255.255.255 UGH   0      0        0 eth1
192.168.3.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 tap0
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        0 lo
0.0.0.0         10.1.1.1        0.0.0.0         UG    0      0        0 tap0

Now try surfing the net, it should work. If you run a caching name server be sure that the client is allowed to inquire from 10.1.1.2 as well.

[top]

Client Configuration Windows XP

Actually I despise this 'operating system', but once in a while there's just no way around it. You have to make sure to install OpenVPN properly, usually just run the installer and be done with it. But only the config files are listed here (for reference), for the client on win xp and the seperate server config file on the linux box. Don't forget to copy the secret key to the windows 'machine'.

#### win xp CLIENT wireless-static.conf ####

#we use tap device
dev tap

#address of openvpn server
remote 192.168.3.1

#define port
port 1196

#set ip address and netmask of client vpn endpoint
ifconfig 10.1.2.3 255.255.255.0

#we need to set routes ourselves via batchfile
up setroutes.bat

#where is the key
secret wireless-static.key

#we want some log info
verb 3

#compression is left off
#comp-lzo


#### win xp CLIENT setroutes.bat ####

route add 10.1.2.0 netmask 255.255.255.0 10.1.2.1
route add 0.0.0.0 mask 0.0.0.0 10.1.2.1

Create a link to where you installed OpenVPN (like "target C:\Programme\OpenVPN\bin\openvpn.exe --config wireless-static.conf", execute in "C:\Meine Daten\OpenVPN"; all important files reside in there! key + conf + bat). In case this sounds too confusing have a look here. Then start the app, a window should pop up with similar messages to the ones above (client side). If it pops up just for a second, something is not right. Maybe a typo? If you can't ping the win xp 'machine', maybe you activated its 'firewall'? Try plain old surfing, if the route is correct.

Be prepared for the most strangest phenomenons. Theoretically it should work, practically you're running windows. Perhaps getting a fresh cup of coffee will magically help.

Last but not least the corresponding server config file for a win xp client.

#### SERVER /etc/openvpn/wireless-static-winxp.conf ####

dev tap
port 1196
ifconfig 10.1.2.1 255.255.255.0
secret /etc/openvpn/wireless.key
verb 3

Run the same tests as described above accordingly.

[top]

Netfilter Rules

Using an encrypted Virtual Private Network is only one half of a secure WLAN integration into a private network. The other half is making sure that (almost) only traffic on the UDP connections can pass from the WLAN subnet into the private network. The whole thing shall still be usable with DHCP. That's where netfilter comes in.

First we have to make sure that traffic from/to tap/tun devices is not blocked.

Oh, and if you're using MonMotha's Firewall script, just add the following lines in appearing order to the end of the script so that each time the connection to your ISP gets reestablished, the whole WLAN stuff is not leaving a huge security hole in your system.


${IPTABLES} -A INPUT -i tun+ -j ACCEPT

${IPTABLES} -A FORWARD -i tun+ -j ACCEPT

${IPTABLES} -A INPUT -i tap+ -j ACCEPT

${IPTABLES} -A FORWARD -i tap+ -j ACCEPT

Now lets focus on eth1:1, 192.168.3.1, which is directly connected to the Access Point. We only want VPN traffic to pass, and some stuff necessary for DHCP, and an ordinary ping shall pass as well. That's what these netfilter rules are for.


${IPTABLES} -t nat -I PREROUTING -i eth1 -s 192.168.3.0/24 \
 -j DROP

${IPTABLES} -t nat -I PREROUTING -i eth1 -s 192.168.3.0/24 \
 -d 192.168.3.1 -p icmp --icmp-type echo-request -j ACCEPT

${IPTABLES} -t nat -I PREROUTING -i eth1 -s 192.168.3.0/24 \
 -d 192.168.3.1 -p udp --dport 1195 -j ACCEPT

${IPTABLES} -t nat -I PREROUTING -i eth1 -s 192.168.3.0/24 \
 -d 192.168.3.1 -p udp --dport 1196 -j ACCEPT

${IPTABLES} -t nat -I PREROUTING -i eth1 -p udp --source-port\
  68 -d 255.255.255.255 --destination-port 67 -j ACCEPT

${IPTABLES} -t nat -I PREROUTING -i eth1 -p udp --source-port\
  67 --destination-port 68 -j ACCEPT

${IPTABLES} -t nat -I PREROUTING -i eth1 -p udp --source-port\
  67 --destination-port 67 -j ACCEPT

[top]

Comments

When you get a working static key setup, it's wise to make the next step towards using dynamic keys. I consider the setup described herein as absolute minimum, anything less is severe security malpractice.

A sidenote on the network setup. It's not necessary (and not wise too) to masquerade 192.168.3.0/24 (eth1:1) because it's solely used to integrate the Access Point and WLAN clients into the private network, hence it should be considered hostile. My corresponding netfilter rules listing:

#### SERVER ####

root@hoth:~# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
ACCEPT     udp  --  anywhere             anywhere            udp spt:bootps dpt:bootps
ACCEPT     udp  --  anywhere             anywhere            udp spt:bootps dpt:bootpc
ACCEPT     udp  --  anywhere             255.255.255.255     udp spt:bootpc dpt:bootps
ACCEPT     udp  --  192.168.3.0/24       hoth.rebelbase.local udp dpt:1196
ACCEPT     udp  --  192.168.3.0/24       hoth.rebelbase.local udp dpt:1195
ACCEPT     icmp --  192.168.3.0/24       hoth.rebelbase.local icmp echo-request
DROP       all  --  192.168.3.0/24       anywhere

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  localnet/24          anywhere
MASQUERADE  all  --  10.0.0.0/8           anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

That's pretty much it. I hope this little text helped you.

Still a work in progress...

[top]

Changelog

Version 1.1.1, 2006-05-01:
Link to Key Signing Policy updated.
Version 1.1.0, 2006-02-07:
Typos corrected.
Version 1.0.0, 2004-12-30:
Initial Release.

[top]

License & Contact

Copyright © 2004 - 2010 markus reichelt.

If you want to contact me, send an email in plain text only to the address listed below; encrypted email is preferred. Have a look at my GnuPG Key Signing Policy.

Encrypted and anonymous message box available at https://privacybox.de/mareichelt.msg, or as Tor Hidden Service in case you prefer such a method of contact. Be advised that the subject will not be encrypted, only the text message itself. Also, in case you want a reply, please provide secure means of contact.

[top]


[ return to publications page ]



markus reichelt <markus.reichelt@gmx.net>
Last modified: 2006-05-01
angstklausel - site policy - imprint - Gegen Stasi 2.0 - FSFE - valid html - valid CSS - any browser