openvpn client configuration with multiple configs (end user type)

Hi,
I have seen tons of stuff out there for server configs and point to point configs however getting openvpn running with multiple configs as a road warrior setup is largely missing.
I have a VPN service with dozens of servers and I connect to a different one every few hours sometimes. Here's my setup:

1. Make sure tap is loaded (kldload if_tap) typically I put it in the /boot/loader.conf if_tap_load="YES"
2. pkg install openvpn
3. modify your rc.conf as by adding the following lines:
openvpn_enable="YES"
openvpn_if="tap"
gateway_enable="YES"

4. get config files from your provider. Put them in /usr/local/etc/openvpn.
I renamed them from myconfig.ovpn to myconfig.conf
example: for F in *.ovpn;do mv "$F" $(echo "$F" | sed 's/ovpn/conf/g');done

5. add a line to the top of your config files. The following line tells opvnvpn where to find your configs, scripts, ca files userpass.text files up/down scripts etc.
cd /usr/local/etc/openvpn

for F in *.conf;do sed -i bak '1s/^/cd \/usr\/local\/etc\/openvpn'$\n''/g' $F;rm $F.bak;done
By the way that's two single quotes back to back. BSD sed doesn't like new line's and this is the only way to make it work.

Every time you want to connect to a different server simply execute sudo openvpn <myconf.conf>

You will be leaking DNS at this point.
To prevent that is a bit more difficult. More on this in a moment

I also use the openvpn-admin client to list all my vpn configs. It is not so good for building a config as it is very limited and unmaintained at this point. but it is still useful for executing them if you are using a desktop of some form.
6. pkg install openvpn-admin
This must be run as root so you start it will sudo openvpn-admin&. It will put a little icon in your tool bar somewhere with all your configs listed.
This will be problomatic for some x installs so make sure your sudoers config is passing x display security and information correctly. If sudoers is setup correctly you can start
this little program when you log on to your window manager.

OK now for the DNS leak issue:

You're going to need some form of script which runs when you connect or disconnect to your vpn provider. This script will alter your dns accordingly.
openvpn does come with a script in /usr/local/libexec/openvpn-client.up and openvpn-client.down.
These scripts should be copied or linked to the /usr/local/etc/openvpn directory so that openvpn can find them
However these scripts work by modifying your resolv.conf file. If you are using local_unbound this may not work.

So you're going to need to modify them to use the resolvconf command and also reload local_unbound (if your using it) service local_unbound restart after you're done.
To do this you require 2 steps.
1. Modify your config files again by adding the following lines:
up 'openvpn-client.up
down 'openvpn-client.down'

2. in the appropriate places in the script you need to use the resolvconf command as follows:
echo -n nameserver <addr> | resolvconf -a tap0
echo -n nameserver <addr> | resolvconf -d em0
The point is that you'll use the resolvconf command to add a nameserver to your tap device and remove the default nameserver from your ethernet device
Then when you are done you remove the nameserver from your tap device and add your original nameserver back to your ethernet device
Finally you'll restart your local_unbound service.

your vpn provider is likely using DHCP to assign you a nameserver. The default openvpn scripts pick that info up from openvpn as well as your interface.
I had to modify my scripts to make them work.


Happy VPN!!!!!!
Thom
 
#!/bin/sh
#converts .ovpn files to conf and adds a path to the top of the file
#first change names
for f in *.ovpn;do mv "$f" $(echo "$f" | sed 's/ovpn/conf/g');done
#add line at beginning of conf file to add the local path where
#openvpn will search for files
#note adding a new line at the end of a replace string for BSD sed is difficult
#this is the only way I could get it to work.
#thanks to the internet and sikmir on stack overflow
for f in *.conf;do sed -i .bak '1s/^/cd \/usr\/local\/etc\/openvpn\'$'\n''/g' $f;rm $f.bak;done
 
#!/usr/local/bin/bash
#
#MODIFIED by THOM for FREEBSD 2018
#
# Parses DHCP options from openvpn to update resolv.conf
# To use set as 'up' and 'down' script in your openvpn *.conf:
# up /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf
#
# Used snippets of resolvconf script by Thomas Hood <jdthood@yahoo.co.uk>
# and Chris Hanson
# Licensed under the GNU GPL. See /usr/share/common-licenses/GPL.
# 07/2013 colin@daedrum.net Fixed intet name
# 05/2006 chlauber@bnc.ch
#
# Example envs set from openvpn:
# foreign_option_1='dhcp-option DNS 193.43.27.132'
# foreign_option_2='dhcp-option DNS 193.43.27.133'
# foreign_option_3='dhcp-option DOMAIN be.bnc.ch'
# foreign_option_4='dhcp-option DOMAIN-SEARCH bnc.local'

## You might need to set the path manually here, i.e.
#hardcoded the path because which was not working correctly
RESOLVCONF="/sbin/resolvconf" #$(which resolvconf)

case $script_type in

up)
for optionname in ${!foreign_option_*} ; do
option="${!optionname}"
echo $option
part1=$(echo "$option" | cut -d " " -f 1)
if [ "$part1" == "dhcp-option" ] ; then
part2=$(echo "$option" | cut -d " " -f 2)
part3=$(echo "$option" | cut -d " " -f 3)
if [ "$part2" == "DNS" ] ; then
IF_DNS_NAMESERVERS="$IF_DNS_NAMESERVERS $part3"
fi
if [[ "$part2" == "DOMAIN" || "$part2" == "DOMAIN-SEARCH" ]] ; then
IF_DNS_SEARCH="$IF_DNS_SEARCH $part3"
fi
fi
done
R=""
if [ "$IF_DNS_SEARCH" ]; then
R="search "
for DS in $IF_DNS_SEARCH ; do
R="${R} $DS"
done
R="${R}"
fi

