Login
     
 
     
Articles:
List of all articles
List by categories
Search in articles
>> admin_tools
>> c
>> cli
>> database
>> debian
>> games
>> gnu
>> hardware
>> internet
>> linux
>> microsoft
>> network
>> os
>> php
>> programming
>> python
>> security
>> server
>> shell
>> text_editor
>> tools
>> web_dev
Links:
List all links
List by categories
Search in links
Online Tools:
>> gnuvd
Other Things:
Login
Admin
Pages
Blog
News
Guestbook
Contact
Sponsors:
None Yet!
Sponsor this project
[ Source ]

create a secure virtual private network with openvpn

Created: 2007-11-28 23:19:00
Modified: 2009-04-25 13:34:00
Categories: tools server security network internet debian
Keywords: vpn openvpn virtual private network
Description:

With openvpn you can easy create a very secure virtual network.

Introduction

With openvpn you can easy create a virtual private network so that you can access this network from outside you own network. This will be ideal for laptops, when you travel and need to access you network. Sure you can access you hosts from anywhere with ssh, but this have some limitation and tunneling everything into this will give some pain.

When setting up openvpn, you can choice about two different ways how the server will act. You can setup one client to one client. This will be ideal to create some bridge between two trusted network located at a different location. Or to setup a server who may receive different openvpn client connections.

Installation and setup

At the time of writing this article, openvpn version 2.0.9-4etch1 is available on Etch and version 2.1~rc8-1 on Lenny.

For the server and client side, the install and the questions during the install are the same.

aptitude install openvpn

During the install, you will be asked for

If you accept here, the package will make a special device called
/dev/net/tun for openvpn's use. If you refuse, the device won't be 
made now. Read README.Debian for details on how to make it. If you 
are using devfs refuse here.

Would you like a TUN/TAP device to be created?

            <Yes>                           <No>

Select Yes.

Then you get the question:

In some cases you may be upgrading openvpn in a remote server using a 
VPN to do so. The upgrade process stops the running daemon before 
installing the new version, in that case you may lose your connection, 
the upgrade may be interrupted, and you may not be able to reconnect to 
the remote host.

Unless you do your upgrades locally, it is advised NOT to stop 
openvpn before it gets upgraded. The installation process will 
restart it once it's done.

This option will take effect in your next upgrade.

Would you like to stop openvpn before it gets upgraded?

            <Yes>                           <No>

Select No.

Note that i don't got these questions when installing openvpn om my Debian Etch and Lenny box anymore! It seems that some things have changed. You can get the latest question with "dpkg-reconfigure openvpn".

One server, one client

Creating the static.key file:

cd /etc/openvpn

openvpn --genkey --secret static.key

Copy this file static.key to the clients in the directory /etc/openvpn.

On server side, create a file /etc/openvpn/tun0.conf and add the following:

dev tun0
ifconfig 10.9.8.1 10.9.8.2
secret static.key

# Enable compression the VPN link
# must be enabled on both sides
comp-lzo

# Verbosity level.
# 0 -- quiet except for fatal errors.
# 1 -- mostly quiet, but display non-fatal network errors.
# 3 -- medium output, good for normal operation.
# 9 -- verbose, good for troubleshooting
verb 3

The client is another computer on another network. A computer on the other side of the world who has also an internet connection.

On the client side create the file /etc/openvpn/tun0.conf and add the following:

# The remote is the ip (or hostname) of the gateway
remote 84.198.69.134
# set float if the gateway get's a dynamic IP
float
dev tun0
ifconfig 10.9.8.2 10.9.8.1
secret static.key

# Enable compression the VPN link
# must be enabled on both sides
comp-lzo

# Verbosity level.
# 0 -- quiet except for fatal errors.
# 1 -- mostly quiet, but display non-fatal network errors.
# 3 -- medium output, good for normal operation.
# 9 -- verbose, good for troubleshooting
verb 3

