Here I have made an ascii art how it should work.
10.10.10.2 +----------+ 10.10.10.1
/ vpn-tunnel | | \
bridge (tun0) =============\\ //========================\\
DEVICE ~.~.> ROUTER -------> (eth1)RPI(eth0) ------------> PROXY <---> | INTERNET | <---> VPN-SERVER
\ wifi D ethernet / \ ethernet / wan | | wan /
(by dhcp) H 192.168.1.1 192.168.10.60 192.168.10.1 +----------+ 62.155.246.85
C
P
The RPi works as a router. Its port eth1 is on the same subnet than all other devices because it is bridged to the wifi on the router. The RPi needs a static ip address on eth1 because it must be addressed as default gateway to the vpn tunnel. The Raspberry Pi B2 has no build in wifi so we need the router.
Setting up a VPN is out of scope here. I assume you can start a VPN client on the RasPi and get a connection to the VPN server with interface tun0.
For the first setup you should also don't set any rules in iptables and leave it complete transparent. iptables is a firewall and only restrict connections. When the network is running then you can setup your firewall step by step.
I use systemd-networkd because the setup is somewhat sophisticated and I think it is the best choise for it.
For reference I use Raspbian Stretch Lite 2018-06-27 updated with sudo apt update && sudo apt full-upgrade && sudo reboot
.
Setup systemd-networkd
For detailed information look at (1). Here only in short. Execute these commands:
# disable classic networking
rpi ~$ sudo -Es
rpi ~# systemctl mask networking.service
rpi ~# systemctl mask dhcpcd.service
rpi ~# sudo mv /etc/network/interfaces /etc/network/interfaces~
rpi ~# sed -i '1i resolvconf=NO' /etc/resolvconf.conf
# enable systemd-networkd
rpi ~# systemctl enable systemd-networkd.service
rpi ~# systemctl enable systemd-resolved.service
rpi ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
Configure static interfaces
Setup
There are two static interfaces eth0 and eth1 given by the hardware. We configure them by creating these two files. You can just copy and paste this in one block to your command line beginning with cat and including EOF (delimiter EOF will not get part of the file):
rpi ~# cat > /etc/systemd/network/04-eth0.network <<EOF
[Match]
Name=eth0
[Network]
Address=192.168.10.60/24
IPForward=yes
[Route]
Gateway=192.168.10.1
Destination=62.155.246.85/32
PreferredSource=192.168.10.60
EOF
rpi ~# cat > /etc/systemd/network/08-eth1.network <<EOF
[Match]
Name=eth1
[Network]
Address=192.168.1.1/24
EOF
Details
You must configure the DHCP server on the router to give the default gateway 192.168.1.1 to its devices otherwise routing will not work. Because we want to route traffic from eth1 to eth0 and further on we have to enable ip forwarding.
We need the public ip address from the vpn server in the internet because we will connect our vpn tunnel to it. But we set the destination ip address with prefix /32
so that packets only to the vpn server will go to the proxy as next hop. All other destination ip addresses must go through the vpn tunnel, means the default route will be set to the end of the tunnel (see later).
Configure virtual private network
Setup
We need two systemd units for the dynamic virtual interface tun0. For example I use openvpn
to create the virtual private network. First start the program. Create a new unit with:
rpi ~# systemctl edit --force virtual-private-network.service
In the empty editor insert these statements, save them and quit the editor:
[Unit]
Description=virtual private network
After=network.target
Wants=network.target
[Service]
WorkingDirectory=/etc/openvpn/client
ExecStart=/usr/sbin/openvpn ovpn.conf
[Install]
WantedBy=network.target
Next unit is for NAT (masquerade) and for setting the default route if needed:
rpi ~# systemctl edit --force masquerade-tun0.service
In the empty editor insert these statements, save them and quit the editor:
[Unit]
Description=masquerade tun0
PartOf=virtual-private-network.service
[Service]
Type=oneshot
RemainAfterExit=yes
# check if tun0 is available otherwise startup must fail
ExecStart=/bin/bash -c '/sbin/ip link show dev tun0 >/dev/null'
ExecStartPost=/sbin/ip route add default via 10.10.10.1 dev tun0
ExecStartPost=/sbin/iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
ExecStopPost=/sbin/iptables -t nat -D POSTROUTING -o tun0 -j MASQUERADE
ExecStopPost=/sbin/ip route del default via 10.10.10.1 dev tun0
[Install]
WantedBy=sys-subsystem-net-devices-tun0.device
Enable the new services:
rpi ~# systemctl enable virtual-private-network.service
rpi ~# systemctl enable masquerade-tun0.service
Reboot.
That's it.
Details
You can edit the units again with:
rpi ~$ sudo systemctl edit --full virtual-private-network.service
rpi ~$ sudo systemctl edit --full masquerade-tun0.service
First we have to start the VPN client with systemd. I have tried not to do it and start it otherwise but then systemd has problems to check the status of the virtual dynamic interface tun0 we need for network address translation (NAT - masquerade). The unit virtual-private-network.service does not do any special. It just starts the VPN client. You can simply adjust ExecStart=
and the environment to start your VPN client.
Because of the nature of systemd it is not possible to ExecStartPost=
NAT (masquerade) together with startup of openvpn in virtual-private-network.service. It starts openvpn and goes on but it takes a time until tun0 is up. ExecStartPost=
will fail complaining tun0 doesn't exist. So we have to make another unit that depends on the existing interface.
I assume there is no possibillity to configure the VPN server and setup up static routes there. Then we have to fake it whith NAT so it believes that all packets come from the RasPi. We do it with the unit masquerade-tun0.service. Essential is the entry WantedBy=sys-subsystem-net-devices-tun0.device
. It binds the unit to the dynamic interface tun0. You can find this .device
simply with systemctl
when its up. We also set the default route because all traffic shall go through the VPN tunnel. Please look with ip route show
what routes your VPN client sets. If it already sets the default route through the tunnel then you should not set it again in masquerade-tun0.service. The unit also cleans up the settings when the VPN client is stopped. You can now start/stop the VPN client with:
rpi ~$ systemctl [stop|start|restart] virtual-private-network.service
references:
[1] Howto migrate from networking to systemd-networkd with dynamic failover