I’m using my raspberry pi as a NAS with a samba server to provide the content through my home network. I wanted to have that content directly accessible from the rest of the world but without the traffic to be visible to anybody else than me. I then decide to use OpenVPN TAP in bridged mode.
OpenVPN Tap: Setup
- TL-841 as router
- Raspberry Pi as NAS
- Internal IP : 192.168.42.0/24
- Range IP router: 192.168.42.10 – 192.168.42.120
- Range IP OpenVPN: 192.168.42.128 – 192.168.42.254
- OpenVPN version: 2.4
Preparation
First, important point, if you have a DHCP server on your router, be sure to configure it to not assign IP address for the whole subnet, but only a part (as I’ve done in the setup). If you don’t, you could encounter 2 devices sharing the same IP, and trust me you don’t want that.
Download scripts/conf
You need to download and extract my scripts and configuration. I’ll walk you through each of those. The following command will download the files and extract them into /tmp/openvpn-scripts:
wget -O /tmp/master.zip https://gist.github.com/Belphemur/3b03eaad96172b2159fc/archive/master.zip && mkdir /tmp/openvpn-scripts && unzip /tmp/master.zip -d /tmp/openvpn-scripts/
Explanation of the command: Wget download the gist on GitHub with my scripts then mkdir create a temporary directory where unzip extract them. I advise you to run it WITHOUT root or sudo it is not needed.
Installing OpenVPN
sudo apt-get install openvpn
Enable TLS
We need the easy-rsa to easily create our root certificate, the certificate of the server and the one for each client. Using those cert, the client will authenticate themselves to the server. No need for login/password.
On Wheezy:
mkdir /etc/openvpn/easy-rsa sudo cp -R /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa/
On Jessie:
sudo apt-get install easy-rsa sudo mkdir /etc/openvpn/easy-rsa sudo cp -R /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
On Stretch:
sudo apt-get install easy-rsa sudo mkdir /etc/openvpn/easy-rsa sudo cp -R /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/ sudo ln -s /etc/openvpn/easy-rsa/openssl-1.0.0.cnf /etc/openvpn/easy-rsa/openssl.cnf
Configuring TLS
Edit /etc/openvpn/easy-rsa/vars bottom according to your organization.
Look for those in the file and change them for your needs.
export KEY_COUNTRY="US" export KEY_PROVINCE="CA" export KEY_CITY="SanFrancisco" export KEY_ORG="Fort-Funston" export KEY_EMAIL="mail@domain" export KEY_EMAIL=mail@domain export KEY_SIZE=4096
Now execute those command to prepare for the generation of the certificate and keys:
cd /etc/openvpn/easy-rsa/ sudo -s #because of the sourcing of the ./vars file you need to be root to do this mkdir keys touch keys/index.txt echo 01 > keys/serial . ./vars # set environment variables ./clean-all
From Debian wiki on OpenVPN:
Remember:
- only .key files should be kept confidential.
- .crt and .csr files can be sent over insecure channels such as plaintext email.
- do not need to copy a .key file between computers.
- each computer will have its own certificate/key pair.
Generating the certs and keys
Those commands will generate the root certificate, the server certificate and the DH keys. I give two choices to generate the DH Param, either you use your own machine or DHTool free service.
Generate DH Param yourself
cd /etc/openvpn/easy-rsa/ ./build-ca ./build-key-server server ./build-dh #takes time
Use DHTool service
Read more about DHTool on this blog post: Public Diffie-Hellman Parameter Service/Tool
cd /etc/openvpn/easy-rsa/ ./build-ca ./build-key-server server curl https://2ton.com.au/dhparam/${KEY_SIZE} > ${KEY_DIR}/dh{$KEY_SIZE}.pem
Disabling Current Systemd Service
By default when you’re installing the OpenVPN server, the installer take care of setting OpenVPN to start with your system.
We don’t want that since you’re installing another service configuration that takes care of the Bridge.
sudo systemctl disable openvpn sudo systemctl stop openvpn
Packet Forwarding
Because we’re going to create a bridge, we need to set the kernel to let the IP packet transit through it. To do this, we’ll use sysctl.
You’ll need to edit the file /etc/sysctl.conf
to add the following line: net.ipv4.ip_forward = 1
Then you reload the configuration: sysctl -p /etc/sysctl.conf
The packet switching is not set in your kernel and will stay after reboot.
Bridge Scripts
Following the OpenVPN tutorial on how to create a bridge and make it work with OpenVPN, I created my own scripts to do this. First, you need to install the bridge-utils, scripts used to create network bridge then create a directory to put my scripts into it.
sudo apt-get install bridge-utils
My bridge scripts are in 3 parts:
- Bridge-conf: to configure the scripts
- Bridge-start: to start the bridge
- Bridge-stop: to destroy the bridge
My scripts are made to restore the system to its previous state after destroying the bridge. I tested them and they work on Debian Jessie on a raspberry pi.
You’ll find all the following file in /tmp/openvpn-scripts/ if you used the command to download the gist.
Bridge-conf
You NEED to modify this file with your own configuration.
sudo ip addr
or
sudo ifconfig
Should give you the information you need to put here. The idea is to make your bridge act like your normal Ethernet interface with the same properties
Bridge-start
If you’re using VMWare for your OpenVPN server, you have some extra steps to do (thanks Per Mejdal Rasmussen)
When using VMware, you need to set the port group in promiscuous mode and add “brctl setageing $br 0” to bridge-start.
Source: StackOverflow
Bridge-stop
Server Configuration
In the same folder, you find the server.conf. The file contains the configuration for OpenVPN in server mode.
You should update the port, protocol (proto) and the server-bridge with your network setting.
- Port: the port your sever will listen on
- Proto: which protocol used (either TCP or UDP)
- server-bridge:
- 192.168.42.2: the internal IP of your device in your home network
- 255.255.255.0: it’s mask (represent the /24)
- 192.168.42.128: starting IP to get assigned to the clients
- 192.168.42.254: the last IP to be assigned to the clients
- compress/comp-lzo: WARNING Only activate
compress lz4
if you’re using OpenVPN version >= 2.4. else keep thecomp-lzo
.
You’ll find also this:
#set the dns servers push "dhcp-option DNS 192.168.42.1" #set the WINS server (SAMBA) push "dhcp-option WINS 192.168.42.2"
It needs to be changed also, the first one to point at your router (that surely act as a DNS server) and the second one to your SAMBA server (NAS). In my case, it’s the same IP as the server because I’m hosting the Samba server and the OpenVPN server on the same device.
Client Configuration Script
Last file that needs to be changed for your needs, build-client. The script generates a configuration file for OpenVPN in the folder you launch it. Either you edit the configuration script with your variable or use the environment variable to set it (See Generate a client configuration)
You’ll find a section VARIABLES with :
- PROTO: The protocol used on the server. (Need to be the same as you set on the server)
- REMOTE: The IP address or HOST of your server. It needs to be your external IP address or an hostname (like exmaple.com) that point to your external IP. (I’m using no-ip as a DDNS service). If you leave it empty, the script will retrieve your external IP for you.
- PORT: the port used by the server
- COMPRESS: the compression algorithm used. If you’re using OpenVPN >= 2.4, replace the default argument by compress. This will make the client ask the server for the compression algorithm.
- OPENVPN_CLIENT_DIRECTIVE: if you need to add another directive in the client configuration
Installing the configuration and scripts
Now that the preparation is ready, let’s put all the script and configuration where they should be.
OpenVPN configuration
Move the server.conf into /etc/openvpn/
sudo mv /tmp/openvpn-scripts/server.conf /etc/openvpn/
Bridge scripts
sudo mkdir /etc/openvpn/bridge sudo mv /tmp/openvpn-scripts/bridge-* /etc/openvpn/bridge/ sudo chmod +x /etc/openvpn/bridge/bridge-*
Client Generator Script
sudo mv /tmp/openvpn-scripts/build-client /etc/openvpn/easy-rsa/ sudo chmod +x /etc/openvpn/easy-rsa/build-client
Service Script for systemd
If you are using Debian Jessie or your distribution is using systemd as an init do this to add service unit for OpenVPN Bridged.
sudo mv /tmp/openvpn-scripts/[email protected] /etc/systemd/system/ sudo systemctl daemon-reload
To make SystemD start the service at boot time
sudo systemctl enable openvpn@server
Generate a client configuration
Now we will generate a client configuration that will be used on your computer to connect to the OpenVPN server. Here we build for the client OnMyWay.
cd /etc/openvpn/easy-rsa/ sudo ./build-client OnMyWay
or
cd /etc/openvpn/easy-rsa/ sudo PROTO=udp REMOTE=example.com PORT=1255 COMPRESS=comp-lzo ./build-client OnMyWay
Using the environment variable is another way to generate a client configuration.
You need to say yes to the signing of the cert and the commit.
You should see something like this:
/etc/openvpn/easy-rsa /home/pi NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/keys Generating a 2048 bit RSA private key ..................................................................................+++ ...................................+++ writing new private key to 'OnMyWay.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [US]: State or Province Name (full name) [NY]: Locality Name (eg, city) [New-York]: Organization Name (eg, company) [Raspy]: Organizational Unit Name (eg, section) [RaspberryPiOrg]: Common Name (eg, your name or your server's hostname) [OnMyWay]: Name [RaspyKey]: Email Address [[email protected]]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /etc/openvpn/easy-rsa/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'NY' localityName :PRINTABLE:'New-York' organizationName :PRINTABLE:'Raspy' organizationalUnitName :PRINTABLE:'RaspberryPiOrg' commonName :PRINTABLE:'OnMyWay' name :PRINTABLE:'RaspyKey' emailAddress :IA5STRING:'[email protected]' Certificate is to be certified until Jan 18 17:49:16 2025 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
You’ll find an OnMyWay.ovpn in the same folder you are. It’s the configuration with the certificate embedded into it.
Revoke a user
sudo -s cd /etc/openvpn/easy-rsa . ./vars ./revoke-full OnMyWay exit
Start the server
If you used my service unit for systemd :
sudo service openvpn@server start
else
sudo /etc/openvpn/bridge/bridge-start sudo service openvpn start
Stop the server
If you used my service unit for systemd :
sudo service openvpn@server stop
else
sudo service openvpn stop sudo /etc/openvpn/bridge/bridge-stop
12th June 2016 at 16:02
When I run the wget command sequence at the start, the tar command gives the error:
gzip: stdin has more than one entry–rest ignored
tar: Child returned status 2
tar: Error is not recoverable: exiting now
This is running on a Pi 3 running Jessie.
I managed to extract the files ok using the archive manager on Ubuntu.
12th June 2016 at 16:16
Should the lines
sudo cp -R /usr/share/doc/openvpn/examples/easy-rsa/2.0/* easy-rsa/
and
sudo cp -R /usr/share/easy-rsa/* easy-rsa/
be
sudo cp -R /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa/
and
sudo cp -R /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
Also I think first it is necessary to make the directory
sudo mkdir /etc/openvpn/easy-rsa
13th June 2016 at 17:07
Good point I correct it. It’s clearer this way.
4th October 2016 at 16:15
Great manual, but I can not find, however, such information for someone who is the first time meets with bridget-utils and openvpn. You have not entered assumptions.
What IP address for raspberry (openvpn hub – probably 192.168.42.2) ?
IP address of interface eth0 is the same as the address br0? In your case is 192.168.42.2, in my 192.168.160.248 (eth0)
After the modifications for own network, I have a problem with the automatic start of the bridge.
My assumptions:
The IP address for eth0 my Raspberry Pi is 192.168.160.248.
Adress for br0 is this same, br0 is one interface. br0 = tap0 + eth0. This same adress as for eth0 interface.
I assume that: this is also the address to be entered in serwer.conf, in this place: “server-bridge 192.168.160.248 255.255.255.0 192.168.160.2 192.168.160.5”
After adjusting the whole I have such a situation, openvpn starts, the unit to it they are combined correctly but there is no bridge. I only interface eth0, Io and eth0 no address (169.254.30.75), the service manual takeoff lose connection with raspberry. You can steer me where you think I make a mistake? Sorry for poor English
dev tap0
#tun-mtu 1500
#tun-ipv6
tls-server
proto udp
port 5555
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh2048.pem
topology subnet
user nobody
group nogroup
server-bridge 192.168.160.248 255.255.255.0 192.168.160.2 192.168.160.5
;client-to-client
#server-ipv6 2001:db8::/64
mssfix
persist-key
persist-tun
#log /var/log/openvpn
status /var/log/openvpn-status-8888.log
verb 4
client-to-client
keepalive 10 120
mute 50
#set the dns servers
;push “dhcp-option DNS 192.168.160.1”
#set the WINS server (SAMBA)
;push “dhcp-option WINS 192.168.160.248”
#For windows, to make the network recognized
;push “route 192.168.90.0 255.255.255.0 192.168.90.1”
;push “route 192.168.3.0 255.255.255.0 192.168.3.1”
cipher AES-256-CBC
auth SHA512
log-append /var/log/openvpn
comp-lzo
#replay-window 128
4th October 2016 at 18:52
Hello,
The assumptions are the setup where it’s exactly how you described it.
Did you modify the bridge-conf with your current network, the ip of your raspberry pi in that network, the mac address of that interface etc ?
What happens when you manually start the script: /etc/openvpn/bridge/bridge-start ?
4th October 2016 at 21:28
I think that somewhere is a loop, because after a manual start losing my connection to the console. Tomorrow I will try to connect the RPI to a monitor. In the console, it is difficult to observe what actually happens, the logs are not sufficient. Openvpn starting properly, two way tunel A-B is connected. (A) no pings to (B), (B) no pinging (A). Remote machine have correct address from the pool (from server.conf). Next machine connected to server received next address from the pool. Only bridge is problem. First conclusion: error in server.conf. After tests, my conclusion is error in the config bridge or interfaces. ETH0 is static (iface, address, netmask, gw)
4th October 2016 at 22:01
I added a part about Packet Forwarding. Maybe this is what your configuration is missing.
4th October 2016 at 22:50
There’s a simple mistake, this is not a loop. I made a mistake in bridge-conf, in the IP address. Bridge does not start after system start, but I can manually run it. Stations has established connection. Only not pinging. I enable STP on br0 & filtered port in tcpdump. Packets on UDP, looks ok. Maybe this is any problem on firewall, RPI is in the lan, port VPN is forwarding from Mikrotik router. Thanks for Your time 😉
21:46:40.072685 STP 802.1d, Config, Flags [none], bridge-id 810f.e0:5f:b9:c0:4f:40.8014, length 42
21:46:40.369236 ARP, Request who-has 192.168.160.144 tell 192.168.160.168, length 46
21:46:40.419985 ARP, Request who-has 192.168.160.152 tell 192.168.160.168, length 46
21:46:40.469300 ARP, Request who-has 192.168.160.174 tell 192.168.160.168, length 46
21:46:40.469409 ARP, Request who-has 192.168.160.18 tell 192.168.160.168, length 46
21:46:40.539222 ARP, Request who-has 192.168.160.2 tell 192.168.160.168, length 46
6th February 2017 at 22:55
Great write up and scripts.
Ive started using your bridge start and stop scripts, and edited my rig that was already setup thinking that I could use the openvpn@ systemd code to get the scripts to run properly when openvpn starts and stops, but its not working for some reason. I have to manually run the bridge start command before starting openvpn for it to all work.
Any pointers on things to check with regards to the openvpn@ service?
7th February 2017 at 15:07
When I wrote the systemd script I wasn’t aware of the difference between network.target and network-online.target.
I updated the service script, it nows start correcty as soon as the network is active and configure the bridge.
Can you confirm me it works for you too ?
14th February 2017 at 01:35
Hi All,
I have the same problem.
Unable to create br0 interface by using [email protected].
After a reboot : KO
After stop and start by hand : KO
But the br0 is created by using ./etc/openvpn/bridge/bridge-start the start openvpn.
I’m trying to debug but i’m not a guru 🙂
Thanks
14th February 2017 at 01:41
Have you tried with the version I updated more or less 5 days ago ?
This one should work correctly for boot and starting manually.
14th February 2017 at 03:15
Dear Antoine,
Yes i’m usine the last script on your repository, i’have s’en the modification in the unit .
However, it doesn’t work at boot or by hand.
Try to : tail -f daemon log but no error,. How CAN i add verbosity ?
14th February 2017 at 03:17
Are you using Debian Jessie ?
Can you copy paste what you get when you do: journalctl -a -u openvpn@server
14th February 2017 at 03:32
Just: started openvpn connections to server
No br0
14th February 2017 at 03:33
And yes, j’essie Fresh install last version
14th February 2017 at 12:57
Status just after reboot:
pi@raspberrypi:~ $ sudo systemctl status [email protected]
● [email protected] – OpenVPN server .server
Loaded: loaded (/etc/systemd/system/[email protected]; disabled)
Active: inactive (dead)
Docs: man:openvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
https://www.aaflalo.me/2015/01/openvpn-tap-bridge-mode
tap0 interface is created but no br0
And the daemon log after stop / start service
Feb 14 12:54:03 raspberrypi systemd[1]: Starting OpenVPN connection to server…
Feb 14 12:54:03 raspberrypi systemd[1]: Started OpenVPN connection to server.
Feb 14 12:54:03 raspberrypi dhcpcd[591]: tap0: adding address fe80::8765:135e:ef34:7a30
Feb 14 12:54:03 raspberrypi dhcpcd[591]: if_addaddress6: Permission denied
Feb 14 12:54:03 raspberrypi dhcpcd[591]: tap0: waiting for carrier
Feb 14 12:54:03 raspberrypi dhcpcd[591]: tap0: carrier acquired
Feb 14 12:54:04 raspberrypi dhcpcd[591]: tap0: IAID 7f:fd:34:92
Feb 14 12:54:04 raspberrypi dhcpcd[591]: tap0: soliciting an IPv6 router
Feb 14 12:54:04 raspberrypi dhcpcd[591]: tap0: soliciting a DHCP lease
Feb 14 12:54:14 raspberrypi dhcpcd[591]: tap0: using IPv4LL address 169.254.203.155
Feb 14 12:54:14 raspberrypi avahi-daemon[342]: Joining mDNS multicast group on interface tap0.IPv4 with address 169.254.203.155.
Feb 14 12:54:14 raspberrypi dhcpcd[591]: tap0: adding route to 169.254.0.0/16
Feb 14 12:54:14 raspberrypi avahi-daemon[342]: New relevant interface tap0.IPv4 for mDNS.
Feb 14 12:54:14 raspberrypi avahi-daemon[342]: Registering new address record for 169.254.203.155 on tap0.IPv4.
Feb 14 12:54:16 raspberrypi ntpd[621]: Listen normally on 6 tap0 169.254.203.155 UDP 123
Feb 14 12:54:16 raspberrypi ntpd[621]: peers refreshed
same result: after stop, tap0 is killed and after start: tap0 ok but no br0
14th February 2017 at 16:22
The problem has been resolved by email.
I’m editing the tutorial, you need to be sure the normal daemon of OpenVPN is not started/enabled.
5th September 2017 at 21:57
On my Raspberry Pi (Linux raspberrypi 4.9.35-v7+ #1014 SMP Fri Jun 30 14:47:43 BST 2017 armv7l GNU/Linux) I had originally installed OpenVPN as a tunnel. I now want to change it to Bridge, using your tutorial. I followed the steps, but get an error when trying to start the bridge:
Tue Sep 5 20:16:14 2017 TUN/TAP device tap0 opened
Tue Sep 5 20:16:14 2017 Persist state set to: ON
device br0 already exists; can’t create bridge with the same name
device eth0 is already a member of a bridge; can’t enslave it to bridge br0.
device tap0 is already a member of a bridge; can’t enslave it to bridge br0.
SIOCADDRT: File exists
Sep 05 20:16:14 raspberrypi systemd[1]: [email protected]: control process exited, code=exited status=7
Can you point me in the right direction to solve this?
5th September 2017 at 22:04
Hello Bram,
It would seem you already have a bridge setup with eth0 and tap0 with the name br0.
6th September 2017 at 20:41
After a reboot, the previous OpenVPN service has been disabled, and indeed did not start. The bridge br0 does exist:
pi@raspberrypi:~ $ brctl show
bridge name bridge id STP enabled interfaces
br0 8000.b827eb50bbf0 no eth0 tap0
When the stop command is issued, the bridge disappears:
pi@raspberrypi:~ $ sudo sh /etc/openvpn/bridge/bridge-stop
Wed Sep 6 19:31:03 2017 TUN/TAP device tap0 opened
Wed Sep 6 19:31:03 2017 Persist state set to: OFF
pi@raspberrypi:~ $ brctl show
bridge name bridge id STP enabled interfaces
I then try to start the server, but it agian fails.
pi@raspberrypi:~ $ sudo service openvpn@server start
Job for [email protected] failed. See ‘systemctl status [email protected]‘ and ‘journalctl -xn’ for details.
That is all I can do right now – the Rasp now is unreachable so I cannot check the log. It is at a remote location, I need to wait until someone can physically cycle the power.
To be continued…
6th September 2017 at 20:47
Okay this is weird.
I think something must be wrong in your openvpn configuration.
Can you use the contact form to send me an email ? I would need your logs (journalctl -u openvpn@server) and it will be easier to resolve this per email.
7th September 2017 at 12:46
Hi Antoine,
Can you tell me how to configure network cards of the clients, for example, Site-Client 1 and LAN-client 1 including their IP addresses and default gateways, so they can be part of the openvpn netrwork (192.168.0.0/24).
Many thanks,
Ibrahim
7th September 2017 at 15:26
Hello Ibrahim,
This would be very specific to your network needs. This guide is to be used when you have already a network in place and you have that information at hand.
To learn how to configure your network, I advise you to go through networking configuration guides.
22nd September 2017 at 08:48
Hi Antoine,
Great manual, but I need some info.
How do I understand this is the configuration for a computer with a single network card? If so on the firewall I need to pass the transmission on the appropriate port.
What do I need to change and how, if I would like to have two network cards, one to the internet and the other to the lan network?
22nd September 2017 at 17:09
Hello Paweł,
You would need to setup the bridge with the interface that is used for your LAN.
You can configure OpenVPN to listen for traffic coming from your WAN (internet) interface and use the bridge with your LAN interface.
25th September 2017 at 14:27
Hello Antoine,
Can I use your scripts for that?
Do I need to configure something special?
25th September 2017 at 15:19
By default OpenVPN listen to all the interface but if you want to bind it to a specific one you can do it using the option in the configuration file:
local X.X.X.X
where X.X.X.X is the IP of your WAN interface.
Other than that, just use the MAC and IP of your LAN interface in all the part talking about the bridge and it should work.
25th September 2017 at 15:25
I will try to set according to your information.
Thank you very much.
3rd October 2017 at 13:15
I ran a complete fresh install of everything, Raspian stretch, and followed through everything here. However when I fire things up, i can no longer do any networking on the PI, i cannot ssh to it or anything else, But everything seems to be running just fine, IE no errors.
I set my eth0 address to 192.168.2.245, br0 gets an address of 192.168.2.112, Any ideas what has gone wrong?
3rd October 2017 at 14:26
Hello Frank,
This looks like you have a dhclient running on your raspberry pi on your bridge. It’s a DHCP client that will query the DHCP server for an IP.
I advise to set a static IP in your DHCP server for your raspberry pi (based on the MAC address) to be sure that whatever happens, you always have the same IP for your raspberry pi.
4th October 2017 at 13:31
HI Antoine,
Thank you for that, as far as I can tell now the VPN Server is running correctly. I copied the ovpn file over to my client, but it wont even ‘dial’ the server. my old config dials in and i see the errors on the server (Expected because nothing will match),, what am I missing to setup the client (windows).
10th November 2017 at 13:53
Hi there Antoine,
I am hoping I could take a moment of your time. I’ve been trying to setup my raspberry pi as an openvpn bridge server, trying a few different tutorials, reading the manual, and finally came across your tutorial.
My experience has been pretty much consistent in all of my tests. Ultimately I cannot get the openvpn bridge server to work out correctly. Here is what I am experiencing, note that all of my testing has been manual starting of the bridge and openvpn.
– The bridge starts up fine, no issues, and I am able to disconnect / connect from the pi with ease. The bridge gets the IP address that eh0 had, along with its gateway, default route, etc.
– The SECOND i turn on openvpn, i lose all connectivity to the pi and I cannot SSH back into it
– If I try in TCP mode, I get connection timeouts and communication the server log does not indicate that any communication made it to the pi
– If I try in UDP mode, I get TLS handshake errors / timeout, the server logs do recognize the attempted connection but that it takes too long for the handshake
– If I start openvpn WITHOUT the bridge, i am able to connect to the pi server just fine (both UDP and TCP), however I (as expected) cannot ping any resources on the local network, even the pi.
– My router is set to forward UDP and TCP packets to the correct server / port, however the previous point proves that’s the case.
What do you think? Would you have nay guidance here? I’m trying to break this problem down in to pieces and it seems like the point of failure is only when the openvpn server is started after the bridge has been established.
server.conf (192.168.0.1 is router, 192.168.0.96 is pi/openvpn bridge):
route 192.168.0.0 255.255.255.0 192.168.0.96
push “dhcp-option DNS 192.168.0.1”
push “route 0.0.0.0 0.0.0.0 192.168.0.96”
topology subnet
mssfix
script-security 2
port 1196
proto tcp
dev tap0
ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh2048.pem
server-bridge 192.168.0.96 255.255.255.0 192.168.0.98 192.168.0.126
client-to-client
keepalive 10 120
tls-auth ta.key 0 # This file is secret
tls-server
cipher AES-128-CBC # AES
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
verb 5
log-append /var/log/openvpn.log
client.conf:
client
dev tap
proto udp
remote vpn.myhostname.com 1196
resolv-retry infinite
#nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
tls-auth ta.key 1
comp-lzo
verb 3
cipher AES-128-CBC
auth-nocache
Thanks for any time you can provide.
10th November 2017 at 23:15
OK, days of trying to solve this problem and the day I post to your blog I think i figured out the underlying issue; figures.
I was bridging eth0 and tap0. What I noticed but didnt care to consider was that my wlan0 had a valid, router supplied, IPv6 address (NOT starting with fe80) but no IPv4 address. That’s weird on its own so I wanted to fix it, so I issued the following command:
sudo dhclient -4 -v wlan0
This forced wlan0 to get its IPv4 address from the router. For some reason once I did this openvpn worked and I was able to successfully connect to openvpn on the pi, ping local and external resources. etc.
So a few strange observations:
– My pi wlan0 is getting a valid IPv6 address from my router (starting with 2601:183) but NO IPv4 address after a fresh boot up.
– wlan0 does not aquire an IPv4 address without manual intervention with ‘sudo dhclient -4 -v wlan0’; i’ll need to address this.
– For some reason, the issue with wlan0 affected openvpn…im presuming at this point there was an underlying issue with routing
– br0 takes the correct IP address / etc from eth0, however once I start openvpn that ip address / etc is then inherited by tap0 ….. im assuming that since i am able to connect successfully that this is desired behavior.
Not enough time from when I first posted here with my issue and resolving it, but I still want to say thanks for your excellent write-up and provided scripts. I hope my added comments here keeps someone else in the future from spending unnecessary time.
10th November 2017 at 23:49
For what I understand you have the wlan0 and eth0 connected to your router, right ?
Is there a reason for using them both ?
Also, if you’re using my sripts, tap0 don’t have an IP assign to it. Only br0 keep an ip. I also advise against push the route 0.0.0.0 as this is asking for the traffic to be redirect by your raspberry pi.
Also you don’t need “route 192.168.0.0 255.255.255.0 192.168.0.96” this is done automatically by the server-bridge directive.
I hope this can help you to iron the last quirk in your setup.
2nd February 2018 at 01:17
Hi Antoine
Well done. I follow this, but now I have noticed that my situation is different than the one presented in the instructions. Is it possible to use two interfaces on the client? Each client (raspberry pi) is connected to the Internet via WLAN0 and has one Ethernet device connected to the raspberry pi LAN port. I want to create a network of local network devices connected to the LAN0 ports of the raspbrry pi clients to allow them to exchange data in the same way as in a normal local area network. Is it possible? I will be grateful for each tip :).
2nd February 2018 at 16:53
Hello Krzysztof,
I would need a better view of the topology of your network to fully understand your situation.
The idea of the tutorial is to setup the bridge between the virtual interface (tap) with the lan interface (eth0) in this case.
There is no problem if you have multiple interfaces on the server, you just need to bridge the VLAN with the LAN one.
As for the client, you can have any number of interface on it, it won’t be a problem.
4th February 2018 at 20:10
Hey
I took a picture showing my network topology [IMG]http://i66.tinypic.com/20gyyb8.png[/IMG]. I’m trying to access programmable logic controllers from my programming computer. Programming a computer can have a LTE modem when I’m out of the house or it can be connected to my local network on the router’s home page.
Antoine is possible to achieve? What topics and packages must I use and understand. What should be done to achieve the intended goal?
5th February 2018 at 22:08
Hello Krzysztof,
Yes you should be able to do it. But you’ll need to configure the routing (iptable) on each raspberry pi to be sure your Programmable logic can see the VPN you’ll create.
For that I advice to check how to work with NAT and packet redirection as you would want your raspberry pis to do the forwarding of the packet between the VPN and the programmable controllers.
15th February 2018 at 15:56
After spending 3 workdays with the guide, I manage to setup an OpenVPN server.
Here are the most important pitfalls:
* Read /var/log/openvpn if it does not work.
* Ubuntu 16.04 LTS comes with version 2.3.10 of OpenVPN. You have to change server.conf and build-client to use comp-lzo. Whis is decribed in the guide
* When using VMware, you need to set the port group in promiscuous mode and add “brctl setageing $br 0” to bridge-start.
Details: https://serverfault.com/questions/558162/arp-response-is-not-present-on-the-other-port-of-linux-bridge-based-on-ubuntu-13%7Carp
15th February 2018 at 16:01
Thanks for your comment, I hope it will help other users in your situation. I’m going to update the guide about VMWare.
Hopefully the part about Ubuntu will be soon resolved as we’re reaching 18.04 very soon 🙂
21st February 2018 at 05:50
this was working till yesterday. not sure if an auto update killed it or if i corrupted my sd card. I still have ssh access to the system 50 miles away because i left ssh with key files only active on the router. from the router I sshed into the pi just fine. The service fails to start though, looks like something to do with the bridge. still have to do some log digging to do but if you know of anything linux or openvpn wise that changed in the last few days and have a min to reply it might end up saving time.
23rd February 2018 at 21:03
Hello John,
Not that I know of.
Did you check that the default OpenVPN service is disabled ?
Also is the systemd unit script up to date ? I made couple of changes to it couple of months ago.
10th September 2018 at 16:47
Antoine –
When trying to ping back to the router I get a destination host unreachable. Very odd.
27th February 2019 at 10:13
Hello,
the generator @ 4096 takes on my pi about 16 hours. is there a way to make easier? how to configure @ 2048 or use an external generator?
the guide is perfect, better than the openvpn official one!
27th February 2019 at 17:09
Hello Andrea,
As said in the tutorial you can use DHTool service to generate the DH.
19th August 2019 at 09:37
Antoine,
Many thanks for putting up this guide! There have been a few changes to easy-rsa, in both how its called and the location of the key store. I’ve highlighted these for other followers of your guide.
*Invoking Easy-rsa*
Instead of calling ./build-ca etc, it now needs to called directly, e.g ./easyrsa build-ca. The vars batch file isn’t directly invoked either.
*server.conf*
Needs to point to the new certificate store
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
dh /etc/openvpn/easy-rsa/pki/dh.pem
*build-client*
Reference to invoking the var bash script should be disabled, and pointers to the generated art/key files updated, e.g.
CERT=`cat ${OPENVPN_EASY_RSA_PATH}pki/issued/${CLIENT}.crt | grep -A 100 “BEGIN CERTIFICATE” | grep -B 100 “END CERTIFICATE”`
The only issue I’ve had with my modifications is that the .key file isn’t being inserted into the .ovpn file, so I’ve had to resort to doing that manually at the moment.
21st August 2019 at 15:06
Is it for Debian 10 ?
6th October 2019 at 21:05
Hi Antoine,
I try to setup OpenVPN on Raspberry PI on latest Raspbian image, but I have an issue with bridge interface. If i try to run ./bridge-start – it runs ok, but after this Raspberry is completely without any access to the internet and to the local LAN as well.
Packet forwarding is allowed. Do you have any idea, how could I fix it?
Thank you for your help!
24th January 2020 at 00:17
Hi, have you find any solution for this problem?
Thank you for your help!
10th October 2019 at 21:18
Thanks so much for your helpful tutorial on building an OpenVPN TAP Bridge! I followed it closely and almost have mine up and running, but am encountering one small issue at the finish line.
Everything gets up and running without errors, but when I try to connect, I lose all internet access on my client-side. However, I tried connecting to the internal ip address of the VPN instead of the external ip, and that actually worked. I have ip forwarding enabled, port 1194 forwarded, and no firewall, so I’m not sure why nothing it getting through. Have you ever encountered this issue before? Any advice you can provide would be greatly appreciated.
15th October 2019 at 15:59
2 possibilities.
27th October 2019 at 21:45
Thanks for your helpful tips! I finally realized I was making a very silly and simple mistake by trying to test the VPN bridge from my local network. Once I tried from outside of it, everything worked great.
4th May 2020 at 21:29
In openvpn server config file:
>dev tap0
>….
>….
>topology subnet
Option “topology” aplies to ONLY with tun devices!
14th December 2020 at 19:58
Hi there,
I managed the tutorial excepted the part with build-key. I can’t create a user because the build-key doesn’t exist. I think I missed something with the DHtools services.
Could you help me, How I am supposed to deal with it ?
Regards,
Vyken
12th August 2021 at 03:49
Hi Antoine,
Thanks for a great walkthrough! It helped me a lot.
But I used EasyRsa 3.0.8 and the key generation works slightly different.
So I post my modifications here hoping it might help someone.
So with EasyRsa v3 the server keys are generated with
“`
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa gen-req vpnserver nopass
./easyrsa sign-req server vpnserver
./easyrsa gen-dh
cp pki/ca.crt /etc/openvpn/server/
cp pki/dh.pem /etc/openvpn/server/
cp pki/private/vpnserver.key /etc/openvpn/server/
cp pki/issued/vpnserver.crt /etc/openvpn/server/
“`
The build-client script is slightly modified to:
“` bash
#!/bin/bash
#This script generate the key for the wanted client and it’s configuration file
#to be used with OpenVPN. If the key has already been generated it will only
#generate the configuration file for OpenVPN
#VARIABLES
#If you don’t set a remote (the external IP of the server or the hostname)
#the script will try to gather it using dig
#You need to change the port to the one set in your server
#if you want to add new directive to client configuration use $OPENVPN_CLIENT_DIRECTIVE
PROTO=”${PROTO:-udp}”
REMOTE=”${REMOTE:-}”
PORT=”${PORT:-5555}”
OPENVPN_EASY_RSA_PATH=”/etc/openvpn/easy-rsa/”
OPENVPN_CLIENT_DIRECTIVE=”${OPENVPN_CLIENT_DIRECTIVE:-}”
DEV_TYPE=${DEV_TYPE:-tap0}
COMPRESS=${COMPRESS:-compress}
#DO NOT MODIFY BELOW
function usage {
echo “Usage: $0 clientName”
echo “ENV Variables:”
echo “PROTO: protocol used”
echo “REMOTE: host or IP address of the server”
echo “PORT: port on the server”
echo “DEV_TYPE: device type (tun+/tap+)”
echo “COMPRESS: No compression algorithm is used . Apparently it might be breached”
exit -1
}
function getIp {
echo `dig +short myip.opendns.com @resolver1.opendns.com`
}
function clientConfig {
cat <<CLIENT_CONF
client
dev $DEV_TYPE
proto $PROTO
remote $REMOTE $PORT
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
auth SHA512
$COMPRESS
verb 3
pull
$OPENVPN_CLIENT_DIRECTIVE
$CA
$CERT
$KEY
CLIENT_CONF
}
if [ $# -eq 0 ]; then
echo “No arguments supplied”
usage
fi
if [ -z “$1” ]; then
echo “Client name not supplied”
usage
fi
if [ -z “$REMOTE” ]; then
REMOTE=$(getIp)
fi
CLIENT=$1
if [ ! -f $OPENVPN_EASY_RSA_PATH/pki/issued/${CLIENT}.key ]; then
pushd $OPENVPN_EASY_RSA_PATH
./easyrsa gen-req ${CLIENT} nopass
popd
fi
if [ ! -f $OPENVPN_EASY_RSA_PATH/pki/private/${CLIENT}.crt ]; then
pushd $OPENVPN_EASY_RSA_PATH
./easyrsa sign-req client ${CLIENT}
popd
fi
CA=`cat $OPENVPN_EASY_RSA_PATH/pki/ca.crt | grep -A 100 “BEGIN CERTIFICATE” | grep -B 100 “END CERTIFICATE”`
CERT=`cat $OPENVPN_EASY_RSA_PATH/pki/issued/${CLIENT}.crt | grep -A 100 “BEGIN CERTIFICATE” | grep -B 100 “END CERTIFICATE”`
KEY=`cat $OPENVPN_EASY_RSA_PATH/pki/private/${CLIENT}.key | grep -A 100 “BEGIN PRIVATE KEY” | grep -B 100 “END PRIVATE KEY”`
clientConfig > $CLIENT.ovpn
exit 0
“`
and I made a revoke script just to remember the new way:
“` bash
#! /bin/bash
# simple script for revoking an openvpn user
if [ $# -eq 0 ]; then
echo “No arguments supplied”
usage
fi
if [ -z “$1” ]; then
echo “Client name not supplied”
usage
fi
CLIENT=$1
pushd /etc/openvpn/easy-rsa
./easyrsa –batch revoke ${CLIENT}
popd
“`
I hope it helps someone