The routing table needs to be adjusted so that all the data won't pass to our old default gateway but to the new gateway point. Issue the command route to see the routing table:

This output

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.9.8.1        *               255.255.255.255 UH    0      0        0 tun0
localnet        *               255.255.255.0   U     0      0        0 eth3
default         moon.pinguin    0.0.0.0         UG    0      0        0 eth3

Remove the default (old) route:

route del default

Add the new route:

route add default gw 10.9.8.1

See the modified routing table. Issue the command route:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.9.8.1        *               255.255.255.255 UH    0      0        0 tun0
localnet        *               255.255.255.0   U     0      0        0 eth3
default         10.9.8.1        0.0.0.0         UG    0      0        0 tun0

On the server side, the firewall needs to be adjusted aswell. For iptables use the following commands:

iptables -A INPUT -i tun+ -j ACCEPT
iptables -A INPUT -i $INTDEV -p UDP --dport 1194 -j ACCEPT

If you want to be able to ping, you must allow iptable too:

## Set ICMP open to the internet  tune0
$IPTABLES -A INPUT -i tun0 -p ICMP -j ACCEPT
$IPTABLES -A OUTPUT -o tun0 -p ICMP -j ACCEPT
# ICMP naar internet filteren
$IPTABLES -A INPUT -i tune0 -p ICMP --icmp-type 0 -j ACCEPT
$IPTABLES -A INPUT -i tune0 -p ICMP --icmp-type 3 -j ACCEPT
$IPTABLES -A INPUT -i tune0 -p ICMP --icmp-type 5 -j ACCEPT
$IPTABLES -A INPUT -i tune0 -p ICMP --icmp-type 11 -j ACCEPT

Start openvpn on both side with the follow command:

openvpn --config /etc/openvpn/tun0.conf

One server, many clients (routed setup)

We should first copy the key generator somewhere at a secure place. This will avoid to loose the config and keys if we later remove or upgrade the package:

We first create the ca keys:

mkdir /etc/openvpn_keys
cp -r /usr/share/doc/openvpn/examples/easy-rsa /etc/openvpn/
cd /etc/openvpn/easy-rsa

Edit the vars file. I changed the KEY_SIZE to 2048, and some other stuff on the end of the file:

export KEY_COUNTRY=BE
export KEY_PROVINCE=Vlaams-Brabant
export KEY_CITY=Halle
export KEY_ORG="DVM@Home"
export KEY_EMAIL="david.van.mosselbeen@gmail.com"

Now let start the process:

source ./vars
./clean-all
./build-ca

