HOWTO: Using OpenVPN on Debian GNU/Linux

Here's a quick HOWTO for setting up an OpenVPN server and client on any (Debian, in this case) Linux machine of your choice. I'm running an OpenVPN server on a box at home, and a client on my laptop, so I can securely route all my laptop traffic through my OpenVPN server, no matter where I am.

I highly recommend reading the official OpenVPN HOWTO from top to bottom, at least once. But here's a short, condensed HOWTO (specifically geared towards my needs, yours might be different):

On the server:

Install OpenVPN (apt-get install openvpn), then copy the "easy-rsa" files to /etc/openvpn/easy-rsa from where we'll use them to create our keys and certificates:

  $ cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/easy-rsa
  $ cd /etc/openvpn/easy-rsa

In the vars file change the KEY_SIZE variable from 1024 to 4096 for good measure:

  export KEY_SIZE=4096

Then, read in the vars file, clean old keys and certificates (if any) and create new ones:

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

You'll now have the chance to enter some data such as country code (e.g. "DE"), state/province, locality, organization name, organizational unit name, common name, name, and email address. The values you choose don't really matter much (except for commonName, maybe, which could be your hostname or domain or such). Finally, the ca.key (root CA key) and ca.crt (root CA certificate) files will be created.

Next, we'll create the server key:

  $ ./build-key-server server

You'll have to enter lots of info again (see above), commonName could be "server" or such this time. Upon "Sign the certificate? [y/n]" say y, as well as upon "1 out of 1 certificate requests certified, commit? [y/n]". Finally, the server.key and server.crt files will be created.

Same procedure for creating a client key (I used "client1" as filename and commonName here):

  $ ./build-key client1

Next up we'll generate Diffie Hellman parameters (this will take a shitload of time due to keysize=4096, go drink some coffee):

  $ ./build-dh

When this step is done, you'll have a dh4096.pem file.

As we want to use OpenVPN's "tls-auth" feature for perfect forward secrecy (it "adds an additional HMAC signature to all SSL/TLS handshake packets for integrity verification"), we'll have to generate a shared secret:

  $ openvpn --genkey --secret ta.key
  $ mv ta.key keys

So much for creating keys. Now, we'll have to configure OpenVPN. Copy the default server config file and edit it:

  $ cd /etc/openvpn
  $ cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz .
  $ gunzip server.conf.gz

The most important change in my setup is that I use port 443/TCP instead of the usual OpenVPN default of 1194/UDP. This increases the chances that you'll be able to use OpenVPN in almost all places, even in environments which firewall/block lots of stuff. Port 443/TCP (for https) will almost always be usable. I also uncommented the following line, which tells the client to use the VPN interface (usually tun0) per default, so that all the client's traffic (web browsing, DNS, and so on) goes over the VPN:

  push "redirect-gateway def1 bypass-dhcp"

Here's my server config file (comments and commented out lines stripped):

  port 443
  proto tcp
  dev tun
  ca /etc/openvpn/easy-rsa/keys/ca.crt
  cert /etc/openvpn/easy-rsa/keys/server.crt
  key /etc/openvpn/easy-rsa/keys/server.key  # This file should be kept secret
  dh /etc/openvpn/easy-rsa/keys/dh4096.pem
  ifconfig-pool-persist ipp.txt
  push "redirect-gateway def1 bypass-dhcp"
  keepalive 10 120
  tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0 # This file is secret
  user nobody
  group nogroup
  status openvpn-status.log
  log-append openvpn.log
  verb 3

You can now start the OpenVPN server, e.g. via

  $ /etc/init.d/openvpn restart

Server firewall setup/changes:

I'm running a custom iptables script on pretty much all of my boxes. Here's the relevant changes needed to allow the OpenVPN server to work properly. Basically, you need to enable IP forwarding, accept/forward tun0 traffic and setup masquerading (change "eth0" below, if needed):

  echo 1 > /proc/sys/net/ipv4/ip_forward
  iptables -A INPUT -i tun+ -j ACCEPT
  iptables -A FORWARD -i tun+ -j ACCEPT
  iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
  iptables -t nat -F POSTROUTING
  iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE

My firewall script gets run upon every reboot. If you don't use such a script, you could add the above stuff to your /etc/rc.local file.

On the client:

Install OpenVPN (apt-get install openvpn), then copy the default client config file and edit it:

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

Change the parameters to match the server config (port 443/TCP, and so on) and use "tls-auth /etc/openvpn/ta.key 1" (note the "1" on the client, and the "0" on the server!). Replace with the public IP address of your OpenVPN server. If it doesn't have a public, static IP address already, you can use services such as DynDNS, or (my preferred method), my ssh-based DIY poor man's dynamic DNS setup.

Here's my full client config:

  dev tun
  proto tcp
  remote 443
  resolv-retry infinite
  user nobody
  group nogroup
  ca /etc/openvpn/ca.crt
  cert /etc/openvpn/client1.crt
  key /etc/openvpn/client1.key
  ns-cert-type server
  tls-auth /etc/openvpn/ta.key 1
  verb 3

