-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Or how to secure your communications using an X509 PKI

Working in Luxembourg, I sometimes need to have a French IP because of some stupid rules in webservices preventing me to access them while I’m at work. Also, It is sometimes necessary for debugging purposes at work, to be able to connect to a destination from a source IP address outside of our AS. Therefore, by its simplicity of setup, I decided to install the open source version of OpenVPN. Here’s how I proceeded.

Prerequisites

For the server part, I’m using a brand new Centos6.2 installation with EPEL repository configured for this demonstration, where I have root credentials (needed). As I’m a mac user, I’ll just show you how to configure one of the most used OpenVPN clients, tunnelblick. That’s basically everything.

Installing EPEL is pretty straight away :

rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
This HOWTO assumes that readers possess a prior understanding of basic networking concepts such as IP addresses, DNS names, netmasks, subnets, IP routing, routers, network interfaces, LANs, gateways, and firewall rules.

A word on routing against bridging

With this howto, you will get a routed VPN, if you want to have the other flavor of VPN, then this is not the right place to look at.

As I’m not authorized by the company Owning OpenVPN to copy any part of their website, and if want to know more about the limitations and differences between a routed or bridged VPN, there is their foreword, linking to their FAQ and to more details on Ethernet Bridging. Anyway, as they say, routing is probably a better choice for most people.

Detail of the setup

What you will get with this setup is a way to connect with your mac (in fact we’ll generate 3 client certificates) to the VPN server, get an IP in a private subnet range, public dns servers and set all the traffic of the client to go through the VPN server.

Installing the software

On Centos, with EPEL repository configured, only one package with its dependencies is needed, and should be the same on most of the distributions around. If you want the source code … it’s available on OpenVPN’s download page.

yum install openvpn
=>	...
	Running Transaction
  	Installing : pkcs11-helper-1.07-5.el6.x86_64	1/3 
  	Installing : lzo-2.03-3.1.el6.x86_64	2/3 
  	Installing : openvpn-2.2.1-1.el6.x86_64	3/3 

	Installed:
  	openvpn.x86_64 0:2.2.1-1.el6

	Dependency Installed:
  	lzo.x86_64 0:2.03-3.1.el6	pkcs11-helper.x86_64 0:1.07-5.el6

	Complete!

Client and server key generation

Generating keys can really be a hassle, but thanks to OpenSSL, there should be on your distribution tools provided to help us dealing with the process of generating certificates.

# Change directory to OpenVPN's configuration directory
cd /etc/openvpn/
# Copy the easy-rsa directory in the current directory
cp -R /usr/share/openvpn/easy-rsa/ .
# Change to the freshly copied directory
cd easy-rsa/2.0/
# To use the generation tool, you need to have in this very current directory an OpenSSL configuration file (openssl.cnf) that matches the currently installed version of OpenSSL.
# So, determine the currently installed OpenSSL version :
rpm -qa | grep openssl
=>	openssl-1.0.0-20.el6.x86_64
# Now, copy the provided configuration file to the expected filename
cp openssl-1.0.0.cnf openssl.cnf

You need now to customize the default values in order to match your needs. Edit the values in the vars file, here as exemple mine :

export EASY_RSA="`pwd`"
export OPENSSL="openssl"
export PKCS11TOOL="pkcs11-tool"
export GREP="grep"
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
export KEY_DIR="$EASY_RSA/keys"
export PKCS11_MODULE_PATH="dummy"
export PKCS11_PIN="dummy"
export KEY_SIZE=2048	#defaults to 1024
export CA_EXPIRE=3650	#going on for 10 years
export KEY_EXPIRE=3650	#here too
export KEY_COUNTRY="FR"
export KEY_PROVINCE="FR"
export KEY_CITY="Amneville"
export KEY_ORG="dotnul"
export KEY_EMAIL="benj@dotnul.com"
export KEY_CN=changeme
export KEY_NAME=changeme
export KEY_OU=changeme
export PKCS11_MODULE_PATH=changeme
export PKCS11_PIN=1234

Now, start generating the certificates.

source ./vars
# NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/2.0/keys
./clean-all
# Create the CA certificates
./build-ca
# Generation of the server certificate
./build-key-server server
# The following command should be repeated the same number of times than you want of clients
./build-key client1
# Now build Diffie–Hellman keys
./build-dh 