As we filled the vars file, some values should not be entered twice during the ./build-ca. Just the Organizational Unit Name (where i filled "IT"), Common Name (eg, your name or your server's hostname) []: dvm.zapto.org

We now create the certificates and keys:

./build-key-server server

Again as we did with the ./build-ca, just that you may fill in some cool challenge password. And had need to manually fill in the company name (DVM@Home).

Respond yes to sign the certificate and commit.

We now need to create the keys for the clients:

./build-key myClient1Hostname
./build-key myClient2Hostname
...

Note that each client needs to have his own common name. So the CN for client1 could be client1.dvm.zapto.org. For the clarity you can use the hostname of the concerned client in case of client1.

If later, you need to create an additional key for a client:

cd /etc/openvpn/easy-rsa
source ./vars
./build-key aNewClient

If you have created the client keys on name of the hostname, don't forget to adjust the above line.

Generate Diffie Hellman parameters:

./build-dh

Note that this command take a very long time, especially because of the length of the 2048 bit key. This took around 20 minutes on a P3 664MHz.

We should now copy some keys to some clients, here's the list with they usage:

Filename Needed By Purpose Secret
ca.crt server + all clients Root CA certificate NO
ca.key key signing machine only Root CA key YES
dh{n}.pem server only Diffie Hellman parameters NO
server.crt server only Server Certificate NO
server.key server only Server Key YES
client1.crt client1 only Client1 Certificate NO
client1.key client1 only Client1 Key YES
client2.crt client2 only Client2 Certificate NO
client2.key client2 only Client2 Key YES
client3.crt client3 only Client3 Certificate NO
client3.key client3 only Client3 Key YES

On server side, copy the needed files from the keys directory where we have create the certifications ca.crt, dh2048.pem, server.crt, server.key to the directory /etc/openvpn/.

On the client side, copy the needed files from the server where we have create the certifications files ca.crt, client.conf. client1.crt, client1.key to /etc/openvpn/.

On server side, copy the default config file:

zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz \
> /etc/openvpn/server.conf

On client side, copy the default config file:

cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf \
/etc/openvpn/

Adjust the config file on server and client side. On the client side i had need to add a line with as content float.

Note that the firewall needs to be adjusted, like the many-clients to one server don't use the same network setup.

On server side, i took a copy of good working "client.conf", so that in the future, if a new client needs to have a VPN connection, i first create the client keys and provide a modified version of the client.conf from the server. As in the client.conf file we just need to change two lines referencing to the client keys.

Testing if the vpn work

You should now start the openvpn client on server side first:

For both server and client, cd first to /etc/openvpn/.

openvpn --config /etc/openvpn/server.conf

And then on the client:

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

If you are running the One server, one client. You should be able to ping 10.9.8.2 from the server and 10.9.8.1 from the client.

If you are running the One server, many clients. You should be able to ping 10.8.0.5 from the server and 10.8.0.1 from the client.

Firewalling

Before everything works like expected, even a ping, the firewalls needs to be configured on server and client side so that it permit the openvpn and other traffic.

vuurmuur

I use vuurmuur to manage the iptables firewall on my gateway. Here's an overview of the vuurmuur config so that i'm able to surf on the web and do some other stuff. It's up to you to add or remove some more rules depending on your needs!

Server side - One server, one client

Note that the following vuurmuur firewall config is for the one-client to one server setup on server side.

I use vuurmuur to manage the iptables firewall on my gateway. Here's an overview of the vuurmuur config so that i'm able to surf on the web.

Note that the following vuurmuur firewall config is for the one-client to one server setup.

I first created an interface called tun0b with ip 10.9.8.1. Then a zone ptp-vpn with local 10.9.8.0/255.255.255.0 as network within that zone.

I added a host in this new local.ptp-vpn zone. I created a host in this network and specified the ip 10.9.8.2 for this host without a mac address.

As rules i have set:

|     61  ----------------------------[ Openvpn ]----------------------------- |
| [x] 62  Accept   openvpn   local.ptp-vpn     firewall(any)     log,loglimit="|
| [x] 63  Accept   ping      local.ptp-vpn     firewall(any)     log,loglimit="|
| [x] 64  Accept   http      local.ptp-vpn     world.inet        log,loglimit="|
| [x] 65  Accept   ssh       local.ptp-vpn     world.inet        log,loglimit="|
| [x] 66  Snat     any       local.ptp-vpn     world.inet        -             |
|     67  -------------------------------------------------------------------- |

*Note that you may disable the interface tun0b in vuurmuur if you have setup a ptp-vpn and openvpn zone in vuurmuur. As both zone's make use of the same tun0 interface with a different ip. Otherwise vuurmuur will complain that the ip don't match the current interface.*

Server side - One server, many clients

Note that the following vuurmuur firewall config is for the one server with many clients setup on server side.

I first created an interface called tun0b with ip 10.8.0.1.Then a zone openvpn with local 10.8.0.0/255.255.255.0 as network within that zone.

I added a host in this new local.ptp-vpn zone. I created a host in this network and specified the ip 10.8.0.6 for this host without a mac address.

|     71  ------------------[ one server multiples clients ]------------------ |
| [x] 72  Accept   openvpn   any               firewall(any)     log,logprefix=|
| [x] 73  Accept   ping      local.openvpn     firewall(any)     log,loglimit="|
|     74  -------------------[ Access local lan from vpn ]-------------------- |
| [x] 75  Accept   ping      local.openvpn     local.lan         log,loglimit="|
| [x] 76  Accept   ping      local.openvpn     world.inet        log,loglimit="|
| [x] 77  Accept   http      local.openvpn     world.inet        comment="Acces|
| [x] 78  Accept   https     local.openvpn     world.inet        comment="Acces|
| [x] 79  Accept   http      local.openvpn     local.lan         comment="Acces|
| [x] 80  Accept   ssh       local.openvpn     local.lan         -             |
| [ ] 81  Accept   ssh       local.openvpn     firewall(any)     log,logprefix=|
| [x] 82  Accept   ldap      local.openvpn     local.lan         -             |
| [x] 83  Accept   imap      local.openvpn     local.lan         -             |
| [x] 84  Accept   imaps     local.openvpn     local.lan         -             |
| [x] 85  Accept   smtp      local.openvpn     local.lan         -             |
| [x] 86  Accept   portmap   local.openvpn     local.lan         -             |
| [x] 87  Accept   nfs       local.openvpn     local.lan         -             |
| [x] 88  Accept   rpc       local.openvpn     local.lan         -             |
| [x] 89  Accept   samba     local.openvpn     local.lan         -             |
| [ ] 90  Accept   any       local.openvpn     local.lan         log,loglimit="|
| [x] 91  Snat     any       local.openvpn     world.inet        -             |
|     92  ------[ Allow local.lan clients reach local.openvpn clients ]------- |
| [x] 93  Accept   ping      local.lan         local.openvpn     log,loglimit="|
| [x] 94  Accept   ssh       local.lan         local.openvpn     log,loglimit="|
| [x] 95  Accept   ident     local.lan         local.openvpn     -             |
|     96  -------------------------------------------------------------------- |

*Note that you may disable the interface tun0b in vuurmuur if you have setup a ptp-vpn and openvpn zone in vuurmuur. As both zone's make use of the same tun0 interface with a different ip. Otherwise vuurmuur will complain that the ip don't match the current interface.*

Client side

On client side you may also use vuurmuur and setup it up to your needs. Vuurmuur is straightforward and isn't hard/complicated to use. Give some time to setup it correctly.

Or just some little shell script that let all in and out. Trust me, this isn't secure at all!!! At all, why do you use a encrypted secured manner to connect to your LAN?? You are warned, use this at your own risk!!!

Create a file called somethings like unsecure_openvpn_firewall_script.sh and put the following into it.:

1
#!/bin/sh

Then followed by and tune up to your needs!:

# This script is especially made for use with openvpn. It open ALL and let
# EVERYTHINGS in and out, use at your own risk!!!
###
#
IPTABLES="/sbin/iptables"
TUN="tun0"
INTDEV="wlan0"
OPENVPNPORT=1194
PROTOCOL=UDP

# Flush all previous rules
$IPTABLES -F

## Open hole!!
# Let everything in and out!!!
#$IPTABLES -A INPUT -j ACCEPT
#$IPTABLES -A OUTPUT -j ACCEPT
#$IPTABLES -A FORWARD -j ACCEPT
# Let some openvpn specifiq stuff pass
$IPTABLES -A INPUT -i tun+ -j ACCEPT
$IPTABLES -A OUTPUT -o tun+ -j ACCEPT
$IPTABLES -A INPUT -i $INTDEV -p $PROTOCOL --dport $OPENVPNPORT -j ACCEPT
$IPTABLES -A OUTPUT -p $PROTOCOL --dport $OPENVPNPORT -j ACCEPT
# Permit ping
## Set ICMP open to the internet  tune0
$IPTABLES -A INPUT -i $TUN -p ICMP -j ACCEPT
$IPTABLES -A OUTPUT -o $TUN -p ICMP -j ACCEPT
# ICMP naar internet filteren
$IPTABLES -A INPUT -i $TUN -p ICMP --icmp-type 0 -j ACCEPT
$IPTABLES -A INPUT -i $TUN -p ICMP --icmp-type 3 -j ACCEPT
$IPTABLES -A INPUT -i $TUN -p ICMP --icmp-type 5 -j ACCEPT
$IPTABLES -A INPUT -i $TUN -p ICMP --icmp-type 11 -j ACCEPT

Or somethings more realist could be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
NETDEV="wlan0"
TUN="tun0"

echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

iptables -A INPUT -i $NETDEV -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -i $NETDEV -p udp --dport 1194 -j ACCEPT
iptables -A INPUT -i $NETDEV -j DROP

iptables -A OUTPUT -o $NETDEV -p tcp --sport 22 -j ACCEPT
iptables -A OUTPUT -o $NETDEV -p udp --dport 1194 -j ACCEPT
iptables -A OUTPUT -o $NETDEV -j DROP

iptables -A INPUT -i $TUN -j ACCEPT
iptables -A OUTPUT -o $TUN -j ACCEPT
iptables -A FORWARD -i $TUN -j ACCEPT

Set this file now as executable:

chmod +x unsecure_openvpn_firewall_script.sh

And now each time before you start your openvpn connection, start this script as root user first. You should execute somethings like ./unsecure_openvpn_firewall_script.sh.

See the firewall script provided with openvpn /usr/share/doc/openvpn/examples/sample-config-files/firewall.sh

You can now start the openvpn connection manually with:

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

Certificates revocation list

At some point, you want to reject some certification. This could be because you know that a particular client certification got compromised. If you want to be able to reject some certification, you need to create a certification revocation list.

As first thing to do, we need to specify in the openvpn server configuration to check revoked certificates from a particular file:

echo "
# Revoked certificate list
crl-verify /etc/openvpn/keys/certification_revocation_list.pem" >> /etc/openvpn/server.conf

We can now create an empty revocation file with:

# First load (source) the needed config
cd /etc/openvpn/easy-rsa
source vars
# Script isn't executable :-s
chmod +x /etc/openvpn/easy-rsa/make-crl
# Finally we create the revocation list
/etc/openvpn/easy-rsa/make-crl /etc/openvpn/keys/certification_revocation_list.pem

To revoke some certification:

# First load (source) the needed config
cd /etc/openvpn/easy-rsa
source vars
./revoke-full client2

See http://openvpn.net/index.php/documentation/howto.html#revoke for more informations.

Hardening the setup

tls-auth

man-in-the-middle-attack, also know as eavesdropping.

On server side, in the directory where we created the keys:

cd /etc/openvpn_keys/examples/easy-rsa/keys
openvpn --genkey --secret ta.key
cp ta.key /etc/openvpn

Edit now the server.conf and uncomment the line tls-auth ta.key 0.

Now on client side, copy in a secure maner (scp) the ta.key from the server to /etc/openvpn/.

Edit now the client.conf and uncomment the line tls-auth ta.key 1.

Other cipher

With a default setup the Blowfish cipher is used.

One server and client side, uncomment the line cipher AES-128-CBC.

Logging

No default logging is setup, in fact all things are logged to the screen and not to a logfile.

On server side define the line:

log-append  /var/log/openvpn/openvpn.log

Now create this directory on the server:

mkdir /var/log/openvpn.log

chown root:adm /var/log/openvpn

After having changed the server config file and restarted openvpn, you will discover that nothings is sent on screen anymore, so check the logs ;-) Some easy trick can be tail -f /var/log/openvpn/openvpn.log.

