OpenVPN - Bridged connection without NAT using LAN DHCP
This is a note about using OpenVPN. OpenVPN is far from simple to setup, because there are a lot of things working together with it to create connections and there are lots of ways to use it. The configuration is also quite hard to get right. Therefore there may be a lot of invalid information here, it is based on the trial-and-error-method.
Note for VirtualBox setups
For VirtualBox setups - ensure that the virtual machine network adapters do not have Promiscuous mode NOT set to Deny. Deny results in that the OpenVPN client is unable to get responses nor contact other hosts on the LAN. On each virtual box machine settings go to -> Network -> Adapter -> Advanced -> Promiscuous mode -> Change Deny to Allow all.
Note using ping from client to hosts on the VPN LAN
Do NOT give up too fast when trying to ping a LAN host from the client through the VPN. The first ping gave "Destination Host Unreachable" 8 times before it started replying.
Creating keys for the server
The following creates certificate files for the client and server. The > lines show what the expected response is. Reference: https://www.golinuxcloud.com/install-openvpn-server-easy-rsa-3-centos-7/ # install required files apt update apt install bridge-utils easy-rsa openvpn # make a ca dir for easy-rsa cd /etc/openvpn make-cadir easy-rsa cd easy-rsa # init pki and build certificate ./easyrsa init-pki ./easyrsa build-ca # > Your new CA certificate file for publishing is at: # > /etc/openvpn/easy-rsa/pki/ca.crt # make diffie-hellman parameters ./easyrsa gen-dh # > DH parameters of size <...> created at /etc/openvpn/easy-rsa/pki/dh.pem # make keypair and certificate request ./easyrsa gen-req <server> nopass # > Keypair and certificate request completed. Your files are: # > req: /etc/openvpn/easy-rsa/pki/reqs/<server>.req # > key: /etc/openvpn/easy-rsa/pki/private/<server>.key ./easyrsa sign server <server name> # > Certificate created at: /etc/openvpn/easy-rsa/pki/issued/<server>.crt mkdir /etc/openvpn/keys/ chmod 750 /etc/openvpn/keys cp -a /etc/openvpn/easy-rsa/pki/ca.crt /etc/openvpn/keys/ cp -a /etc/openvpn/easy-rsa/pki/dh.pem /etc/openvpn/keys/dh.pem cp -a /etc/openvpn/easy-rsa/pki/issued/<server>.crt /etc/openvpn/keys/ cp -a /etc/openvpn/easy-rsa/pki/private/<server>.key /etc/openvpn/keys/ To use them in /etc/openvpn/server.conf: tls-server persist-key ... ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/<server>.crt key /etc/openvpn/keys/<server>.key # this file should be kept secret dh /etc/openvpn/keys/dh.pem
Creating keys for the client on the server
Keys for the clients are made on the server or somewhere else, then each client gets it's own key to login with. ./easyrsa gen-req <client> nopass ./easyrsa sign client <client> cp -a /etc/openvpn/easy-rsa/pki/issued/<client>.crt /etc/openvpn/keys/ cp -a /etc/openvpn/easy-rsa/pki/private/<client>.key /etc/openvpn/keys/ copy the client certificates to the client node under /etc/openvpn scp /etc/openvpn/keys/<client>.* <client-hostname>:/etc/openvpn/ Note, only ca.crt is shared, <client>.crt and <client>.key belong to the client. To use this in the configuration in the client at /etc/openvpn/client.conf: client ... ca ca.crt cert <client>.crt key <client>.key ns-cert-type server ...
Bridged setup without LAN using DHCP server on the LAN
The following configuration creates a bridged connection without NAT using the DHCP server on the LAN, resulting in that the clients get real IP:s from the LAN. Note, the client adds gateway DNS:es to /etc/resolv.conf after some seconds WITHOUT a push command from the server when connecting. But it does not add the default gateway. The configuration setting "redirect-gateway local def1" is suggested in some setup examples, but seems to be to quick, it tries to add routes before tap0 has received an ip, which makes the system complain with "Nexthop has an invalid gateway". Without this configuration setting it cannot add the default gateway in the client routing automatically. Therefore a workaround has been supplied here, to set the tap0 interface in /etc/network/interfaces, then it will manage this when ready on its own. This will also route all traffic through the LAN (using the the 0.0.0.0 and 128... lines). The downside of this workaround is that you can only connect to 1 VPN since it will do the same for all connections using the tap0 interface. 12.345.678.9 is here the external WAN IP and 192.168.2.* is the internal LAN that should be reachable using the OpenVPN connection.
server : /etc/openvpn/server.conf
port 1194 proto udp4 dev tap0 keepalive 100 1200 persist-key persist-tun tls-server ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/<server>.crt key /etc/openvpn/keys/<server>.key dh /etc/openvpn/keys/dh.pem script-security 2 remote-cert-tls client up "/etc/openvpn/up.sh br0" down "/etc/openvpn/down.sh br0" # to override network dhcp server with openvpn dhcp server # server-bridge 192.168.2.200 255.255.255.0 192.168.2.100 192.168.2.150 push "redirect-gateway local def1" cipher AES-256-CBC
server : /etc/openvpn/up.sh
#!/bin/sh BR=$1 DEV=$2 MTU=$3 # to use the older ifconfig # /sbin/ifconfig $DEV mtu $MTU promisc up # /sbin/brctl addif $BR $DEV # to use the newer ip PATH=/sbin:/usr/sbin:/bin:/usr/bin ip link set "$DEV" up promisc on mtu "$MTU" if ! brctl show $BR | egrep -q "\W+$DEV$"; then brctl addif $BR $DEV fi
server : /etc/openvpn/down.sh
#!/bin/sh BR=$1 DEV=$2 # to use the older ifconfig # /sbin/brctl delif $BR $DEV # /sbin/ifconfig $DEV down # to use the newer ip PATH=/sbin:/usr/sbin:/bin:/usr/bin brctl delif $BR $DEV ip link set "$DEV" down
server : /etc/network/interfaces
source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The WAN interface auto eth0 iface eth0 inet static address 12.345.678.9 netmask 255.255.255.0 # The VPN-tap0-br0-eth1-LAN bridge auto br0 iface br0 inet static address 192.168.2.200 netmask 255.255.255.0 network 192.168.2.0 broadcast 192.168.2.255 gateway 192.168.2.1 dns-nameservers 192.168.2.1 bridge_ports eth1 bridge_fd 0 bridge_hello 2 bridge_maxage 12 bridge_stp on bridge_prio 1000 # The LAN interface auto eth1 iface eth1 inet manual up ifconfig $IFACE 0.0.0.0 up up ip link set $IFACE promisc on down ip link set $IFACE promisc off down ifconfig $IFACE down
client : /etc/network/interfaces
# ref: https://serverfault.com/questions/612868/openvpn-linux-client-does-not-bring-up-tap0-interface # this works to add and remove gateway since openvpn # assigns them before dhclient has assigned an IP to tap0 allow-hotplug tap0 iface tap0 inet dhcp # testing up route add default gw 192.168.2.1 # extra to ensure all traffic is routed through it up route add -net 0.0.0.0 netmask 128.0.0.0 gw 192.168.2.1 up route add -net 128.0.0.0 netmask 128.0.0.0 gw 192.168.2.1 down route del default gw 192.168.2.1 # extra to remove all traffic routing down route del -net 0.0.0.0 netmask 128.0.0.0 gw 192.168.2.1 down route del -net 128.0.0.0 netmask 128.0.0.0 gw 192.168.2.1 #up ip route add 0.0.0.0/1 via 192.168.2.1 #up ip route add 128.0.0.0/1 via 192.168.2.1 down dhclient wlan0
client : /etc/openvpn/client.conf
# the ip to the server remote 12.345.678.9 port 1194 client dev tap proto udp4 nobind persist-key persist-tun ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/<client>.crt key /etc/openvpn/keys/<client>.key verb 3 float remote-cert-tls server auth-nocache cipher AES-256-CBC
Start and stop commands
server start (runs automatically on boot): service openvpn start server stop: service openvpn stop client start: openvpn /etc/openvpn/client.conf client stop: killall openvpn maybe also dhclient wlan0 (otherwise it won't reset the /etc/resolv.conf), but it is done in /etc/network/interfaces
About static IP addresses
Static MAC addresses for static IP assignment does not seem to exist in OpenVPN. Instead it is suggested is to use the internal OpenVPN DHCP and create a custom profile for each user based on the client certificate name at /etc/openvpn/ccd/<client certificate name>. Then the OpenVPN DHCP on the server will send static IP:s to the clients. If using dnsmasq on the LAN as DHCP server, then it is possible in dnsmasq to assign static IP a based on the client hostname. To assign IP:s in dnsmasq on the server based on the client hostname, edit /etc/dnsmasq.conf or /etc/dnsmasq.d/<file> and add this line: dhcp-host=<hostname>,<ip> For Tomato routers running the dnsmasq server please note that there are no fields to fill in hostnames for client identification, only MAC addresses. The line above should therefore be added to the custom configuration for the dnsmasq server located at Advanced, DHCP/DNS, Dnsmasq Custom configuration. dhclient client hostname is set at /etc/dhcp/dhclient.conf, send host-name. No change needed unless you want to send custom hostnames - like if you want different hostnames when connecting from LAN or VPN) if using dhclient.
This is a personal note. Last updated: 2020-05-27 20:08:07.