2

My access point spawns a wireless local area network. Now I want to connect it to my other private network over the internet with openvpn so it gets direct part of the remote network in a common broadcast domain using the same ip address range and the DHCP server on the remote network. I know I have to use a tap interface instead of a tun interface on openvpn for this but how to setup the other components?

1
  • @RobinDinse In a comment on another question you asked for a very interesting setup here. I see some quirks with it. I have made this question and answer so we can better work on its solution.
    – Ingo
    Commented Mar 18, 2019 at 22:29

1 Answer 1

3

Example for this setup:

               bridge                                     ┌──────────┐                             bridge
              ┌───────┐            vpn-tunnel             │          │                            ┌───────┐ 192.168.179.1
              │ (tap0)│════════════════════════╗  ╔═══════╪══════════╪═══════╗  ╔═════════════════│(tap0) │╱
        wifi  │    br0│RPi(wlan1) <.~.~.~.~.> router <───>│ INTERNET │<───> router <─> (eth0)VPN- │    br0│  wifi
phone <~.~.~.>|(wlan0)│         ╲     wifi    ╱       wan │          │ wan  ╱               server|(wlan0)│<~.~.~.> DHCP-
    ╲         └───────┘ 192.168.50.X       192.168.50.1   │          │   <public-ip>              └───────┘         server
192.168.179.X           (dhcp local)                      ╰──────────╯
(dhcp remote network)

The advantage of openvpn is that it is independent from the underlaying network setup, no matter if you use dhcpcd, /etc/network/interfaces or systemd-networkd. It only needs a connection to the VPN-server and interfaces that can be added to a bridge as slaves. For this example I will use systemd-networkd because it has everything built-in and we do not need additional programs. To show the setup of the VPN-server I will use a RPi 3B so you can take it as template for setting up your own VPN-server based on an other hardware.

This example is made for Raspberry Pi to be used in a home environment to be as simple as possible. It uses a peer to peer VPN tunnel (mode p2p) with static preshared encryption keys. This simplyfies the setup a lot but you can only connect one client to the VPN-server. If you need a second one you can setup a second instance of the VPN-server (maybe a third one?). But if you need more clients to connect to the VPN-server, e.g. in an enterprise environment, you have to setup a PKI (public key infrastructure) with a master Certificate Authority (CA) to be used for a client/server VPN tunnel (mode server). This is much more complicated and not an issue here 2.

You need a connection from the RasPi to the VPN-server. Configuring it, for example with DynDNS, port forwarding and routing is out of scope here. You should have setup it before starting.

For reference I use Raspbian Stretch Lite 2018-11-13, updated with sudo apt update && sudo apt full-upgrade && sudo reboot on 2019-04-01.

♦ Set up the VPN-server

Do ♦ General Setup then create this file to configure openvpn:

rpi ~# cat > /etc/openvpn/server.conf <<EOF
dev tap0
mode p2p
secret static.key
cipher AES-256-CBC
EOF

Create these files to setup the bridge:

rpi ~# cat > /etc/systemd/network/02-br0.netdev <<EOF
[NetDev]
Name=br0
Kind=bridge
EOF

rpi ~# cat > /etc/systemd/network/04-eth0.network <<EOF
[Match]
Name=eth0
[Network]
# Use your own static ip addresses for the VPN-server
Address=192.168.50.2/24
Gateway=192.168.50.1
DNS=84.200.69.80 84.200.70.40
EOF

rpi ~# cat > /etc/systemd/network/12-br0_add-slaves.network <<EOF
[Match]
Name=tap0
[Network]
Bridge=br0
EOF

rpi ~# cat > /etc/systemd/network/16-br0_up.network <<EOF
[Match]
Name=br0

[Network]
Address=192.168.179.1
# Don't use the next lines if there is already a dhcp server running
DHCPServer=yes

[DHCPServer]
PoolOffset=129
DNS=84.200.69.80 84.200.70.40
EOF

To configure wpa_supplicant to be used as access point create this file:

rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="RemoteNet"
    mode=2
    key_mgmt=WPA-PSK
    proto=RSN WPA
    psk="verySecretPassword"
    frequency=2437
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl enable [email protected]

Now we have to tell wpa_supplicant to use a bridge. We do it by modifying its service with:

rpi ~# systemctl edit [email protected]

In the empty editor insert these statements, save them and quit the editor:

[Service]
ExecStartPre=/sbin/iw dev wlan0 set type __ap
ExecStartPre=/bin/ip link set wlan0 master br0

ExecStart=
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -Dnl80211,wext -i%I -bbr0

ExecStopPost=-/bin/ip link set wlan0 nomaster
ExecStopPost=-/sbin/iw dev wlan0 set type managed

Reboot.

♦ Setup the VPN-client

Before starting with setup you should first check if you can connect from the RasPi to the VPN-server on the internet. Your VPN-server has the <public-ip> (e.g. 93.93.128.230):

rpi ~$ ping -c4 <public-ip>

# check if openvpn is reachable on its default UDP port 1194
rpi ~$ nc -vz -u <public-ip> 1194
Connection to <public-ip> 1194 port [udp/openvpn] succeeded!
rpi ~$

Then do ♦ General Setup and create this file to configure openvpn:

rpi ~# cat > /etc/openvpn/client.conf <<EOF
dev tap0
mode p2p
remote <public-ip> 1194 udp
secret static.key
cipher AES-256-CBC
EOF

Create these files to configure the interfaces:

rpi ~# cat > /etc/systemd/network/08-wlan1.network <<EOF
[Match]
Name=wlan1
[Network]
DHCP=yes
#[DHCP]
#UseRoutes=no
EOF