Server configuration

Now copy the OpenVPN’s sample configuration file provided on CentOS to the appropriate directory.

cp /usr/share/doc/openvpn-2.2.1/sample-config-files/server.conf /etc/openvpn/

Edit the server.conf configuration file to reflect your needs and apply the key/certs configuration we just generated before.

# As I don't run https on this server, I'll just make OpenVPN to bind on TCP/443 as this is generally opened everywhere.
port 443
proto tcp
# Create a routed IP tunnel
dev tun
# CA, Server key/cert and Diffie–Hellman keys generated previously
ca easy-rsa/2.0/keys/ca.crt
cert easy-rsa/2.0/keys/server.crt
key easy-rsa/2.0/keys/server.key  # This file should be kept secret
dh easy-rsa/2.0/keys/dh2048.pem
# Provide a VPN subnet in a private subnet
server 172.30.90.0 255.255.255.192
# Make client <-> vip address associations
ifconfig-pool-persist ipp.txt
# Route all client traffic through the VPN server
push "redirect-gateway def1"
# Push DNS servers
push "dhcp-option DNS 80.92.67.144"
push "dhcp-option DNS 80.92.65.30"
# Uncomment this if you want that all your clients can talk with each other within the VPN subnet 
client-to-client
# Ping every 10s, remote peer is down if no response within 120s
keepalive 10 120
# Enable compression of the traffic
comp-lzo
# Run the server as unpriviledged user
user nobody
group nobody
# After priv downgrade, don't access key and tun
persist-key
persist-tun
# Some log file and verbosity
status openvpn-status.log
verb 3
Customizing firewall and sysctl

Make sure that your firewall permits connections to the previously defined port, otherwise edit /etc/sysconfig/iptables and restart iptables.

iptables-save | grep 443
=>	-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT

Make sure that your firewall masquerades VPN ip’s, otherwise edit /etc/sysconfig/iptables and restart iptables.

iptables-save | grep MASQUERADE
=>	-A POSTROUTING -s 172.30.90.0/26 -o eth0 -j MASQUERADE

Finally, make sure that packets are able to go through the VPN server, otherwise edit /etc/sysctl.conf and reload with sysctl -p.

sysctl net.ipv4.ip_forward
=> 	net.ipv4.ip_forward = 1

Start OpenVPN with service openvpn start and check that the magic happened :

# Do we have the tunnel iface present ?
ip addr list tun0 
=> 	4: tun0:  mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100
	link/[65534] 
	inet 172.30.90.1 peer 172.30.90.2/32 scope global tun0	
# And the routing table is indeed changed
route -n
=>	Kernel IP routing table
	Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
	ww.xx.yyy.z     0.0.0.0         255.255.255.0   UH    0      0        0 eth0
	172.30.90.2     0.0.0.0         255.255.255.255 UH    0      0        0 tun0
	172.30.90.0     172.30.90.2     255.255.255.192 UG    0      0        0 tun0
	0.0.0.0         ww.xx.yyy.z     0.0.0.0         UG    0      0        0 eth0

Client configuration : tunnelblick

As I’m a mac user, I needed some working and easy VPN client, I choosed tunnelblick because it’s small, convenient and can also connect to my office VPN server. So, go ahead, download it, install it (As you’re reading an article on OpenVPN, I assume that you know how to install a software on a Mac.).

Create a folder on your mac, let’s say dotnul. In this folder, put the ca.crt, client1.key and client1.crt inside and create the following client.conf configuration file containing the following :

# We are a client
client
# Using a routed tunnel
dev tun
# Connecting to your server
proto tcp
remote yourserver.domain.tld 443
# If just above you specified a hostname, uncomment the following line
# resolv-retry infinite
# Don't bind to a specific local port
nobind
# Make things persistant
persist-key
persist-tun
# The usual stuff
ca ca.crt
cert client1.crt
key client1.key
# Verify server certificate by checking that the certicate has the nsCertType
ns-cert-type server
# Compress
comp-lzo
# Be kinda verbose
verb 3

You should now have a folder looking like this :

  • Folder Content