You can now create a script for the log rotating. See the directory /etc/logrotate.d/.

I created a file /etc/logrotate.d/openvpn and have fill this with:

# logrotate for openvpn
/var/log/openvpn/openvpn.log {
        rotate 999999
        mail SomeUser@SomeMail.com
        mailfirst
        monthly
        compress
        delaycompress
        missingok
        notifempty
        postrotate
                /etc/init.d/openvpn restart > /dev/null
        endscript
}

The log file /var/log/openvpn/openvpn.log will be rotated monthly, before rotating, the content of the log will be mailed to SomeUser@SomeMail.com. 999999 rotates will be keept and all will be compressed.

Startup script

Openvpn won't startup default, some few easy action is required. Before configuring the system to automatically startup openvpn at boot time. Be sure that the set is well been tested. You should first experiment and adjust all the wanted options before letting the system start openvpn at boot time.

On server side, i adjusted the file /etc/default/openvpn and have commented the line #AUTOSTART="none" and set AUTOSTART="server".

On client side, i won't let openvpn startup at boot time, because the client is a laptop and it's possible that this laptop may be connected to some LAN's where the port 1194 is blocked by the firewall. Anyway if you want to let openvpn start at boot time, adjust the same lines as for the server, but replace the work server with client.

Tools

Things left to do

  • Tweak the Bind9 DNS server so that we may be able to ping the clients connecting with the hostname. Actually no hostname lookup is possible. We need to ping the client on his ip. See also the ;push "dhcp-option DNS 10.8.0.1".
  • Load balancing. See remote-random. Should be two remote server at different locations?
  • Is tls-server and tls-client needed?
  • See for the options: ipchange (--ipchange /script-ip.sh), float (float should be set as we get the ip of the ISP, see DHCP). shaper throttles the outgoing data bandwidth, only works for outgoing traffic. route-up (--route-up /script.sh) - start script when route is up. redirect-gateway force all traffice to pass to the VPN??
  • Max connections for a vpn server is 128?
  • See for tls-server and tls-client.

