AVM has built a VPN server into the FRITZ!Box, why should I use some other software for this job, you may ask. The reason is quite simple: the build in one is a piece of closed source software written by AVM and there is only one official client which could be used to connect to it, the FRITZ!VPN software. This client software is only available for the Windows operation system family and so by no means anything useful to me. I’m pretty sure they are using some official protocol like IPSec, so it might be possible to connect to the FRITZ!Box with other clients as well, but that’s something I didn’t want to try. OpenVPN on the other side is a rock solid open source software which could be used from many popular OS’s these days. Even graphical clients, like TunnelBlick for Mac OS X, are available. So here comes the second article of the FRITZ!Box tuning series, which will explain how to convert your FRITZ!Box into a OpenVPN server, where any number of clients can concurrently be connected. I highly recommend to read the first part of this series, because this post is build on top of the stuff done there. This count especially for the filesystem layout on the usbstick and the way additional software is started. Also in the following it will be helpful to have ssh access to the FRITZ!Box all the time. As already written in the first part, there is no guarantee that the information presented here will work on your side or that I’m responsible for anything happen to your FRITZ!Box. In preparation of the following you need access to a second OpenVPN installation which will be used to create all necessary certificates and keys and which could be used to test the installation afterward. I’m using a Gentoo Linux host where you could install OpenVPN simply by executing emerge openvpn
. Make sure you have the examples USE flag set to get all the helper scripts which make the life much more easier.
The agony of choice
OpenVPN could be configured in many different ways. So first of all we have to decide which features of OpenVPN we will use. In its simplest variant OpenVPN could be used with one preshared static key. The advantage of this setup type is the easy configuration. The disadvantage is that only one client could be connected at the time. That is not what we want, so we will configure our setup to be using a Public Key Infrastructure (PKI). This allows more than one client to be connected at the time and it is possible to mark single keys invalid without affecting other client keys. The second question which has to be answered is, if we want use routing or bridging in our setup. Again, routing is simpler to set up and also a little bit faster than bridging. Bridging on the other side allows the tunneling of non IP protocols such as IPX, tunnel all the IP broadcast and make it possible to use the same subnet on the client side as on the server-side. Especially the last point is a nice feature as with routing all hosts on the server-side needs a routing table entry to find the connected clients. But my main reason for preferring bridging over routing is the broadcast feature of the first one. In my home network works a NAS station as a file server. This includes of course simple filesystem sharing with AFP and NFS, but also serves this box audio data with the Digital Audio Access Protocol (DAAP). DAAP is used by Apple in iTunes to share music with other clients in the network and that is what my NAS station does. This protocol, as well AFP, using broadcast messages (ZeroConf) to find some potential clients. So now it should be clear why I want bridging, it allows me to hear music or to simply connect to my file station without any interaction.
Building up a PKI
To create all necessary certificates and keys we are using the easy-rsa scripts from OpenVPN. They are located under /usr/share/openvpn/easy-rsa
. First we change the vars
file. On the bottom of the file are personal information defined which should be changed to fit to your environment. The entries looking as follow on my side (with a pseudo email address).
export KEY_COUNTRY="DE" export KEY_PROVINCE="Sachsen" export KEY_CITY="Dresden" export KEY_ORG="64k" export KEY_EMAIL="you@yourdomain.org"
You could also increase the KEY_SIZE from 1024 to 2048 within that file. This should make your keys unbreakable for the next few decades years. Now we are ready to create the master-key and the master certificate of the Certificate Authority (CA) by executing:
source vars ./clean-all ./build-ca
Please be aware that this will delete all previously created keys. Answering all questions with the default values should be sufficient. Next the key for the server has to be created.
./build-key-server server
You can again accept all default values. A challenge password is not necessary, but you have to sign the certificate. Now its time for our first client key and certificate. You could the following repeat again and again, for every new client you want allow to access the OpenVPN server.
./build-key client
Again, don’t forget to sign the key. If you ever have to mark a client certificate invalid you could do it with the following command:
./revoke-full client
This will create or update a Certificate Revocation List (CRL) file which will be later used by the server to verify the certificate integrity of a connecting client. For now we create an empty one with
KEY_CN="" KEY_OU="" KEY_NAME="" $OPENSSL ca -gencrl -out keys/crl.pem -config $KEY_CONFIG
The last step in this key building marathon is to create a Diffie-Hellman key. This key will be used to initiate the secure channel between the two parties. Its created by:
./build-dh
Creating the server and client configuration
We start with the configuration of the server:
# set the path to the tap device dev tap dev-node /var/tmp/tap0 mssfix tun-mtu 1500 # TCP or UDP server? proto udp port 1194 # CA and key files ca /var/media/ftp/FLASH-DISK-01/addons/openvpn/keys/ca.crt cert /var/media/ftp/FLASH-DISK-01/addons/openvpn/keys/server.crt key /var/media/ftp/FLASH-DISK-01/addons/openvpn/keys/server.key crl-verify /keys/crl.pem # this is opened after the chroot # Diffie hellman parameters dh /var/media/ftp/FLASH-DISK-01/addons/openvpn/keys/dh1024.pem # bridge setup server-bridge 192.168.220.1 255.255.255.0 192.168.220.50 192.168.220.99 mode server tls-server push "dhcp-option DNS 192.168.220.1" ifconfig-pool-persist ipp.txt client-to-client # compression? comp-lzo # The maximum number of concurrently connected clients we want to # allow. max-clients 20 # It's a good idea to reduce the OpenVPN daemon's privileges after # initialization. user nobody group nobody # Put openvpn in a jail. chroot /var/media/ftp/FLASH-DISK-01/addons/openvpn # The persist options will try to avoid accessing certain resources on # restart that may no longer be accessible because of the privilege # downgrade. persist-key persist-tun # where to log log-append /var/media/ftp/FLASH-DISK-01/addons/openvpn/log/openvpn.log # verbose level for debugging ;verb 4 # make sure the connection is kept alive keepalive 10 120
For bridged mode it is essential that OpenVPN uses a TAP device and not the TUN device mode (see here for the reason). We use UDP as the transport protocol and enable compression. Also we want that OpenVPN drops its privileges after the initialization and chroot into a jail to make it a little bit more secure. As the subnet for clients 192.168.220.0/24 is used. That is the same as my internal network uses. OpenVPN is allowed to use addresses ranging from 192.168.220.50 to 192.168.220.99. You have to make sure that the FRITZ!Box (or any other DHCP server in your network) doesn’t serve addresses from that range. Of course you could change some of the settings to your needs, but then you have to make sure they match the configuration of the client.
Next we create the client configuration, which looks as follow:
# Specify that we are a client and that we will be pulling certain # config file directives from the server. client # The hostname/IP and port of the server. remote xtestx.dyndns.org 1194 proto udp dev tap pull mssfix tun-mtu 1500 # SSL/TLS parms. tls-client ca keys/ca.crt cert keys/client.crt key keys/client.key ns-cert-type server # Keep trying indefinitely to resolve the host name of the OpenVPN # server. Very useful on machines which are not permanently connected # to the Internet such as laptops. resolv-retry infinite # Don't enable this; It must be disabled for iTunes to find the iTunes # server and for AFP broadcast in general. #nobind # Downgrade privileges after initialization (non-Windows only) user nobody group nobody # Try to preserve some state across restarts. persist-key persist-tun # Enable compression on the VPN link. comp-lzo # debug level ;verb 4 mute-replay-warnings mute 20
You have to change the remote hostname to your needs. You may also add the full path to the certificates and keys depending on your client OpenVPN installation.
Next we pack all files up for the server and the client respectively. The server needs the following one:
server.conf keys/ca.crt keys/crl.pem keys/dh1024.pem keys/server.crt keys/server.key
client.conf keys/ca.crt keys/client.crt keys/client.key keys/server.crt
Customizing the FRITZ!Box
Connect to your FRITZ!Box and copy all the server files to the usbstick. I created a directory openvpn
under the /var/media/ftp/FLASH-DISK-01/addons
path. Next we need the OpenVPN binary for the FRITZ!Box. You can get it here. Unpack the file and copy the openvpn binary to /var/media/ftp/FLASH-DISK-01/addons/bin
on the FRITZ!Box. Make sure the file mode has the executable bit set for the user. All files are now on the right places, so we can adjust our start script. Add the following code to the startup.sh
file.
# Add a nobody user echo 'nobody:x:65534:65534:nobody:/:/bin/false' >> /var/tmp/passwd # Add some groups echo 'root:x:0:' > /var/tmp/group echo 'nobody:x:65534:' >> /var/tmp/group # Create a tap device for openvpn mknod /var/tmp/tap0 c 10 200 # Start openvpn ${BASE}/openvpn/bin/openvpn --config ${BASE}/openvpn/server.conf --daemon
As you see, we add a new nobody user to the Linux system. Then the device node for the TAP device is created and at the end the OpenVPN server is started. As we using the bridged setup, we have to add the new device to a bridge. Fortunately we haven’t to create one, cause the FRITZ!Box itself is working in bridged mode. You can confirm this by executing:
brctl show lan
To let the system automatically add our TAP device to the lan bridge, we change the internal FRITZ!Box configuration. Edit the /var/flush/ar7.cfg
file with nvi and search for the string brinterfaces. There should be one section with the name lan. Simply add the new tap0 interface to the interfaces value. The section should then look like this:
brinterfaces { name = "lan"; dhcp = no; ipaddr = 192.168.220.1; netmask = 255.255.255.0; dstipaddr = 0.0.0.0; interfaces = "eth0", "ath0", "tap0", "wdsup1", "wdsdw1", "wdsdw2", "wdsdw3", "wdsdw4"; dhcpenabled = yes; dhcpstart = 192.168.220.100; dhcpend = 192.168.220.200; }
Now, as soon the tap0 interface is created it will be added to the bridge. The last important point in the server setup is to change the internal firewall to allow connections to port 1194 from the outside. Search for forwardrules in the ar7.cfg
file and add this new rule:
forwardrules = "tcp 0.0.0.0:7777 0.0.0.0:22 0 # SSH-Server", "udp 0.0.0.0:1194 0.0.0.0:1194 0 # VPN-Server";
Thats all for the server. A reboot of the FRITZ!Box should start the new OpenVPN server. If you have trouble you should manually start the OpenVPN server and increase the debugging level, as shown in the above configuration with the keyword verb.
Setting up the client
On the client side we need the files we packed above. On Gentoo the OpenVPN configuration is located at /etc/openvpn
. Copy the configuration, the certificates and the key file to that place. The OpenVPN start script of Gentoo looks for the configuration file, based on the start script name. So we have to create a link like this:
cd /etc/openvpn ln -s client.conf openvpn.conf
By the way, this lets you configure more than one OpenVPN connection at the time. Just create a link in /etc/init.d
with the new configuration name and link it to the openvpn
start script.
To make a first attempt to start the OpenVPN connection type
/etc/init.d/openvpn start
If all goes well you should have a new device tap0 when you execute ifconfig
. Also there should be a route set, which point to the tap0 device when the 192.168.220.0/24 subnet is the target. Of course now you should be able to connect to any host in your home network by the IP. I didn’t experiment enough with the pushing of the name server from the OpenVPN server, instead I just added the FRITZ!Box as an additionally name server to my /etc/resolv.conf
. So here is room for further experiments.
To let the OpenVPN client start at boot time add it to the default runlevel by executing:
rc-update add openvpn default
Also note that with the above configuration the client always try to reconnect to the server, even if the FRITZ!Box is rebooted, which is a nice feature.
Conclusion
This setup allows you to connect to your home network in a very secure way without loosing any functionality. You are able to browse network shares on the local network or using services like DAAP without any further interaction. The public key infrastructure make this setup a candidate for small business installations. If an employee leave the company his certificate is simply revoked without affecting the access of other employees.
Hi,
this won’t work with Fritz!Box 7270 until you deactivate Wlan.
Otherwise the box will reboot if a client connects.
greets Jan
Hi Jan,
I wouldn’t say that this doesn’t work, cause I use it all day (with activated WLAN). Connecting with clients from an external network shows no problem. But you are right that there are problems with the net80211 kernel module of the FRITZ!Box. If one try to connect from the internal network to a connected client, this kernel module panics, which is followed by an reboot. For me this seems a bug in the FRITZ!Box firmware. I didn’t really tried to understand whats wrong there or even to fix it, cause it didn’t bother me really much. But maybe there should be done a bug report to AVM.
Christian
I reported it to AVM. Unfortunately they didn’t handle Bug-Reports for modified FRITZ!Box firmwares. So it seems we have to live with it. The problem is also discussed here (in German).
Hi,
I try this configuration, but when i want to start Openvpn on the Fritz!box, it’s say : “bus error”.
Greets
Sylvain
Hi Sylvain,
I guess you are not having a FRITZ!Box 7270 or your firmware isn’t the newest one. The older versions have older kernels and a older glibc. You could try to use this one. Another way is to compile a version yourself with the help of freetz.
Christian
Thank Christian,
I solved my problem. openvpn file was corrupted by the transfer FTP between my pc and the fritz! box.
I try to make a vpn between my fritz! Box and a SIP telephone snom SP 820.
This phone is a client vpn openvpn which should allow me to secure and troubleshoot NAT when using a SIP client from the internet.
Sylvain
When I power off ->power on the Fritz!Box I have to copy again the startup.sh and ar7.cfg (from the usb media attached). Is that legit ? Is there a way I can save the changes permanently ?
Thanks in advance! (and much obliged ..overall)
George
Hi George,
You have to use
nvi
for editingar7.cfg
and add the full path of the script (on the usb stick) to/var/flash/debug.cfg
. It’s described in detail here.Chris
It’s all false, if you try to use OpenVPN in bridge mode with tap interface created and WLAN on FritzBox 7270v2 will start to restart periodically as soon as WLAN interface will try to transmit anything through!!!
Of course for example 7170 doesn’t have this problem.
http://www.ip-phone-forum.de/archive/index.php/t-230138.html?s=b008bb7c575b40435c684e214a8bec65
I’ve documented my success at using vpnc (Open Source VPN client) to connect to my Fritz!Box devices at http://blog.mithis.net/archives/useful-bits/1833-connecting-to-a-fritzbox-under-linux-using-vpnc
Using OpenVPN is probably a better solution, but mine doesn’t require you to modify your Fritz!Box in any way.