OpenVPN bridge
To setup OpenVPN, there are really multiple variations. My main objective is very simple: I have hosts on several locations, where I run OpenVPN, and I would like to automatically being able to appear as having an IP address on those hosts. That is, by connecting to specific ports on my router, all my network traffic will appear as originating in one of those hosts.
This goal is better achieved by setting a OpenVPN bridge (as opposed to the more simple point to point tunnel approach). Security requires using a static key, or SSL/TLS + certificates for authentication and key exchange. For my objective, it is enough to use a static key, much simpler to setup.
The setup requires multiple steps, to setup VPN on the remote (server) side, and on the router (client) side. Note that the final client -any device connected to the router- requires no setup at all.
Configure remote server for VPN
This configuration obviously depends on the server, which in this case runs Debian. To just slightly beef up the security, we will use port 11943 instead of the default 1194 (using UDP).
To install openVPN, the server must support TUN/TAP devices. I use a VPS based on OpenVZ which lacked this support, so I had to request its inclusion to my hosting company, who obliged very quickly (the second host I use -also VPS / OpenVZ- turned my request off, which says plenty on the options that I will renew my plan with them).
sudo apt-get update sudo apt-get install openvpn
generate now the static key:
cd /etc/openvpn sudo openvpn --genkey --secret static.key
And configure the tun device:
sudo vi /etc/openvpn/tap0.conf
In this file, we enter the following contentto create a network on 10.192.168.x, where the server is itself 10.192.168.1. Note that the communications will use UDP on port 11493:
dev tap0 ifconfig 10.192.168.1 255.255.255.0 port 11943 proto udp secret /etc/openvpn/static.key script-security 3 keepalive 10 120 persist-key persist-tun comp-lzo status /var/log/openvpn-status.log verb 3
Some details are very important here. If you miss in this configuration the persist-tun line, the tun device can be reset every two minutes (as defined by the keepalive directive). In that case, the device is effectively taken down and up again. If you happen to have a dhcp server listening on that device, it will report that the network is down and will just stop serving DHCP requests.
The setup can now be tested with:
sudo openvpn --config /etc/openvpn/tap0.conf --verb 6 sudo ifconfig
The first line will fail if there is no TAP device support. If everything goes ok, the secon line will show a device tap0 with address 10.192.168.1.
In debian, installation of openvpn sets it up as a service, and it will automatically use the created configuration file /etc/openvpn/tap0.conf, so it is effectively sufficient to enter:
sudo service openvpn restart
Configure OpenVPN on OpenWrt router
We assume now than OpenVPN is installed, either as compiled in the image, or installed as a package. As reported, the TL-841N has not memoty enough to support the package option, so I had to compile it in the image.
First thing: get the static.key file that we created on the server, and copy it in the router as /etc/openvpn/static.key. This file should be chmod 600:
chmod 600 /etc/openvpn/static.key
configure now the tap device
vi /etc/openvpn/tap0.conf
And enter the following content to create a network on 10.192.168.x
remote YOUR_SERVER_IP_ADDRESS #the public IP address of the server dev tap0 ifconfig 10.192.168.2 255.255.255.0 port 11943 proto udp secret /etc/openvpn/static.key keepalive 10 120 persist-key persist-tun resolv-retry infinite mute-replay-warnings comp-lzo verb 3
Test it now doing:
openvpn --config /etc/openvpn/tap0.conf --verb 6
Now, the VPN connection between the server and the router is already working; it can be tested the connection doing:
ping 10.192.168.1
NOTE: It could possibly not work if you have some firewall / iptables rules etc setup on your router. In that case, it is obviously needed to open the required ports for VPN communication.
Once the configuration is tested okay, we can enable the OpenVPN connection from startup by editing the file /etc/config/openvpn:
vi /etc/config/openvpn
That should contain:
config openvpn custom option enabled 1 option config /etc/openvpn/tap0.conf
To test it, try now rebooting. Doing then on the router:
ifconfig
should show the tap0 connection. And doing ping 10.192.168.1 should work as well
Create the bridge on the router
An assumption now is that the device has been split into several virtual interfaces (vlans). This is not strictly required, but helps with the setup, by allowing us to login in the router (the ports allocated to the bridge will connect us directly to the VPN server).
When created the virtual interface for the router, I had configured it as (file /etc/config/network):
config interface 'landenver' option ifname 'eth1.2' option type 'bridge' option proto 'static' option ipaddr '192.168.2.1' option netmask '255.255.255.0'
But to use this virtual interface as a VPN bridge, we need to change slightly this configuration, into:
config interface 'landenver' option ifname 'eth1.2' option proto 'static' option ipaddr '192.168.2.1' option netmask '255.255.255.0'
Not including the option type bridge line, means that no ifname will be created for this virtual lan. Note also that the changes we had included on the router's file /etc/config/dhcp related to interface landenver can be commented out, as the router will not be serving any DHCP leases on this interface.
The router contains in this moment two interfaces (tap0 and eth1.2) that we want to bridge. This is achieved by entering:
brctl addbr br0 brctl addif br0 tap0 brctl addif eth1.2
Ready now to bring the VPN up:
ifconfig br0 up
NOTE: if you are connected to the router via any port allocated to the VLAN, you will lose now connection to the router; to continue working on the router you need therefore to connect now to other port on a separate VLAN.
The bridge can be easily tested now on any client attached to the router (on a port of the VLAN).On that client, allocate a static address on the VPN:
ifconfig eth0 10.198.168.201
So the client attached to the router can now directly ping the server:
ping 10.198.168.1
For this configuration to be permanent, we create in the router the file /etc/init.d/vpn-bridge as the following script:
#!/bin/sh /etc/rc.common START=96 SERVICE_DAEMONIZE=1 SERVICE_WRITE_PID=1 start() { stop ifconfig tap0 &> /dev/null || sleep 1 ifconfig tap0 &> /dev/null || sleep 1 ifconfig tap0 &> /dev/null || sleep 1 ifconfig tap0 &> /dev/null || sleep 1 ifconfig tap0 &> /dev/null || sleep 1 brctl addbr br0 brctl addif br0 tap0 brctl addif br0 eth1.2 ifconfig br0 up } restart() { start } shutdown() { stop } stop() { ifconfig br0 &> /dev/null || return ifconfig br0 down brctl delbr br0 } reload() { restart }
And setup the rc.d links:
chmod +x /etc/init.d/vpn-bridge cd /etc/rc.d ln -sf ../init.d/vpn-bridge S98vpn-bridge
Now the bridge is configured and brough up on startup.
Get connected
A client connected to the router is now on the same VPN as the remote server. But unless there is a DHCP daemon on the server, the client will have no IP address (ergo no real connection).Assigning a static address is not good -we want the client to be attached to different networks depending on the chosen rooter port, and we want it to be automatic-. The router itself is not envolved here anymore: it should be now a transparent tunnel between both ends: each of our client devices and the remote server.
So what is needed is the server providing the IP address to the client. Furthermore, we will need to setup the server so that all traffic coming from the VPN tunnel appears as coming from the server itself, to ensure full internet conectivity.
To provide the IP address, it is needed to have a DHCP daemon on the server. In my case, my VPS has a static IP address, but there could be already a DHCP server on the network. Never minds, we execute our own daemon serving IP addresses for the created VPN. In Debian, install the DHCP server as:
sudo apt-get install isc-dhcp-server
We ensure now that it serves the tap0 interface:
sudo vi /etc/default/isc-dhcp-server
and modify the line INTERFACES to contain:
INTERFACES="tap0"
Then, the file /etc/dhcp/dhcpd.conf needs some content like:
ddns-update-style none; option domain-name "codingnight.net"; option domain-name-servers 8.8.8.8, 8.8.4.4; default-lease-time 43200; max-lease-time 86400; authoritative; log-facility local7; subnet 10.192.168.0 netmask 255.255.255.0 { range 10.192.168.100 10.192.168.150; option subnet-mask 255.255.255.0; option broadcast-address 10.192.168.255; option routers 10.192.168.1; }
In this way, it will serve IP addresses on the created VPN network in 10.192.168.x
To ensure that traffic appears as coming from the server:
echo 1 > /proc/sys/net/ipv4/ip_forward
And we do this change persistent by editing the file /etc/sysctl.conf and ensuring it contains:
net.ipv4.ip_forward = 1
The last step is to update the iptables; in my OpenVZ VPS, the ethernet driver is virtualizes as venet0, so it is needed:
iptables -t nat -A POSTROUTING -s 10.192.168.0/24 -o venet0 -j MASQUERADE iptables -F FORWARD iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -s 10.192.168.0/24 -j ACCEPT iptables -A FORWARD -j DROP
And we do the change persistent by entering:
iptables-save > /etc/iptables.up.rules
If no previous iptables rules were defined, it is needed to create the file /etc/network/if-pre-up.d/iptables with the following content:
#!/bin/bash /sbin/iptables-restore < /etc/iptables.up.rules
And chmod it:
sudo chmod +x /etc/network/if-pre-up.d/iptables
Now, it is enough to start the DHCP server:
sudo service isc-dhcp-server start
Presto!, any client attached to the router should receive now an IP address from the VPN server -assuming the clients are configured to receive such IP address automatically!