Now you only need to copy the required certificates and keys to the client (into /etc/openvpn): client1.crt, client1.key, ca.crt, and ta.key. Do not copy the other, server-specific private keys and such to the client(s)! Also, the root CA key (ca.key) should not even be left on the server, but rather moved to some offline storage/box, so that it cannot fall into the wrong hands, e.g. in the case of a server compromise.

I prefer to manually start the client on my laptop when needed, so I use AUTOSTART="none" in /etc/default/openvpn and then start the client via:

  $ openvpn /etc/openvpn/client.conf

That's it. Comments and suggestions for improving the setup and/or the security aspects of it are highly welcome!


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

iptables entry

Just wanted to comment for anybody having problems on this step:
iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE
Your error will probably be something about iptables: No chain/target/match by that name. or iptables: Unknown error 4294967295.

The solution is to simply use this line instead:
iptables -t nat -A POSTROUTING -s -o venet0 -j SNAT --to x.x.x.x
replacing venet0 with your interface and x.x.x.x with your servers external IP address.

Btw, happy holidays :)

Server firewall

Do you plan on posting an example of the firewall you use on the server? I see the laptop/desktop, but not the server one.

fw_laptop on servers

I'm using fw_laptop on various servers too, I just hand-edit it a bit to allow access to services I want to run, and forbid everything else.

Just be careful not to disable ssh on remote servers, otherwise you could have a problem.


By far the best VPN

By far the best VPN, even though it isn't the standard protocol, it makes configuration and maintenance much easier.

Simple and easy deployment.

My first experience with VPN, and I also tried to do PPTP, but I never got all clients connecting (mobile, laptop, linux, windows) ..

client1.crt and client1.key


i am new to this and have not yet setup anything, but should the list of files to copy to the client not also include these two files? You reference them in your client.conf, but don't actually tell your readers to copy them, nor provide a step that would generate them on the client (or have i missed anything?).

Anyway: thanks for this howto! I was a bit afraid to start with OpenVPN but now feel much more confident. I will try to use it on my Android smartphone (hurray for Linux!), hope all goes well...

client keys

Oops, you're right. I forgot to mention that those files need to be copied to the client. Fixed now, thanks!


firewall and ports

You use port 443 in the hope to be reachable from anywhere. You can do better (in particular when port 443 is already used by your webserver) in configuring several ports (in the hope that one of them will work)

  • in your server, do not change the default port (1194), so that correct networks will work with the correct port
  • on your server, use iptables to redirect some incoming connection from several ports to the 1194 port. For myself, I use shorewall that create the iptables rules for me, so I do not know the exact syntax with plain iptables. On my server, port 23 (telnet), 143 (imap) and 465 (ssmtp) are redirected to 1194 [yes, the telnet port is the one that was not used on my server *and* not filtered by my university...]
  • on your client, use several lines "remote HOST PORT": openvpn will try when in turn. On my config, I even add a line "remote localhost 1194" so that I can reach my openvpn server after doing a "ssh -L 1194:localhost:1194 MYSERVER" on networks where only SSH connections are allowed.


Wow, this is far more complicated than I imagined. I've done VPN for windows XP and 7 and they were far less complicated. I'd like to learn this though.

Client key

Hi! Thanks for this clear tuto.

There's a little error nevertheless. The client key should be generated with ./build-key client1 because openvpn may (at least, did in my case) refure it for being a server key and not a client one.



Yes, you're entirely right, of course. Thanks for reporting! It was a copy-paste error on my side. Should be fixed now.

great howto!One

great howto!

One correction
I believe this line:
$ ./build-key-server client1
should read:
$ ./build-key client1



Yup, fixed now. Thanks!

HOWTO: Using OpenVPN on Debian GNU/Linux: creating a client key

"./build-key-server client1" is false (would lead to "error=unsupported certificate purpose" on client connect)

use "./build-key client1" instead.


Thanks, fixed. It was a copy-paste error on my side.


I understand that not everybody uses NetworkManager, but if you are using NetworkManager, you really should rely on the openvpn plugin for the client.
Maybe you could add that?

Really? I've used openvpn

Really? I've used openvpn via startup scripts as well as manually on the command line across many different distributions and never encountered problems with network manager.

If anything, I'd be wary of NM botching things up...

Virtual machine

This is a great howto! However I think there are some problems with a virtual machine on Xen. Port mapping in a Xen-virtual server which is an openvpn server has some problems. I could not connect to such a server.

Xen and others

Yep, it's possible that there are issues with various virtualized environments. Your provider might not have compiled vtun support (or other required stuff) into the kernel, and/or you might need to add /dev/net/tun via mknod yourself and/or the firewall rules need to be adjusted (change eth0 to venet0 or the like), and possibly more. Your provider might also simply fordbid VPN usage on their hardware/server completely (and intentionally), in which case you're out of luck anyway.