Welcome to the most active Linux Forum on the web.
Go Back > Forums > Linux Forums > Linux - Networking
User Name
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.


  Search this Thread
Old 12-03-2017, 10:37 AM   #1
Senior Member
Registered: Jul 2006
Location: North Carolina
Distribution: CentOS 6, CentOS 7 (with Mate), Ubuntu 16.04 Mate
Posts: 2,127

Rep: Reputation: 174Reputation: 174
How I connect to a VPN with no DNS leakage and a kill switch.

For the past year or more I have been using a couple of commercial VPNs to carry my home Internet traffic. One comes "free" with my annual Usenet subscription and the other is ProtonVPN. Proton is a good organization and I don't mind chipping in a few dollars a month towards their secure email and VPN services. That said, I have been refining my setup during this time and finally have it working to my liking. THANK YOU to many members of this forum for their assistance along the way. I thought I might post my monologue here for a couple of reasons. First, I hope it might be useful to other members and second, perhaps more importantly, I would like to have some other eyes look at it and see if I have done anything wrong.

The objectives of my setup are to:

- Share my Internet connection to the computers on my LAN.
- Provide a common outward facing firewall for my LAN
- Share my VPN connection to the computers on my LAN
- Prevent DNS leakage out of the VPN

Here is my network design:

DSL Modem <-Ethernet-> MagicPC <-Ethernet-> Switch <-Ethernet-> my LAN

The DSL Modem is running in transparent bridge mode. It does not act as a router. The Internet IP address is assigned to the "MagicPC." The MagicPC is a small Dell PC running CentOS 7.4 as a headless server. I call it the MagicPC because it serves as a router, firewall, DHCP server, VPN sharing box etc. which is too much to type on the line above The MagicPC has a built in Ethernet NIC, a WiFi NIC which is disabled and a USB connected USB to Ethernet dongle from StarTech. The NICs were configured using the NetworkManager GUI.

The built in Ethernet NIC - called p1p2 - connects to the DSL Modem. It was configured to Automatically connect to this network (Internet) when available and various other default settings. The critical changes were in the IPV4 Settings tab:

Method: "Automatic (DHCP) addresses only" (this is required so that the ISP's DNS does not get assigned)
Search domains: blank (I will set the name server later)

The dongle Ethernet - "Wired connection 1" is connected to my LAN. The NetworkManager configuration is again all defaults EXCEPT:

IPV4 Settings; Method: "Shared to other computers" This will magically assign the address to this connection. My LAN will use the private addresses - I installed dhcpd on the MagicPC and have reserved IP addresses for the physical machines on my network. Virtual machines pickup addresses from the dhcpd daemon on the MagicPC. Configuring dhcpd is beyond the scope of this post but I might be able to answer some questions about what I have done.

N.B. It is my understanding that by specifying "Share to other computers" as I did above will enable dnsmasq to provide dhcp services to the LAN. I have not verified this and had already installed and configured dhcpd.

At this point I could connect to the Internet from any computer on my LAN except that I do not have a DNS (name server) specified at this point. As I am concerned with DNS leakage - connecting to a DNS server outside of the VPN tunnel - I will leave things in this state for the moment.

The VPN connection is accessed using the OpenVPN program. It may be installed on CentOS thus
#yum install openvpn
Configuration of the VPN is provided by the vendor in the form of something.ovpn files specific to each of the vendor's servers. A username and password are also provided by the vendor. As I will be creating some scripts to to manage my connection I am placing the necessary files in /home/ken/bin or ~/bin. This directory is in my path which makes things a little easier in actual practice. For the rest of this post I will be using examples with ProtonVPN.

The first file I create is ~/bin/propw which will contain my credentials:


I set the permisions to allow only my account to access the file
chmod 600 ~/bin/propw
Yes this is somewhat of a security weakness but as I am the only user on the MagicPC I will live with it. With this file in place and a configuration file present I can connect to the VPN from the command line thus
sudo openvpn --config ~/bin/ --auth-user-pass ~/bin/propw
However, I still need to specify the DNS/name server.

The premise of my approach is that the DNS server used by a Linux computer is specified in the file /etc/resolv.conf. This file is generated by the NetworkManager program when the computer is booted (or the network interface is cycled down and up I believe). This precludes the option of hard coding the ProtonVPN DNS server address into the file. My approach is to manually control the contents of /etc/resolv.conf as the VPN is connected or disconnected.

[It has been suggested to hard code the ProtonVPN address into /etc/resolv.conf and then set the immutable attribute on the file to prevent NetworkManager from overwriting it. This will work but it presents other issues. If you wish to connect to the Internet without the VPN the file must manually be adjusted. Also, Proton VPN uses a couple of DNS addresses depending on which server you are connected to. Including only the correct address in /etc/resolv.conf will increase responsiveness.]

For my next trick I must put the correct name server address in /etc/resolv.conf. To do that I created 3 custom files thus
# DNS servers for OpenDNS

#Generated by Ken - hard coded DNS for ProtonVPN

#Generated by Ken - hard coded DNS for ProtonVPN
ProtonVPN uses two private addresses for their VPN tunnel so I need to use the correct name server address. This may be determined by connecting to the VPN using the command shown above and then
[ken@taylor16 bin]$ ifconfig
        inet  netmask  destination
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  
I examined the output and looked for the information about tun0, the VPN tunnel. This tunnel is on the 10.8.8 subnet thus the name server will be found on I need to replace any existing /etc/resolv.conf with resolv.conf.proton8. I do this by taking advantage of an openvpn feature which allows scripts to be run when the VPN is connected or disconnected.

To accomplish this I added these three lines to the bottom of the .ovpn file
script-security 2
up /etc/openvpn/
down /etc/openvpn/
For this purpose I have a script
# replace /etc/resolv.conf with special version for ProtonVPN
rm /etc/resolv.conf
cp /etc/resolv.conf.proton8 /etc/resolv.conf
The above script is executed when openvpn processes the .ovpn file. When I close the VPN I change the name server back to one which points to I find this to be a reliable and privacy respecting DNS (unlike my ISP). The second script is called by the line "down /etc/openvpn/" which I added to the .ovpn file.
# restore Open DNS /etc/resolv/conf after exiting VPN
rm /etc/resolv.conf
cp /etc/resolv.conf.opendns /etc/resolv.conf
Why are these scripts located in /etc/openvpn instead of ~/bin? No good reason. They happened to be created there during development and I never relocated them. It should not matter where they are located.

A quick review before going further...

sudo openvpn --config ~/bin/ --auth-user-pass ~/bin/propw

- This command asks for my sudo password (I will deal with that alter)
- Now that I have escalated privileges the openvpn program reads credentials from the propw file and the VPN connection information from the .ovpn file. It then makes the VPN connection.
- Finally it puts the correct resolv.conf file in place.

The VPN channels all traffic through the tunnel to the VPN provider's exit server - in this case it is in New Jersey - and to the Internet. Any of the various "what is my IP address" sort of sites will show that my computer appears to have an IP address which is not from my ISP but which is located in New Jersey (or New York depending on the source of their location data.) I have checked several "DNS leak" web sites and have never found this approach to "leak."

When I am done using the VPN I issue Ctrl-c Ctrl-c (not sure why it requires 2 times) and openvpn closes. Its last step is to replace the resolv.conf file with the VPN provider's DNS address with the file containing the addresses for I am now connected to the Internet "naked" Oh my

N.B. If the VPN connection "dies" due to an ISP interruption or some other malfunction beyond the confines of the openvpn machine the connection will stop. Nothing requiring DNS will be able to communicate with the Internet. This is sort of a "kill switch" but not entirely. Bittorrent traffic will resume even if there is not a DNS server available. I will address this later.

Ignoring for the moment the dual NIC setup, this approach to connecting to a VPN could be applied to a single computer. It is a substitute for the NetworkManager-openvpn-gnome package which manages VPN connections from a notication icon on the panel of a gnome or Mate desktop. This method does NOT stop DNS leakage based on my testing. My command line process does.

As for the down sides.
- a terminal must stay open all the while the VPN is connected
- a lot of typing to call up the VPN
- sudo password required each time

I have addressed these as follows:

Install the screen utility
#yum install screen
which works as follows

- open a terminal
- issue the command screen which sort of opens another terminal within the terminal
- issue the VPN connection command and allow it to complete
- issue Ctrl-a D which will detach the screen - the original terminal may be closed and openvpn will continue to run.
- when it is desired to close the VPN or select a different VPN server simply open a terminal and issue the command "screen -r" to reattach the openvpn terminal

In order to reduce the amount of typing I have created scripts containing the openvpn commands. For example ~/pro-nj contains the command to launch the ProtonVPN connection to their New Jersey server which has been used as an example. The file is of course marked executable and as /bin is in my path I simply need to issue the command pro-nj to make the connection. And of course I am prompted for my sudo password.

To eliminate the need to enter my password each time I added the following lines to the to the end of the sudoers file (using visudo as root)
User_Alias FREE = ken
Cmnd_Alias STUFF = /usr/sbin/openvpn
If you are not familiar working with visudo please do a little research first lest you do something undesirable to your system.

At this point I can:

- initiate an ssh terminal session to the MagicPC from any other machine on my lAN
- invoke screen
- connect to the VPN server of my choice with a few keystrokes (e.g. pro-nj)
- leave the screen active with Ctrl-a D
- close the ssh connection and the calling terminal
- enjoy my VPN connection from any computer on my LAN

I mentioned at the beginning I am using the MagicPC as an outward facing firewall for my LAN. This post focuses on the VPN aspect but allow me to say briefly that I configured the firewall quite easily using firewalld in CentOS7. In a nutshell I placed the Internet connection, p1p2 in the "drop" zone. Any incoming traffic is dropped (ignored, not even acknowledged) unless it is in response to a communication initiated from MY side of the firewall. The second NIC which communicates to my LAN is in the public zone. This zone is configured to allow only ssh and vnc-service to access the MagicPC from the LAN side. Perhaps this should be the subject for another post.

Finally, the issue of a kill switch. As I described above. my approach will stop any Internet communication which requires DNS in the event that the VPN connection dies. This does not stop Bittorrent.

How to deal with Bittorrent?

Bittorrent does not need DNS once a torrent file had been processed and the Bittorrent traffic has started. If the VPN is dropped the traffic will stop briefly and then restart almost immediately as Bittorrent works by IP address directly. One of the reasons people use a VPN is to shield Bittorrent traffic. It is therefor not desirable for the torrent client to resume traffic on a naked connection if the VPN drops out. Here is my approach (still a work in progress):

n.b. Only select ProtonVPN servers allow P2P traffic including Bittorrent. In my example I am using Netherlands-06.

My approach is to check once per second to verify if the VPN is connected. I tried doing this by pinging the DNS over the VPN. This did not work as the DNS server would quickly tire of my pings, flip me the digital bird and refuse to respond. This caused my script to believe the VPN was down.

My second approach was to ping my tunnel IP addrss. This occurrs locally on the MagicPC so it was instantaneous and did not tire of working. Except that my tunnel address was not always the same - even using the same ProtonVPN server.

Finally I decided to simply check for the presence of the tunnel. It it was not there, the VPN was obviously down. I created the script
# This script will kill a transmision instance if the VPN connection is lost.
# Start this script before starting a Bittorrent job as DNS is not 
# required for Bittorrent and it will continue if the VPN drops 
# thus exposing the true IP adddress
# Update: This scrip is now launched by the openvpn script - allow 
# 10 seconds for the VPN to come up
sleep 10

while [ 0 -lt 1 ]
# Check for the presence of the tunnel
   ifconfig tun0 >> /dev/null
   if [ $? -eq 0 ]; then
      sleep 1
      echo "VPN down"
      killall transmission-gtk

Essentially I am looking for the tunnel with ifconfic and examining the exit code from that command. I am also making the assumption that the Bittorrent traffic is resulting from the use of the Transmission program running on the MagicPC. That is generally the case as the MagicPC only draws about 8 Watts compared to a couple of hundred for my workstation. It is up all the time so might as well run large download jobs on it.

I am considering changing the "killall transmission-gtk" command to "sudo ifdown p1p2" which will disconnect the incoming Ethernet connection from my DSL modem and thus cut off ALL Internet traffic to/from my LAN if the VPN dies.

Here is the modified VPN connecting script for this special case (pro-NL06)
# launch the scram script - in case the VPN dies, kill any bittorrent job &
sudo openvpn --config ~/bin/ --auth-user-pass ~/bin/propw
That is what I have to offer. PLEASE feel free to ask questions and/or make suggestions. Perhaps if this document meets the requirements it could be promoted to a Tutorial



p.s. Most of the above will work on Ubuntu. NetworkManager on Ubuntu is a little different in how it names connections. This impacts the kill switch approach - a little tweaking required. Please ask if you wish to run this on Ubuntu. I am setting up a Raspberry P1 3 as a possible replacement for the MagicPC. It runs UbuntuMate just fine so that would be the OS of choice.

Last edited by taylorkh; 12-03-2017 at 10:44 AM.


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
/etc/openvpn/update-resolv-conf and DNS leakage taylorkh Linux - Networking 3 06-27-2017 02:46 PM
How (I think?) I solved DNS leakage on my CentOS 7 PC taylorkh Linux - Networking 1 03-31-2017 01:05 PM
Firewall restore and VPN kill switch johnyjj2 Linux - Networking 1 05-27-2015 06:24 PM
IPSEC VPN "charon too long to start... - kill kill" saavik Linux - Networking 1 09-24-2013 01:39 PM
Connect to vpn server, no DNS specified fatrandy13 Linux - Software 2 12-19-2005 09:08 PM > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 06:11 AM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration