Personal VPN

A HOWTO for running a personal VPN service using openvpn.

What is a personal VPN?

Typically, the goal of a normal VPN is to give trusted clients (optional) access to a trusted network.

The goal of a personal VPN service is totally different:

  • We don’t trust the clients
  • Clients route ALL their traffic through the VPN and out onto the public internet.
  • Clients have no ability to communicate with eachother over the VPN.

The purpose of this is to bypass surveillance from the ISP, encrypt the last mile transmission, and prevent data retention of IP addresses.

This HOWTO will create a personal VPN service with the following properties:

  • Each VPN client gets their own public IP address. This means they can accept incoming connections on the public IP and it will get routed to their VPN IP. It also means two users won’t have the same IP at the same time. The IP might change between sessions.
  • Any user with a valid login/password in your user database may use the VPN service. For this HOWTO, we do not create client certificates.
  • The client will use the DNS on the VPN server.

Creating the certificates

There are many great tutorials on the internet for creating certificates for use with openvpn. The main howto is very useful as well.

For this setup, we don’t need client certificates, so you can skip that part. In brief, the process is:

Create the Certificate Authority

apt-get install openvpn
cp -r /usr/share/doc/openvpn/examples/easy-rsa/ /etc/openvpn
cd /etc/openvpn/easy-rsa
edit vars
. ./vars

This will create:

  • keys/ca.crt — This is the root certificate of the CA we created. In order for a client to connect to your vpn, they will need a copy of this file in advance.
  • keys/ca.key — This is the private key of the CA. It must be kept private and secure. You will only use it to create server certificates.

Create a server certificate

cd /etc/openvpn/easy-rsa

Replace with the actual DNS of the vpn server. It must match, or the client will reject the certificate.

This will create:

  • keys/ — The server certificate. This will be sent to the clients by openvpn.
  • keys/ — The server private key. Keep this secure.

Build diffie hellman parameters

The dh file is used to negotiate a shared secret over an insecure connection.

cd /etc/openvpn/easy-rsa

This generates:

  • dh1024.pem — we will specify this file in our openvpn configuration. It is not particularly secret, but you don’t distribute it to clients.

A minimal test setup

apt-get install openvpn

Create the file /etc/openvpn/personal-vpn.conf:

dev tun

ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/
key /etc/openvpn/easy-rsa/keys/
dh /etc/openvpn/easy-rsa/dh1024.pem


plugin /usr/lib/openvpn/ login

On the server run (as root):

export LD_PRELOAD=/lib/
openvpn /etc/openvpn/personal-vpn.conf

(you can omit the LD_PRELOAD in debian ‘squeeze’ or later)

Now run ifconfig on the server to check that it created a tun0 network interface and set the ip to be

On the client run (as root):

sudo openvpn --remote --client --dev tun --auth-user-pass --ca ca.crt

The file ca.crt is the one you created earlier. Login with any normal user account on the VPN server. Later we will use an SQL user database.

If it works, you can ping the VPN server, but you won’t yet be able to get out onto the internet over the VPN. That will come later.

A word on address space

It is good to use the 172 IP netblock because it is rarely used for home NAT. We have to make sure that the IP address we assign to clients does not conflict with any other networks they are on. So, it would be very bad to pick as a VPN network, because this is the most common IP space used for local networks.

The possible reserved netblocks that can be used for your VPN:

IP range max addresses class max netmask – 16,777,216 single class A ( – 1,048,576 16 contiguous class Bs ( – 65,536 256 contiguous class Cs (

Routing all the client’s traffic through the VPN

For this HOWTO, we want all the client’s traffic to be routed through the VPN server. To tell the client to do this, just add these lines to the openvpn configuration:

push "redirect-gateway def1"
push "dhcp-option DNS"

Where is the VPN IP address the VPN server.

We need to run a DNS server on the VPN server otherwise the client won’t have access to DNS anymore (since most ISPs will block access to their DNS from other networks, and once connected to the VPN you will appear to be coming from an external network).

Setting up a DNS server is beyond the scope of this HOWTO, but a simple one might look like:

apt-get install bind9

Edit /etc/bind/named.conf.options

acl "trusted" {;

acl "vpnclients" {;

options {
  allow-query {
  allow-recursion {

Network configuration

OK, so you have the VPN connection established and you can ping the VPN server from the client, and the client from the VPN server.

How do you get your traffic out to the internet? There are two methods listed here: either everyone can share a single IP or you can give each client their own public IP.

Option A: all clients share a single public IP address

This setup is fairly easy. It is just like if you were setting up a local network with a firewall and NAT. Run this once:

echo '1' > /proc/sys/net/ipv4/ip_forward
iptables --table nat --append POSTROUTING --source --out-interface eth0 --jump MASQUERADE

To confirm the iptables are setup:

iptables --table nat --list

should produce:

target     prot opt source               destination         
MASQUERADE  all  --        anywhere

To remove this:

iptables --table nat --delete POSTROUTING --source --out-interface eth0 --jump MASQUERADE

Option B: each client gets their own public IP address

For this setup, we will be generating a unique route for each client. These routes will be setup and torn down in special scripts called by openvpn when a new connection is created or destroyed.

In this example, we have available the public IPs (ie .192 to .254) to use for the VPN. We will hand out private IPs in the range and then set up a 1:1 mapping between the block and the block.

cd /etc/openvpn
chmod u+x *.sh

In /etc/openvpn/person-vpn.conf, add these lines:

script-security 2
client-connect /etc/openvpn/
client-disconnect /etc/openvpn/
topology subnet

The option topology subnet will make openvpn allocate a single IP for each client. The default is p2p, which will allocate a /30 subnet to each client. This is more compatible with older openvpn clients, but throws off our 1:1 mapping.





ifconfig eth0:$ip_suffix up $public_ip netmask $netmask

# rewrite incoming packets to use vpn ip
iptables --table nat --append PREROUTING --dst $public_ip --jump DNAT --to-destination $vpn_ip

# rewrite outoing packets to use public ip
iptables --table nat --append POSTROUTING --src $vpn_ip --jump SNAT --to-source $public_ip

exit 0





ifconfig eth0:$ip_suffix down
iptables --table nat --delete PREROUTING --dst $public_ip --jump DNAT --to-destination $vpn_ip
iptables --table nat --delete POSTROUTING --src $vpn_ip --jump SNAT --to-source $public_ip

exit 0

Database authentication

OK, we are almost done. The final thing is to use an external database for the user/password, instead of using the /etc/password file.

Change /etc/openvpn/personal-vpn.conf to use openvpn instead of login for pam authentication:

plugin /usr/lib/openvpn/ openvpn

Then create the file /etc/pam.d/openvpn:

auth required /lib/security/ host= user={dbuser} passwd={dbpass} db={db} table=users usercolumn=username passwdcolumn=password where=is_active=1 crypt=1
account sufficient
session sufficient

Replace {dbuser} and {dbpass} with whatever is appropriate for your database. In this example, we also limit access to records where is_active = 1.

Putting it all together

Modify /etc/default/openvpn:

export LD_PRELOAD=/lib/

The fully completed /etc/openvpn/personal-vpn.conf


dev tun
keepalive 20 120
topology subnet


#user nobody    \ well, this sucks, but the current setup needs to be able
#group nogroup  / to run ifconfig and iptables. so, for now, we run as root.

script-security 2
client-connect /etc/openvpn/
client-disconnect /etc/openvpn/


ca    /etc/openvpn/easy-rsa/keys/ca.crt
cert  /etc/openvpn/easy-rsa/keys/
key   /etc/openvpn/easy-rsa/keys/
dh    /etc/openvpn/easy-rsa/dh1024.pem


push "redirect-gateway def1"
push "dhcp-option DNS"
# ^^ note: if using MASQUERADE, push the vpn ip for dns. If using SNAT, push the public ip.


plugin /usr/lib/openvpn/ openvpn


dev tun
easier than tap
keepalive 20 120
keeps the connection from dying due to inactivity.
topology subnet
allocates only a single ip per client, instead of 4.
script-security 2
allows client-connect scripts
client-connect /etc/openvpn/
where the networking is setup for a client
client-disconnect /etc/openvpn/
where the networking is taken down for a client
push “redirect-gateway def1”
makes the client send all their traffic to the server.
push “dhcp-option DNS”
tells the client to use our dns server. note: if using MASQUERADE, push the vpn ip for dns. If using SNAT, push the public ip.
don’t use client certs. the clients are not ‘trusted’
plugin /usr/lib/openvpn/ openvpn
use pam for password authentication, service named ‘openvpn’ (ie whatever is in /etc/pam.d/openvpn)
not sure of the benefit. we don’t have a common-name (because there is no client cert) so this seemed like a good idea.

Other commonly suggested server options:


But I am not sure what the benefit is.

Configuring clients

You must download to each client the ca.crt file created earlier.

Network Manager (gnome)

apt-get install network-manager-openvpn
/etc/init.d/network-manager restart
  • Click on the network manager applet
  • Select VPN Connections > Configure VPN menu item
  • Click Add button
  • Choose OpenVPN if you get a choice of vpn type. Then click Create…
  • Use these settings:
    • Gateway:
    • Type: password
    • User name: your user name on
    • Password: your password
    • CA Certificate: the file ca.crt.
    • Advanced:: TLS Authentication: select “verify peer…”, and select “server” in the list “remote peer certificate TLS type” (you will need network-manager-openvpn >= 0.9.8)

If you move the location of the CA cert file, then the vpn will break.

After you have saved the configuration, you can click on the network manager applet and apply it. If it worked, you should see a lock in the corner of the applet. If it didn’t work, tail /var/log/syslog.

tunnelblick (mac)

Edit the configuration file:

dev tun
remote 1194
ca /path/to/ca.crt

You can easily build custom bundles with tunnelblick so that you can distribute a single program pre-configured for a particular vpn with the certificates already included. This way, no configuration is required, just download and double click.

openvpn command line (mac and linux)


apt-get install resolvconf openvpn

required files:

  • /etc/openvpn/riseup/client.conf: a configuration file for connecting as a client
  • /etc/openvpn/riseup/auth: a file to store your username and password
  • /etc/openvpn/riseup/riseup-ca-cert.pem: the CA cert needed to authenticate the server.

running openvpn:

sudo openvpn --config /etc/openvpn/riseup/client.conf

Create the file /etc/openvpn/riseup/auth:


The first line is your vpn username, the second line is your password. This can be commented out for a login prompt on startup

Create the file /etc/openvpn/riseup/client.conf:

# Specify that we are a client and that we
# will be pulling certain config file directives
# from the server.

# Use the same setting as you are using on
# the server.
# On most systems, the VPN will not function
# unless you partially or fully disable
# the firewall for the TUN/TAP interface.
dev tun

# Are we connecting to a TCP or
# UDP server?  Use the same setting as
# on the server.
;proto tcp
proto udp

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
# choose whichever is closer for you
remote 1194
;remote 1194

# Keep trying indefinitely to resolve the
# host name of the OpenVPN server.  Very useful
# on machines which are not permanently connected
# to the internet such as laptops.
resolv-retry infinite

# Most clients don't need to bind to
# a specific local port number.

# Downgrade privileges after initialization (non-Windows only)
user nobody
group nogroup

# Try to preserve some state across restarts.

# If you are connecting through an
# HTTP proxy to reach the actual OpenVPN
# server, put the proxy server/IP and
# port number here.  See the man page
# if your proxy server requires
# authentication.
;http-proxy-retry # retry on connection failures
;http-proxy [proxy server] [proxy port #]

# Wireless networks often produce a lot
# of duplicate packets.  Set this flag
# to silence duplicate packet warnings.

# SSL/TLS parms.
# See the server config file for more
# description.  It's best to use
# a separate .crt/.key file pair
# for each client.  A single ca
# file can be used for all clients.
ca /etc/openvpn/riseup/riseup-ca-cert.pem
auth-user-pass /etc/openvpn/riseup/auth

# Verify server certificate by checking
# that the certicate has the nsCertType
# field set to "server".  This is an
# important precaution to protect against
# a potential attack discussed here:
# To use this feature, you will need to generate
# your server certificates with the nsCertType
# field set to "server".  The build-key-server
# script in the easy-rsa folder will do this.
remote-cert-tls server

# If a tls-auth key is used on the server
# then every client must also have the key.
;tls-auth ta.key 1

# Select a cryptographic cipher.
# If the cipher option is used on the server
# then you must also specify it here.
;cipher x

# Set log file verbosity.
verb 3

# Silence repeating messages
mute 20

# Log-File
log /etc/openvpn/riseup/openvpn.log

script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf


Ive followed the above instructions to the letter! but I constantly get the

AUTH: Received AUTH_FAILED control

is my login details the same( for openvpn ) as what I use to write this querie?
or have I missed something
I dont think I have as your instructions are fairly easy to follow


i would confirm that pam is configured correctly. there is some tool for testing a pam auth. try that. also, the logs should have more details, what do they say?


auth-nocache disrupts the connection pretty frequently, requiring manual entry of ones username and password. After I disabled that option, my VPN connection was much more reliable.