rpi ~# cat > /etc/systemd/network/12-tap0.network <<EOF
[Match]
Name=tap0
[Network]
DHCP=yes
[DHCP]
UseRoutes=no
EOF

In the example above the default route is set to the local router, so the internet traffic isn't routed through the VPN tunnel. If you want to send internet traffic through the tunnel to use an internet router on the remote side, then just toggle commenting of [DHCP] and UseRoutes=no.

To setup the client connection of wpa_supplicant create this file:

rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan1.conf <<EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="TestNet"
    psk="verySecretPassword"
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan1.conf
rpi ~# systemctl enable [email protected]

Reboot.

Now the tap interface has an ip address from the subnet 192.168.179.0/24 and you can ping 192.168.179.1:

rpi ~$ ip -4 addr show dev tap0
5: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    inet 192.168.179.211/24 brd 192.168.179.255 scope global dynamic tap0
       valid_lft 2387sec preferred_lft 2387sec


♦ Bridge client access point to the VPN tunnel

Create these files to setup the bridge:

rpi ~$ sudo -Es
rpi ~# cat > /etc/systemd/network/02-br0.netdev <<EOF
[NetDev]
Name=br0
Kind=bridge
EOF

rpi ~# cat > /etc/systemd/network/12-tap0.network <<EOF
[Match]
Name=tap0
[Network]
Bridge=br0
EOF

rpi ~# cat > /etc/systemd/network/16-br0_up.network <<EOF
[Match]
Name=br0
[Link]
MACAddress=22:6f:e8:92:70:04
[Network]
DHCP=yes
[DHCP]
UseRoutes=no
EOF

Because a bridge is always given the same MAC address, we need to give br0 another unique one to differ it from the bridge on the VPN server.

In the example above the default route is set to the local router, so the internet traffic isn't routed through the VPN tunnel. If you want to send internet traffic through the tunnel to use an internet router on the remote side, then just toggle commenting of [DHCP] and UseRoutes=no in 08-wlan1.network and 16-br0_up.network.

To configure wpa_supplicant to be used as access point create this file:

rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="ClientNet"
    mode=2
    key_mgmt=WPA-PSK
    proto=RSN WPA
    psk="verySecretPassword"
    frequency=2437
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl enable [email protected]

Now we have to tell wpa_supplicant to use a bridge. We do it by modifying its service with:

rpi ~# systemctl edit [email protected]

In the empty editor insert these statements, save them and quit the editor:

[Service]
ExecStartPre=/sbin/iw dev wlan0 set type __ap
ExecStartPre=/bin/ip link set wlan0 master br0

ExecStart=
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -Dnl80211,wext -i%I -bbr0

ExecStopPost=-/bin/ip link set wlan0 nomaster
ExecStopPost=-/sbin/iw dev wlan0 set type managed

Reboot.

Now you can connect to the access point ClientNet with your phone and get an ip address from the DHCP server on the RemoteNet far away. The phone is now member of the broadcast domain RemoteNet with all its resources so as it would be direct connected to it.

♦ General Setup

Switch over to systemd-networkd

Execute these commands:

# Install openvpn and helper to speed up getting random numbers for encryption
rpi ~$ sudo -Es
rpi ~# apt install openvpn openvpn-systemd-resolved rng-tools

# disable classic networking
rpi ~# systemctl mask networking.service dhcpcd.service
rpi ~# 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 systemd-resolved.service
rpi ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Create static key for encryption

On a openvpn device (client or server) generate a static secret key. Don't generate it two times. Use only one static.key.

rpi ~# openvpn --genkey --secret /etc/openvpn/static.key

Copy /etc/openvpn/static.key over to the openvpn device on the other end (client or server) to /etc/openvpn/static.key with same permission (sudo chmod 600 /etc/openvpn/static.key) so you have the same key available on the client and server.

Go back where you come from and continue the setup.


References:
(1): My-Tiny.Net - Virtual Private Networks
(2): openvpn - How To
(3): openvpn - Static Key Mini-HOWTO
(4): openvpn - Ethernet Bridging

5
  • @RobinDinse I have finished the answer to your question about bridging your smartphone to a remote network with openvpn.
    – Ingo
    Commented Apr 1, 2019 at 23:03
  • at the beginning where you switch over to systemd-networkd, would this be for both hotspot and server? my hotspot is already using systemd-networkd but not my raspberry server. Also, the instructions under the "Set up VPN-Server" you create the wpa_supplicant file for the client? shouldn't this part be ni the "set up the VPN-client"? unless your hotspot is also the server?
    – Agustin
    Commented Nov 11, 2019 at 0:13
  • @Agustin Both the server setup section and the client setup section refer to use General Setup first. I have reordered the sections to make it clearer. The client connects to its router with a WiFi client connection. The server presents also a hotspot. That is the setup shown in the drawing. When I refer to your question Setting up Bridged VPN using: RPi 3G Hotspot router + openvpn client to connect to home RPi OpenVPN server it may not direct fit your needs.
    – Ingo
    Commented Nov 11, 2019 at 10:19
  • @Agustin This bridging setup here is a complete different task and a bit more complex. You should first finish your first setup using routing.
    – Ingo
    Commented Nov 11, 2019 at 10:29
  • @Agustin You have asked for the server configuration at raspberrypi.stackexchange.com/questions/108217/…. The hotspot on the server side (right side of the drawing) is only an example. You can also use a wired subnet there. Because we "merge" two subnets (left side with right side of the drawing) I need to have a subnet on the server for demonstration. I chose a wireless one. About the connection to UDP port 1194: have you tested it wit nc as described in section ♦ Setup the VPN-client?.
    – Ingo
    Commented Feb 17, 2020 at 9:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.