for NS in $IF_DNS_NAMESERVERS ; do
R="${R}nameserver $NS"
done

#echo -n "$R" | $RESOLVCONF -x -p -a "${dev}"
echo -n "$R" | $RESOLVCONF -a "${dev}"
#if you don't remove the name server from em0 it will still leak sometimes.
echo -n "$R" | $RESOLVCONF -d "em0"
;;
down)
$RESOLVCONF -d "${dev}"
;;
esac

# Workaround / jm@epiclabs.io
# force exit with no errors. Due to an apparent conflict with the Network Manager
# $RESOLVCONF sometimes exits with error code 6 even though it has performed the
# action correctly and OpenVPN shuts down.
exit 0
 
I know that the script removes name server from em0 and doesn't ever put it back but it still works.
A TO-DO would be to enumerate the interfaces... get the name servers for each one...write a file somewhere
Then read that file to restore the information as it was before connecting to the vpn.
 
Although I skipped most of the post one small detail did catch my eye: why all the hassle for the DNS leak?

There's a very simple solution for that: # route del default. After that there's no way that your host will be able to contact anything outside its local network, problem solved. The network leak problem isn't only about DNS, it's about everything else too (depending on your level of paranoia).

On that note:

2. in the appropriate places in the script you need to use the resolvconf command as follows:
echo -n <nameserveraddr> | resolvconf -a tap0
echo -n <nameserveraddr> | resolvconf -d em0
Your resolvconf commands are wrong, see also resolvconf(8):
Code:
     resolvconf solves this by letting the daemon send their resolv.conf(5)
     file to resolvconf via stdin(4) with the argument -a interface[.protocol]
     instead of the filesystem.
Notice: resolv.conf(5). And a correct resolv.conf syntax is:
Code:
nameserver 8.8.8.8
Don't take my word for it though:
Code:
root@psi:/etc # echo -n 8.8.8.8 | resolvconf -a em0
root@psi:/etc # cat resolv.conf
search intranet.lan
nameserver 10.0.1.5
#options edns0
root@psi:/etc # echo -n "nameserver 8.8.8.8" | resolvconf -a em0
root@psi:/etc # cat resolv.conf
# Generated by resolvconf
nameserver 8.8.8.8
See what I mean?

I noticed you did use the correct syntax in that script of yours but strangely enough you didn't in your post itself. If you're writing howto's then it's trivial to make sure that the commands you share actually work.

And about the script removing stuff from /etc/resolv.conf, why not simply make a backup prior to messing with it and then restoring that backup later?

No offense intended but I get the impression that you simply took an existing script, edited some parts but don't fully understand how it actually works. That by itself isn't a problem, but it becomes a different story if you start sharing howto's which contain commands that simply don't work.

Another example: if_tap_load="YES" has no place in /etc/rc.conf, I think you mistook that for /boot/loader.conf. If you want to load kernel modules using rc.conf you'd be looking at kld_list instead, see also rc.conf(5) and/or loader.conf(5).

Either way, thanks for sharing. Despite my criticism I definitely appreciate the effort you put into all this. Just take on a little more effort next time and check your facts before sharing, that way you'll avoid problems like these.
 
If you remove the route but leave the DNS then your dns queries will go through the VPN then out to the broad internet and back to your local ISP's DNS...
That's still leaking. What you need is to use the DNS provided by your VPN provider or hand jam one manually, something you like to use, something public.
You need a default route to route the traffic out the VPN. We're not just going to an office network. And from a paranoia standpoint you'd limit stuff like that with a firewall
which is a much different issue. Not only that but if you're not careful you'll have problems with keeping your VPN alive, loosing the route to the server.

Typeo I just missed a space between nameserver and addr, this is true I'll edit.

The point was that the openvpn provided scripts do as you said with resolv.conf but that won't do anything if it's been taken over by local_unbound.
And you'd still be leaking DNS.

No offense taken, I've been a programmer since 1978. Paper tape and assembly language on an Interdata 716 then IBM 3090's and MVS in '90
I started with Unix in 1982 and Linux when it was 2 floppies. I retired from IT work in 2008 after chasing hackers for unnamed players internationally.

The if_tap_load was a cut and paste error I said the correct place earlier. Sorry.

I initially wrote a script my self but then modified a different script that was more closely related to the ones included by openvpn
because it would be easier for others to follow the similarity between the two.

I'll correct and fix. thanks
Thom
 
If you remove the route but leave the DNS then your dns queries will go through the VPN then out to the broad internet and back to your local ISP's DNS...
No they won't. Notice that I mentioned default route, without a default route entry the host will have no way to access anything beyond the local network. Using a VPN doesn't change that.

However, I did make a flawed assumption up there: in a home situation the router is often both the default gateway but also acts as a DNS server. In such scenarios removing the default route would not prevent the host from contacting the DNS server because it's in its local network. That could eventually lead up to unwanted data.
 
True enough with no default route nothing goes anywhere... kinda defeats the purpose... that's a lock so big that it makes the system useless. he he...
My point was removing routes from em0, and placing another default gateway out the VPN, then not changing the DNS will still leak because the traffic
then goes out the VPN and back to the local ISP. If your DNS is your local router that's additionally a problem. So solving the DNS problem by modifying DNS is better than trying to solve the DNS problem by adding the complexity of routing issues as well. It's keeping everything in it's proper network layer... Solving a layer 4 or 5 problem by changing something on layer 3 (routing) can have unintended consequences.
 
Back
Top