Setting Up Openvpn Server

The objective of this project was to install a vpn server on one of the boxes in the cloud (initially asafoetida, then moved to tarragon), in order to provide a VPN server service for a friend who was traveling. My friend uses the name Darrell for his client, so in what follows the vpn is called by this name.

Create a Certificate Authority

A lot of the instructions, even from openvpn site, say to use the “easyrsa” package to generate the certificates for openvpn. This package seems to be put out by the openvpn boys, or at least with their cooperation. But I didn’t do that. I created a ca with raw openssl.

I built the ca on my laptop  in /etc/ssl/mycerts/ca. The root ca is in that directory, but a subdirectory called intermediate has an intermediate ca, and that is where the actual signing is done. I probably won’t leave it on the laptop. Not sure yet what I will do with the ca.

Generate the private keys and certificates

Once the ca is in place, we generate the certificates for server and client as follows:

First I generated 2048 private keys, one for server, one for client, with:
openssl genrsa -aes256 -out client.key 2048
openssl genrsa -aes256 -out server.key 2048

and generated the csr (one for each), using those keys with:
openssl req -new -sha256 -key client.key -out client.csr
openssl req -new -sha256 -key server.key -out server.csr

There are directories within /etc/ssl/mycerts/ca/intermediate, certs/ for the certs, and csr/ for the requests:

Now use the csr to generate the certs (one for each):
cd /etc/ssl/mycerts/ca/intermediate
openssl ca -config openssl.cnf -days 365 -notext -md sha256 -extensions server_cert -in csr/server.csr -out certs/darrell_server.cert.pem


openssl ca -config openssl.cnf -days 365 -notext -md sha256 -extensions usr_cert -in csr/client.csr -out certs/darrell_client.cert.pem

I also created a diffie-hellman parameter for the link:
openssl dhparam -out dhparams.pem 4096

And I generated a “ta key”, which is apparently a shared key used to resist certain attacks:
openvpn --genkey --secret /etc/openvpn/ta.key

Also on both server and client sides, I had to build the config files for openvpn. They are called, respectively, darrell.server.conf and darrell.vpn.conf. Maybe I should have called the latter darrell.client.conf. The client side is shown later on. Here is the server side configuration file:


[root@tarragon server]# cat darrell.server.conf
port 1194
proto udp
dev tun
ca /etc/openvpn/server/ca-chain.cert.pem
cert /etc/openvpn/server/certs/darrell_server.cert.pem
key /etc/openvpn/server/private/server.key
dh /etc/openvpn/server/dhparams.pem
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 1.1.1.1"
keepalive 10 120
tls-auth /etc/openvpn/server/ta.key 0
cipher AES-256-CBC
compress lz4-v2
push "compress lz4-v2"
user nobody
group nobody
persist-key
persist-tun
status /etc/openvpn/server/darrell-status.log
verb 3
explicit-exit-notify 1
tls-auth ta.key 0
auth SHA512

Ok, so on the server (asafoetida initially, later moved to tarragon), in /etc/openvpn/server, I have the following files:
ca-chain.cert.pem
certs/darrell_server.cert.pem
dhparams.pem
private/server.key
darrell.server.conf
ta.key

The file ca-chain.cert.pem has in it both the certificate for the intermediate ca and the certificate for the root ca which signed the intermediate. Both of these are needed on the server side, for sending to the client. Later, when we build the client side, it really only needs the root ca cert.

Initially, I started the openvpn server manually, with:
cd /etc/openvpn/server
openvpn darrell.server.conf

But see below discussion of automatic startup.

Client Side

On the client side (on lemongrass), in /etc/openvpn/client, I have these files:
client.key
darrell_client.cert.pem
darrell.vpn.conf

And on lemongrass also, I (initially) started the client manually with:
cd /etc/openvpn/client
openvpn darrell.vpn.conf