Now, rename this folder by appending a .tlbk at its name (You should now have a dotnul.tlbk folder). Double click then on the folder that is now a valid tunnelblick configuration file. This will prompt you to know at which system level you want this tunnel to be available. It’s your choice. Your password will be asked because of the creation of interfaces.

Start a traceroute to some internet reachable host, and if the first hop you reach is the first of the VPN subnet, Congrats, you’re able to connect to internet through your vpn !

traceroute -nn 8.8.8.8
=>	traceroute to 8.8.8.8 (8.8.8.8), 64 hops max, 52 byte packets
 	1  172.30.90.1  17.999 ms  18.746 ms  22.426 ms

Client configuration on Windows7

There is a slight problem with Windows7 and the usage of the OpenVPN client as it requires a some elevated privileges, and this can’t be achieved with a standard user account. I’ll provide anyway the configuration method, but better ask somebody competent in the Microsoft operating systems field to solve this issue, because this goes fat beyond the scope of this tutorial.

Download the Windows installer on the windows page and install the software. (Screenshots are attached here, but not much details will be provided on how to click)

  • Setup1
  • Setup2
  • Setup3
  • Setup4
  • Setup5

Now, create the same files than created the step before, and put them on the folder c:\Program Files\OpenVpn\config (or anywhere you installed OpenVPN). You can now lauch the provided GUI … and connection will be established (see next step to know how to add username/password authentication mechanism).

  • Putting files
  • Connecting

Asking for an username and password

I was recently pointed to the fact that if I got my laptop stolen, you would be able to connect to the server without any problem. I then decided to add username/password authentication to the connection process.

Of course, I would be possible for me to directly revoking the used certificate on the server to prevent the usage of the stolen certificate, but I would then need to go fast and not forget it.

On the server side, create a new user with a password, and add the following line to the server.conf file :

plugin /usr/lib64/openvpn/plugin/lib/openvpn-auth-pam.so login

Restart OpenVPN service. Then, on the client side, add the following line to the client.conf configuration file:

auth-user-pass
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJW5eRKAAoJEBeKS2x6xuR7hWIP/RJosxF1HF3xBzGKizXJKxHm
ARqEeZv2tW6NxGRtgM2PRhMnDCTCn6UIvNRS40mGdOgKoAImG6W2iIFCF+t/TAt4
bFcWxXLN1ZW4g+HhtOBjnXedgy+KxGVkyJV9KuggOgFZDQFVFqxYSzZUWC3BAiJS
CBlNAjllxUgB7D7G+Td5PR8pqyWQ/yd45Yv3JLxa61IZFtwVKHbAqq03/9PZVyJG
ekOORdAknCGgguifIqdwEpH85ZLc/gCz02NOSaXlBKFX0xe8tP3cjQ9lO+ymYBXO
fjFwn+cebSgcQtAd+Z5Yq7rzNVNIqRPgC6ca4m7319pPnP5L2MdU/2M7MYfh8Wvg
8JKm5p5xkcxj7J++kGauo6+sL8TqDjY+AbJkygLK6bk7WAwWnd8JqbQ1+VmO4YoN
w7hvwJjmm1lP6yRhPnd/HpEqd17ObXb1xvR3G2oiUB5IkVgxo9J4GzFgkPZfWD9j
Hb9TPVB4QO954pA29w5dhNzGW/eVxUFHNo3Q9IHpXtpDURDeS28e0GJ/VVMgQqDo
NxpgdgGbLI0RE/X5+JzT0cnBHmpfXw9zChmYpbuMSbtc3WgnUIRpayE6zHjGfgIT
pJQ72n8s0E3vlEg0lHEJvKP70HJAVWHX9WdUyghrTJkffPnZW+VuhN0l5sJGhc1e
/Fv7Y/C1vQ5ex4HvWpRw
=kOmD
-----END PGP SIGNATURE-----

Hint: To validate signature, please view page source and copy html code between BEGIN PGP Signed message and END PGP Signature anchors.

Created the 2012-01-08

Share this


Article content

Resources

10 last blog posts

Article history :

  • 2012-01-28 15:54:23 +0100: New Added username and password authentication on top of everything in server and client configuration. Added also OpenSSL client configuration for Windows.

Related to this article

blog comments powered by Disqus