Config files

Resources

Books

  • Building and integrating virtual private netwoks. By Packt publishing. ISBN 1-904811-85-X. http://www.packtpub.com. First published on april 2006.

On the web

Comments leaved by users (total: 0)

No comments yet!

Add a comment

obfuscated letters
 
  • Do you know that you may use some special markup syntax to create header, italic, bold, styling and links and much more. See the sandbox for the markup language.
  • Do you need some other help?

[ Toggle on/off history ]

Item History:

120 | 2008-11-09 01:51:12 | view diff
Added an excellent link to the resources.
121 | 2008-11-09 02:16:56 | view diff
Added info about certificate revocation list
252 | 2009-04-25 13:30:38 | view diff
No revision comment
253 | 2009-04-25 13:32:12 | view diff
No revision comment
254 | 2009-04-25 13:33:17 | view diff
No revision comment
255 | 2009-04-25 13:34:13 | view diff
No revision comment
256 | 2009-04-25 13:37:07 | view diff
No revision comment

Login:
User Name
Password

Last Articles
python stuff concerning python
2009-07-22 12:00:00
vim
2009-06-06 23:53:00
fluxbox
2009-05-23 12:42:00
setting up a toshiba satellite a110-178
2009-05-21 15:35:00
create a secure virtual private network with openvpn
2009-04-25 13:34:00
>>> Read more...

Last News
Released pyguicms 1.0.0-beta1
2008-06-02 21:20:00
guicms replaced by pyguicms
2008-04-27 17:39:00
pyguicms up and running and online
2007-11-29 22:31:00
>>> Read more...

Last Links
mxtoolbox
2009-09-25 17:54:00
minibikeshop
2009-09-05 12:43:00
magicbike
2009-09-05 12:40:00
systranet
2009-07-22 11:42:00
transfer big files
2009-07-22 11:42:00
>>> Read more...

Last Pages
sandbox
2008-09-07 22:30:00
about
2008-09-07 22:29:00
help
2008-09-07 22:25:00
welcome page
2008-09-07 18:27:00
python stuff to check
2007-12-03 00:16:00
>>> Read more...