Here is the entire client config file /etc/openvpn/client/darrell.vpn.conf:
root@lemongrass:#cd /etc/openvpn/client
root@lemongrass:#cat darrell.vpn.conf
client
dev tun
proto udp
remote 54.203.69.119 1194
resolv-retry infinite
remote-random
nobind
persist-key
persist-tun
ping 15
ping-restart 0
ping-timer-rem
reneg-sec 0
explicit-exit-notify 3
verb 3
pull
fast-io
cipher AES-256-CBC
auth SHA512
cert darrell_client.cert.pem
key client.key
remote-cert-tls server
<ca>
-----BEGIN CERTIFICATE-----
MIIF5DCCA8ygAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYcxCzAJBgNVBAYTAlVT
MREwDwYDVQQIDAhDb2xvcmFkbzETMBEGA1UEBwwKQnJvb21maWVsZDETMBEGA1UE
...

—–END CERTIFICATE—–
—–BEGIN CERTIFICATE—–
MIIF9jCCA96gAwIBAgIJAMrX0lux8xc+MA0GCSqGSIb3DQEBCwUAMIGHMQswCQYD
VQQGEwJVUzERMA8GA1UECAwIQ29sb3JhZG8xEzARBgNVBAcMCkJyb29tZmllbGQx

—–END CERTIFICATE—–
</ca>
key-direction 1
<tls-auth>
#
# 2048 bit OpenVPN static key
#
—–BEGIN OpenVPN Static key V1—–
fb167340f0c74c249b435dcddc75e7e7
adffe06ea124488cf244724749306f6f

—–END OpenVPN Static key V1—–
</tls-auth>

Firewall adjustments

The server is an amazon ec2 instance, and all ec2 instances have a firewall, called a “security group” provided by amazon. I used the same “security group” rules at the amazon level for asafoetida as for tarragon (http+mail+ssh, etc), but with an additional rule to admit udp 1194.

On asafoetida proper, there was not an additional iptables firewall – it had a default Accept-Accept-Accept filter table and no nat table. I added a couple of forward rules to filter, to accept forwarding of tun+ to eth0 and eth0 to tun+. Also I added a nat table postrouting rule to masquerade all output through eth0 to the vpn address.

On tarragon, the default redhat firewall sends forward traffic through the input chain (?), and I only had to accept udp 1194, and accept tun+., and add the nat table postrouting, so in /etc/sysconfig/iptables I added:
-A RH-Firewall-1-INPUT -i tun+ -j ACCEPT
-A RH-Firewall-1-INPUT -i eth0 -m state --state NEW -p udp --dport 1194 -j ACCEPT

I had not previously had a nat table in the tarragon firewall, so I had to put one in:
*nat
:PREROUTING ACCEPT [4:240]
:INPUT ACCEPT [4:240]
:OUTPUT ACCEPT [2:135]
:POSTROUTING ACCEPT [2:135]
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

The link gets made, and the routing table on both client and server seem to be adjusted properly, but traffic doesn’t flow out of the server. The problem turned out to be that I had failed to turn on ip forwarding on the box.
echo “1” > /proc/sys/net/ipv4/ip_forward

And to make that last, I put it in /etc/sysctl
net.sys.ipv4.ip_forward = 1

Starting Automatically

There are systemd instance scripts for starting a client (openvpn-client@) and for starting a server (openvpn-server@). So if you put a conf file in the /etc/openvpn/client directory named fred.conf, you can then do:
systemctl enable openvpn-client@fred

And similarly, for an openvpn server config named darrell.conf in /etc/openvpn/server:
systemctl enable openvpn-server@darrell

Revoking Certificates

This is just a parenthetical note, to record one additional bit of experience, to help me remember. I had to reissue the certs because I failed the first time to specify the “extensions” part. However, you cannot reissue a cert with the same common_name (i.e. you can’t generate a new cert using the same csr) until you remove the old cert, which is a better practice anyway.
openssl ca -config openssl.cnf -revoke certs/darrell_server.cert.pem

Then I reissued the 2 certs, with the names server2 and client2. But that isn’t relavent to these instructions, and so in the instructions above I continued to reference the certs as darrell_server.cert.pem and darrell_client.cert.pem, even though on the box the names really had the “2” appended.