Getting secure WLAN by using OpenVPN on a WRT54G under OpenWRTIf you want to use OpenVPN just to get your WLAN secure so that nobody can snoop your packet contents and nobody can use your system to get access to the internet, this is probably the right page for you. If you decide to configure your system like it is described here you have to do it carefully without leaving one or more steps out. This is important because everything is working very closely together. This configuration is based on OpenVPN version 2.0-beta...! All connected machines (clients) must have a 2.0 version of OpenVPN.I have spend a lot of time to find the configuration I am describing here. I think this is one of the standard configurations of an OpenVPN server on the WRT54G and therefore it should be documented. Hopefully, it will help save some of your time! But, I have to mention one additional point: "This configuration has only been tested with my WRT54G-Ver1.1!" Because everything is done by using the nvram variables you should only have to check/change the nvram settings. Changes/History
The system layoutMy intention for this system configuration was to get the system behavior just as it was before the installation. The new security aspect should be totally transparent to the user of the system. The system should be able to handle Linux clients as well as Windows clients.
So what can be done? The trick is to block everything coming from eth2 which isn't certificated. Here OpenVPN joins the game.
Creating the keys and certificates needed by OpenVPN in tls-server modeThis description is taken from the OpenVPN home page. # create your main key/certificate pair openssl req -nodes -new -x509 -keyout my-ca.key -out my-ca.crt -days 3650 # put these two files to the locations defined in the openssl.cnf Now the openssl is configured to produce a key/certificate pair for the openvpn server and each client you want to give access to your private network represented by the bridge interface br0. for each key/certificate pair you have to specify several parameters e.g. company name etc. Because the OpenVPN server takes the client names for individual configurations, the name entry of the key/certificate should be different and mappable. If the clients are uniform in configuration you can take generic names like clientX. # first for the server openssl req -nodes -new -keyout server.key -out server.csr openssl ca -out server.crt -in server.csr openssl dhparam -out dh1024.pem 1024 # do this for each client (replace the X by a number or # chose a different name) openssl req -nodes -new -keyout clientX.key -out clientX.csr openssl ca -out clientX.crt -in clientX.csr OpenVPN Server configurationGetting the correct timeThe usage of OpenVPN requires a correct time setting on all machines that want to build a tunnel between them. That means you have to get the right time at the startup procedure of the router. With the ntpclient application you can obtain the correct time. I have inserted the following line into the S50services startup script: ntpclient -s -h ntp1.ptb.de You should take one ntp server which is located close to your router. In Germany where the time is made ;-)) the PTB Braunschweig is one server you can trust. This configuration leads to the effect that every time the router is turned on a connection to your ISP is made to get the right time. Server configuration file "server.conf"First of all, the OpenVPN server has to get the information on what to do and where to find additional information. This information is located in the file server.conf, which looks like this: # main behavior mode server tls-server # use tap devices because of the windows clients dev tap # execute the following script for each client which is started up /etc/openvpn/server-tun.up # use the following encryption method cipher BF-CBC auth SHA1 # certificates an the private key ca /etc/openvpn/my-ca.crt dh /etc/openvpn/dh1024.pem cert /etc/openvpn/server.crt key /etc/openvpn/server.key # the servers ip on eth2 local 192.168.2.1 # information which is evaluated by the clients # this is: take the tap interface as default gateway push "route-gateway 192.168.1.1" push "redirect-gateway local" # additional windows stuff which is ignored by linux clients # take the router as dns server push "ip-win32 dynamic" push "dhcp-option DNS 192.168.1.1" # directory contains the client specific configurations # the ip address and netmask client-config-dir /etc/openvpn/server-config-dir # standard configuration: keep keys in mind and don't reopen devices keepalive 10 60 persist-key persist-tun # ping only on active connection ping-timer-rem # emit nothing more than fatals verb 0 This configuration requires two additional scripts/configurations which are executed/evaluated while the server starts/the connection comes up. The first one is a script which is used to add the interface to the lan bridge and to add firewall rules to get access from the WLAN to the OpenVPN server which is about to start. To understand what is done in detail have a look at the description of the startup scripts S41openvpn and S45firewall. The following frame consists of the important stuff in this script: #!/bin/ash
LAN=$(nvram get lan_ifname)
WLAN=$(nvram get wlan_ifname)
# bring up the tap interface
$DEBUG ifconfig $1 0.0.0.0 up
# and add that to the bridge
$DEBUG brctl addif $LAN $1
# prepare a rule to accept incoming requests for the OpenVPN server
echo "iptables -t filter -A INPUT -i $WLAN -p udp --dport $local_port\
-m state --state NEW -j ACCEPT" >> /etc/tun-iptable-rules
# and prohibit all requests coming from non wireless internal interfaces
# for the OpenVPN server (avoid multiple interfaces in one net)
for interf in $(nvram get vpnlan_ifnames); do
echo "iptables -t filter -A INPUT -i $interf -p udp --dport $local_port\
-m state --state NEW -j DROP" >> /etc/tun-iptable-rules
done
I like a fixed mapping of IP addresses to my clients. This mapping is stored in the client specific configuration files located in <client-config-dir>. These files are named by the entry of the keys/certificates. In my system the contents are like (with different IP's): ifconfig-push 192.168.1.100 255.255.255.0 The configuration of the DHCP server of the WRT must exclude these IP's which are reserved for WLAN clients (see Configuration of DHCP and DNS). Additional nvram entriesTo keep the configuration consistent some configuration details should be set in the nvram to get global access from all configuration files. We have two additional things to configure, the WLAN part and the new base configuration for the bridge. The following frame contains all entries to set the configuration files. # settings for the insecure wlan interface nvram set wlan_ifname eth2 nvram set wlan_ipaddr 192.168.2.1 nvram set wlan_proto none # settings for the new and secure lan (vpnlan) nvram set vpnlan_ifname=br0 nvram set vpnlan_ifnames=vlan2 nvram set vpnlan_hwaddr=$(nvram get lan_hwaddr) nvram set vpnlan_ipaddr=192.168.1.1 nvram set vpnlan_netmask=255.255.255.0 nvram set vpnlan_proto=static nvram commit Startup file S41openvpnThe intent of my configuration was to make it very simple to reactivate the original configuration. This will probably conform with your interests. This means the original interface's configuration is built by the S40network script. After that work is done the S41openvpn script brings up the interfaces for the OpenVPN configuration and starts the desired OpenVPN server processes. This is shown in the following frame: #!/bin/sh . /etc/functions.sh # load the kernel module $DEBUG insmod tun # reconfigure the lan ifup vpnlan # bring up the wlan and set the static ip (by hand because there isn't a gateway) ifup wlan $DEBUG ifconfig $(nvram get wlan_ifname) $(nvram get wlan_ipaddr) up # prepare the iptable settings rm -f /etc/tun-iptable-rules # start the openvpn servers for the fixed ports # /etc/tun-iptable-rules is filled and tun interfaces are added to the bridge $DEBUG openvpn --config /etc/openvpn/server.conf --port 5000 --daemon $DEBUG openvpn --config /etc/openvpn/server.conf --port 5001 --daemon Startup file S45firewallAt the moment when this script is executed all of the interfaces are setup correctly. The only part missing is prohibiting the access to the router from the WLAN, except for services needed to connect the OpenVPN server and get an IP address. There are too much changes to the original version of the firewall script so that my startup script replaces the original one. The original script is allways available in /rom. My script looks like this: #!/bin/sh
. /etc/functions.sh
WAN=$(nvram get wan_ifname)
WANIP=$(ifconfig $WAN | awk 'BEGIN {FS=" [^:]*:";} (NR==2) { print $2 ; exit; }')
LAN=$(nvram get vpnlan_ifname)
WLAN=$(nvram get wlan_ifname)
IPT=/usr/sbin/iptables
for T in filter nat mangle ; do
$IPT -t $T -F
$IPT -t $T -X
done
# set the new default action -> we have to allow explicitly
$IPT -P INPUT DROP
$IPT -t filter -A INPUT -m state --state INVALID -j DROP
$IPT -t filter -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# enable the OpenVPN server ports (script is created in S41openvpn and
# filled by the configuration scripts)
if [ -f /etc/tun-iptable-rules ]; then
. /etc/tun-iptable-rules
fi
# accept all from secure lan
$IPT -t filter -A INPUT -i $LAN -j ACCEPT
# enable DHCP and SSH access from wlan (uncomment if desired)
$IPT -t filter -A INPUT -i $WLAN -p udp --dport 67 -m state --state NEW -j ACCEPT
#$IPT -t filter -A INPUT -i $WLAN -p tcp --dport 22 -m state --state NEW -j ACCEPT
# drop everything else from wlan
$IPT -t filter -A INPUT -i $WLAN -m state --state NEW -j DROP
# accept icmps from wan and lan
$IPT -t filter -A INPUT -p icmp -j ACCEPT
# block all access from wan
$IPT -t filter -A INPUT -i $WAN -p tcp -j REJECT --reject-with tcp-reset
$IPT -t filter -A INPUT -i $WAN -j REJECT --reject-with icmp-port-unreachable
# pass through
$IPT -t filter -A FORWARD -m state --state INVALID -j DROP
$IPT -t filter -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
# block everything else wlan->wan
$IPT -t filter -A FORWARD -i $WLAN -j DROP
# forwarding ssh from outside (uncomment following block if desired
# and define SSHHost variable above)
#if [ "$(nvram get wan_proto)" = "pppoe" ]
#then
# $IPT -t nat -A PREROUTING -p tcp -i $WAN --dport 22 \
# -j DNAT --to-destination $SSHHost:22
#else
# $IPT -t nat -A PREROUTING -p tcp -i $WAN -d $WANIP --dport 22 \
# -j DNAT --to-destination $SSHHost:22
#fi
#$IPT -t filter -A FORWARD -p tcp -i $WAN -d $SSHHost --dport 22 \
# -m state --state NEW -j ACCEPT
$IPT -t filter -A FORWARD -i $WAN -m state --state NEW,INVALID -j DROP
$IPT -t filter -A FORWARD -o $WAN -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
$IPT -t nat -A POSTROUTING -o $WAN -j MASQUERADE
Configure dnsmasqFinally, we have to startup a DHCP service for the new and separate WLAN net. The request for an IP address will be the first contact a wireless client makes to the router. Therefore, you have to alter your /etc/dnsmasq.conf file. You have to add a dhcp-range line for the new net. In addition, you have to change the lan entry to separate the dhcp range from the addresses which are set fixed by the OpenVPN client-config files (that is why the upper bound is set to 99 in the first entry). . . # enable dhcp (start,end,netmask,leasetime) # one rage for the vpn lan (already existing entry) dhcp-range=192.168.1.10,192.168.1.99,255.255.255.0,24h # new range for the wlan net dhcp-range=192.168.2.2,192.168.2.254,255.255.255.0,24h . . First try and installationThe frame below shows where to put the mentioned files. To transfer the files it's easiest to have a ssh daemon installed, e.g. dropbear. Because it's always dangerous to change the startup configuration of the system, the system might be in an unusable state afterwards. I suggest to make a test of the configuration first. Rename the startup scripts so that their names start with something different than S, e.g. TS41opnvpn and TS45firewall. Checklist: Transfer all files to their intended locations. Make the mentioned configurations in the files on your router. Create all missing nvram entries. Test the installation and fix the configuration by renaming the startup scripts. File location tableFiles to install /etc/init.d/TS41openvpn /etc/openvpn/server.conf /etc/openvpn/my-ca.crt /etc/openvpn/dh1024.pem /etc/openvpn/server.crt /etc/openvpn/server.key /etc/openvpn/server-tun.up /etc/openvpn/server-config-dir/Client1 /etc/openvpn/server-config-dir/Client2 # copy S45firewall to TS45firewall Files to change/configure /etc/init.d/TS45firewall /etc/init.d/S50services /etc/dnsmasq.conf File attributes chmod rg+x /etc/init.d/TS41openvpn chmod go-rwx /etc/openvpn/server.key chmod rg+x /etc/openvpn/server-tun.up Test the configurationRestart the router and check if the time is set and if everything is working as before. The best way to test the configuration in this state is to connect your computer to a TP connector at the router. Start /etc/init.d/TS41openvpn. After that is done, your shell should be unusable, because this script is closing the interface that you are currently using. Start a new ssh/telnet connection to the router. Check the state of the bridge: #> brctl show
bridge name bridge id STP enabled interfaces
br0 8000.000xxxxxxxxx no vlan2
tap0
tap1
If eth2 is utilizing the bridge the script wasn't executed correctly. Check the execution permissions of the script. If the tap entries are missing, then the OpenVPN server couldn't start as expected. In this case, we can start it by hand and check if the server can say what's wrong. Check the process table and kill all openvpn processes (if there are some) and start one by hand: openvpn --config /etc/openvpn/server.conf --port 5000 --verb 3 Some additional checks should also be made: #> ifconfig eth2
eth0 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX
inet addr:192.168.2.1 Bcast:192.168.2.255 Mask:255.255.255.0
UP BROADCAST .....
#> ifconfig br0
br0 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX
inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST .....
If you connect a wireless client to the router, the client should get an IP address of the insecure range 192.168.2.0/24 set in dnsmasq.conf. OpenVPN Client configurationThe configuration of windows and linux clients is nearly the same. The difference is the configuration of the DNS service which must be switched to the secure net, this is a very unusual behavior. This is necessary because the DNS service is an outgoing service and might initiate a call to your ISP that cannot be admitted from the insecure wireless net. On windows clients, this configuration is done in the server.conf of the router, but this is a windows specific configuration. On linux clients, we have to use two scripts to do that work, "client-tun.up" and "client-tun.down". The common client configuration "client.conf"The following frame shows the common client configuration. Only the server port to be used, the location/names of the keys and certificates must be set, depending on the installation of OpenVPN. # the main behavior tls-client # the device to take for the connection dev tap # OpenVPN peer (server) remote 192.168.2.1 # and port (this port should only be used by a unique client machine) port 5000 # activate the device only if connected to the server up-delay # once the VPN is alive. (comment next two lines if you use this on a windows machine) up /etc/openvpn/linux-tun.up down /etc/openvpn/linux-tun.down down-pre # set the data obtained by the server pull # this is: route-gateway Setting DNS service on the client machinesThe change of the DNS service location of the linux machine is done by the linux-tun.up script which is shown below. This script saves the original resolv.conf and builds a new one where the router is set as a DNS server and the search entry is taken from the original resolv.conf:
#!/bin/bash
echo "###### linux-tun.up: $*"
PATH="/bin:/usr/bin"
RESOLV="/etc/resolv.conf"
if [ -f $RESOLV ] ; then
cp $RESOLV ${RESOLV}.openvpn
gawk '
BEGIN {
printf("nameserver %s\n", ARGV[2]);
ARGC = 2;
}
/^search/ {
print;
} ' ${RESOLV}.openvpn $route_vpn_gateway > $RESOLV
else
echo "nameserver $route_vpn_gateway" > $RESOLV
chmod a+r $RESOLV
fi
If the OpenVPN tunnel is going down. the original resolv.conf should be restored. This is done by the following script: #!/bin/bash
echo "###### linux-tun.down: $*"
PATH="/bin:/usr/bin"
RESOLV="/etc/resolv.conf"
if [ -f ${RESOLV}.openvpn ] ; then
cat ${RESOLV}.openvpn > $RESOLV
rm ${RESOLV}.openvpn
fi
Don't forget to set the execution bit of the up/down scripts! Windows ClientsTo avoid that windows is using the insecure wlan for netbios services you have to disable these services for your wlan network adapter. These services should be enabled only for the new virtual tap network adapter. Final OpenVPN testNow everything should be configured correctly. Test if everything works together. First start one server OpenVPN by hand. Now start the OpenVPN client on a wireless connected machine which uses the port provided by the server you just started. You should see the process of building the connection. Hopefully, the connection can be established ;-)) Generally, it should not be possible to build up an OpenVPN tunnel from the TP LAN. The firewall will block these requests, but this firewall configuration isn't activated yet. That's the reason why you should use a WLAN connection to check the building of the connection! I don't know what would happen if you try to connect from TP LAN. openvpn --config /etc/openvpn/server.conf --verb 3 If everything works fine rename the TS41openvpn to S41openvpn. After a reboot of the router everything should work as desired. Only blocking the WRT access, from the wireless lan, isn't activated yet. Activating the firewallAfter activating the firewall script by starting TS45firewall everything should proceed as it was. Try to connect to the router by using telnet or ftp on the insecure net (192.168.2.0/24). There shouldn't be any answer from the router because the request is eaten up by the firewall, i.e. the client is waiting and waiting for the answer and finally responding "Connection timed out". You should notice a difference if you try these services on the secure net (192.168.1.0/24). You should immediately get an answer even if it is "Connection refused". Finally check if it's still possible to get an external connection. If everything works fine move TS45firewall to S45firewall. This replaces the original startup script. DownloadI have tared everything together. The first file contains all configurations to be made on the WRT54G except certificates and keys. The second file is the linux client configuration. Follow the comments in the configuration file to transform it to a windows configuration file. Have a look at the changes section at the beginning of the page, in that case I have forgotten to update the archive files you have to do that by your own! ;-))DisclaimerAlthough I have made and documented everything with care there are probably some bugs on this page or in the downloads. This is the reason why I don't give any warranty of any kind! If you find a bug or if you have any suggestions for improvement or changes of the described configuration feel free to contact me! Cheers, Special thanksTo David Theriault for correcting the grammar of this document to make it more readable! |






