Accessing AWS VPC instances using OpenVPN-NL

Pre-requisites

  1. Amazon VPC CIDR (the /16 one) – 172.31.0.0/16 is our example

  2. Ubuntu 14.04 instance launched in a public subnet with EIP attached

  3. EIP of the above machine – 54.63.44.120 is our example
  4. SSH connection to the Ubuntu instance

Setting up the server

We are going to use a distribution of OpenVPN called OpenVPN-NL (http://openvpn.fox-it.com/) because it has more secure defaults than the standard OpenVPN installation that is distributed with Ubuntu. Also, OpenVPN-NL makes use of mbed-TLS (previously PolarSSL) instead of OpenSSL because of its compactness and ease of auditability (is that even a word?). Run all following commands as the root user:

Tin-can security
Tin-can security (c) Colin Dunn – Flickr


Step 1: Download and add the signature key for OpenVPN-NL

wget -qO - https://openvpn.fox-it.com/repos/fox-crypto-gpg.asc | apt-key add -

Step 2: Add OpenVPN-NL repository to the package sources list

echo deb https://openvpn.fox-it.com/repos/deb trusty main | tee -a /etc/apt/sources.list.d/openvpn-nl.list

Step 3: Install OpenVPN-NL and easy-rsa

apt-get update && apt-get -y install openvpn-nl easy-rsa

The easy-rsa package downloads utility scripts that can be used to generate certificates for the server and clients.

Step 4: Switch to the new openvpn-nl directory and create diffie-hellman parameters

pushd /etc/openvpn-nl
openssl dhparam -out dh2048.pem 2048

This step takes a while. Once it’s done, you should see a file named dh2048.pem

Step 5: Prepare to generate CA certificate and key

We could use the easy route and use the easy-rsa utility to generate our CA certificate and key. Copy easy-rsa to /etc/openvpn-nl directory. Create a directory to save the keys

cp -r /usr/share/easy-rsa /etc/openvpn-nl
mkdir /etc/openvpn-nl/easy-rsa/keys
pushd /etc/openvpn-nl/easy-rsa

Step 6: Set variables

Set the variables for the certificate in the vars file. The KEY_NAME value is important.

export KEY_COUNTRY="US"
export KEY_PROVINCE="KA"
export KEY_CITY="Metropolis"
export KEY_ORG="Krypton"
export KEY_EMAIL="kal-el@fortofsolitu.de"
export KEY_OU="SuperHeroClub"
export KEY_NAME="SecureServer"

Step 7: Export the variables

source ./vars
./clean-all  #not optional

This step is NOT optional unless you know how to manually create an ‘index.txt‘ and a ‘serial‘ file under keys directory. Basically, index.txt is an empty file that contains certificate information and serial is a file with, well, a serial number.

Step 8: Generate the CA certificate

From within the easy-rsa directory type the following to build the CA file:

./build-ca

There will be prompts asking you to confirm various parameters you specified in the vars file. Just press Enter for all of them unless you want to change a particular value. This should have created a certificate ( ca.crt ) and a key file (ca.key).

Step 9: Generate the server certificate

Now that we have a CA certificate, let’s generate a server certificate for OpenVPN-NL.

Note: The trust between OpenVPN server and clients has to be bidirectional. i.e. The server needs to trust the client certificates and the clients need to trust the server certificate we are about to generate

Run the following command to generate the server certificate while within the easy-rsa directory:

./build-key-server SecureServer

Remember to replace ‘SecureServer’ with whatever you entered as the value to KEY_NAME in the vars file. Do not add a password or a company name, just ‘Enter Key your way through those questions.

This step should give us SecureServer.crt and SecureServer.key, the certificate and the key file respectively. You should also see now that the value of ‘serial’ has incremented by 1 and the index.txt file has information about the server certificate.

Copy the CA certificate, Server certificate and server certificate key to the primary OpenVPN directory.

cp /etc/openvpn-nl/easy-rsa/keys/{ca.crt,SecureServer.crt,SecureServer.key} /etc/openvpn-nl/.

Step 10: Generate a HMAC firewall

Generate a firewall that helps prevent DoS or UDP flooding attacks. This helps prevent some common attacks by authenticating the TLS connections.

openvpn-nl --genkey --secret ta.key

Step 11: Edit OpenVPN server configuration to incorporate the changes

Copy a sample server configuration file to the current directory

gunzip -c /usr/share/doc/openvpn-nl/examples/sample-config-files/server.conf.gz > /etc/openvpn-nl/server.conf

In your /etc/openvpn-nl/ directory, you should now have the following files:

  • server.conf – The server configuration file
  • dh2048.pem  – The diffie-hellman parameter file
  • ca.crt      – The CA certificate
  • SecureServer.crt – The server certificate
  • SecureServer.key – The server certificate key file
  • ta.key      – The HMAC firewall file

We are now ready to configure the server. Edit the /etc/openvpn-nl/server.conf file to make changes to the parameters like so:

# Certificate settings
ca ca.crt
cert SecureServer.crt
key SecureServer.key
dh dh2048.pem

# AWS VPC NETWORK / MASK
push "route 172.31.0.0 255.255.0.0"

# HMAC authentication
tls-auth ta.key 0

# Explicit cipher specification
cipher AES-256-CBC

# Privilege de-escalation
user nobody
group nogroup

# Logging
log openvpn.log
# ..

Un-comment the lines as necessary by removing the preceding semicolon. Replace the SecureServer.crt with the name of the files you have for server certificate. Leave the rest of the parameters as they were.

In the example, above I’m assuming my VPC’s CIDR is 172.31.0.0/16. You can be picky about the subnets you want to access by modifying the push route parameter. For example, if you have two private subnets 172.31.16.0/20 and 172.31.32.0/20, you can replace the push line with:

push "route 172.31.16.0 255.255.255.240"
push "route 172.31.32.0 255.255.255.240"

Step 12: Enabling IP packet forwarding

This step allows the Linux kernel to forward network packets from the Clients on to the destination.

Edit the /etc/sysctl.conf file and un-comment the following line

net.ipv4.ip_forward=1

Load the new settings

sysctl -p

Step 13: Restart the OpenVPN-NL service

service openvpn-nl restart

Generate client certificates

Now that the server is all setup, let’s generate the client certificates. This can be done using the easy-rsa utility. In our setup, let’s assume there are two road warriors (clients on the move using laptops) that need to connect to the VPC. Let’s call them Lex and Diana; We need to generate certificates for both Lex and Diana. Let’s say Lex has a laptop and an iPhone and Diana has a laptop and an Android phone. We need to generate certificates for each device.

(c) jasleen_kaur - Flickr
Lots ‘f keys

From within the easy-rsa directory

./build-key lexLaptop

Leave the password fields blank and press ‘enter’ all the way through the prompts. Now we are left with the following files (under the keys directory)

lexLaptop.crt
lexLaptop.key
lexLaptop.csr

Ignore the csr file. It’s an intermediate step (certificate signing request) and we won’t need it. Our certificate has also been signed using the CA certificate. Let’s repeat the steps for Lex’s iPhone, Diana’s Laptop and her Android phone.

./build-key lexiPhone
./build-key dianaLaptop
./build-key dianaAndroid

This should leave us with a total of four sets of certificates and key files; one each for each of Lex and Diana’s devices.

Editing the client configuration template

Copy the Client example file from the documentation directory

cp /usr/share/doc/openvpn-nl/examples/sample-config-files/client.conf /etc/openvpn-nl/easy-rsa/keys/

Edit the client.conf so that it looks like the following. Replace the values as necessary

remote <EIP_OF_OPENVPN_SERVER> 1194
ca ca.crt
cert <USER_CERT_FILE>
key <USER_KEY_FILE>
auth SHA256
cipher AES-256-CBC 

Replace the <EIP_OF_OPENVPN_SERVER> with the, um.. EIP of your OpenVPN-NL server (duh). Replace the <USER_CERT_FILE> with the .crt file corresponding to the user and <USER_KEY_FILE> with the .key file corresponding to the user. Therefore, there have to be one client configuration file for each device for each user. In our case, we have

lexiphone.conf
lexlaptop.conf
dianaandroid.conf
dianalaptop.conf

Contents of lexiphone.conf

remote 54.63.44.120 1194
ca ca.crt
cert lexiPhone.crt
key lexiPhone.key
auth SHA256
cipher AES-256-CBC

Contents of lexlaptop.conf

remote 54.63.44.120 1194ca ca.crt
cert lexLaptop.crt
key lexiLaptop.key
auth SHA256
cipher AES-256-CBC

Contents of dianaAndroid.conf

remote 54.63.44.120 1194
ca ca.crt
cert dianaAndroid.crt
key dianaAndroid.key
auth SHA256
cipher AES-256-CBC

Contents of dianaLaptop.conf

remote 54.63.44.120 1194
ca ca.crt
cert dianaLaptop.crt
key dianaLaptop.key
auth SHA256
cipher AES-256-CBC

Packaging the client files

On a standard Linux client, we can securely copy over the certificates and files and then start OpenVPN client. Do this from within the /etc/openvpn-nl directory

tar -cf lexlaptop.tgz ca.crt lexLaptop.crt lexLaptop.key ta.crt lexlaptop.conf

This compressed package can be directly uncompressed into the /etc/openvpn directory of the client and once the openvpn service is started, the connection is established

pushd /etc/openvpn-nl
tar -xf lexlaptop.tgz
service openvpn-nl start

Alternatively, we can create a .ovpn file that has all the information embedded in it. A ovpn file consists of the client configuration and the certificate and authentication information appended in a quasi-XML style. Here is some sample content of a .ovpn file. Let’s call this dianaAndroid.ovpn

client
dev tun
proto udp
remote 54.169.178.87 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca [inline]
cert [inline]
key [inline]
remote-cert-tls server
tls-auth [inline] 1
auth SHA256
cipher AES-256-CBC
comp-lzo
verb 3
<ca>
-----BEGIN CERTIFICATE-----
MIIE2TCCA8GgAwIBAgIJAOkzxcy8FBPmMA0GCSqGSIb3DQEBCwUAMIGjMQswCQYD
VQQGEwJJTjELMAkGA1UECBMCVE4xEDAOBgNVBAcTB0NoZW5uYWkxEDAOBgNVBAoT
[..tons of text..]
Ui5QLft5pC+NlN8AmFoE7MAlrVPnOpHaD4rzcE+Jk/XDhfBea1uOA+frubKCQGvs
K+/mmukY4BhZKyuW4+YfeR+HgPeJc/hhpPT4U8xmE8V52e2dSilctsgqGjse
-----END CERTIFICATE-----
</ca>
<cert>
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, ST=KA, L=Metropolis, O=Krypton, OU=SuperHeroClub, CN=Krypton CA/name=server/emailAddress=kal_el@fortofsolitu.de
        Validity
            Not Before: Feb 16 02:06:22 2016 GMT 
            Not After : Feb 13 02:06:22 2026 GMT 
        Subject: C=US, ST=KA, L=Metropolis, O=Krypton, OU=SuperHeroClub, CN=diana/name=server/emailAddress=kal_el@fortofsolitu.de
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:b8:09:61:59:70:09:28:d2:3a:60:ad:ef:0c:99:
                    ee:fc:e3:c3:8c:76:4f:aa:d7:3a:ab:70:01:70:43:
                    fc:23:37:ee:f2:a6:2e:6b:b5:b3:6b:9d:f8:9e:f2:
                    2b:c7:65:fb:92:6e:27:46:40:4b:38:9f:c2:50:75:
                    6f:ad:0b:4e:a4:e1:a6:1d:b3:78:ce:bb:30:ff:7b:
                    bb:19:f4:9a:36:20:6f:b9:b4:c0:1e:c5:ba:6e:3c:
                    3b:05:09:68:97:eb:d2:ea:12:8d:9b:1c:9f:b7:1e:
                    da:88:c6:d4:7f:dd:71:c2:6f:16:97:d9:f1:4e:01:
                    eb:78:d9:03:57:d9:9f:a4:68:df:be:36:c7:89:7f:
                    d7:7c:b9:d9:18:bf:18:36:0e:99:f8:a4:a8:da:a9:
                    99:04:4f:96:3a:7e:e2:1a:f6:5e:f0:c4:99:23:fa:
                    35:3c:24:b6:97:a9:1d:e7:22:f4:ca:fd:f4:b5:76:
                    27:cf:ae:7f:4a:7a:9e:cb:0f:11:67:73:95:b7:ce:
                    23:6a:4c:eb:61:d1:6c:39:bb:e9:58:2d:82:02:14:
                    71:44:0a:b4:54:56:0a:9b:58:32:04:c7:94:95:90:
                    0f:d6:7a:df:39:9b:91:0f:d8:98:74:63:c7:11:80:
                    56:23:ae:30:38:d4:61:2e:9d:2e:75:a6:66:4d:6b:
                    bc:a3
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                Easy-RSA Generated Certificate
            X509v3 Subject Key Identifier: 
                A6:DA:39:3E:56:00:AE:D3:67:47:F3:C1:8E:A7:94:07:E8:7D:28:6F
            X509v3 Authority Key Identifier:
                keyid:B6:7B:64:97:5D:E4:85:2A:6E:94:14:33:79:45:5C:5F:2D:16:81:3B
                DirName:/C=US/ST=KA/L=Metropolis/O=Krypton/OU=SuperHeroClub/CN=Krypton CA/name=server/emailAddress=kal_el@fortofsolitu.de
                serial:E9:33:C5:CC:BC:14:13:E6

           X509v3 Extended Key Usage:
               TLS Web Client Authentication
           X509v3 Key Usage:
               Digital Signature
           X509v3 Subject Alternative Name:
               DNS:diana
     Signature Algorithm: sha256WithRSAEncryption
         a5:6e:2f:ea:40:59:d4:08:0c:d6:e3:c0:31:a3:53:a6:aa:e3:
         03:40:6d:79:5c:0e:ff:5b:32:8b:7e:0b:9f:a3:07:71:61:8f:
         8b:96:88:e6:68:9c:38:70:af:16:b2:92:34:4d:4d:d3:f4:bb:
         c3:e2:ab:b8:e1:01:78:6d:32:90:b0:f1:94:57:ed:5c:64:00:
         cf:cf:a3:48:e8:1f:ad:82:32:01:96:91:ea:51:63:64:a5:d0:
         56:b1:18:45:75:e5:3a:87:6c:4b:ae:fe:4b:89:f0:88:92:53:
         54:ba:2c:44:af:d8:37:06:32:7e:6c:da:ce:70:8c:3a:a2:62:
         bf:5a:ea:9f:ed:36:dd:fa:8f:18:15:d0:e4:01:a0:47:fb:e0:
         11:2a:53:ba:e1:42:10:36:68:13:52:ce:65:7e:bc:7d:8f:11:
         72:51:48:ec:e0:f2:ed:01:25:d5:85:90:7e:d8:21:05:4d:2d:
         37:3e:c2:b4:fe:7e:2f:5c:a4:fe:b3:ef:bb:25:c5:91:f7:34:
         a9:e7:46:31:e4:a3:54:06:48:07:66:9e:a5:db:06:54:93:52:
         f6:6d:e1:64:aa:60:3d:38:fe:35:43:d6:e2:7d:46:4f:31:01:
         29:ed:d7:3e:19:6c:b2:c1:4a:a9:91:ea:9c:ab:96:46:cf:23:
         98:91:6e:e2
-----BEGIN CERTIFICATE-----
MIIFMDCCBBigAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCSU4x
CzAJBgNVBAgTAlROMRAwDgYDVQQHEwdDaGVubmFpMRAwDgYDVQQKEwdLcnlwdG9u
[..tons of text..]
hZB+2CEFTS03PsK0/n4vXKT+s++7JcWR9zSp50Yx5KNUBkgHZp6l2wZUk1L2beFk
qmA9OP41Q9bifUZPMQEp7dc+GWyywUqpkeqcq5ZGzyOYkW7i
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4CWFZcAko0jpg
re8Mme7848OMdk+q1zqrcAFwQ/wjN+7ypi5rtbNrnfie8ivHZfuSbidGQEs4n8JQ
[..tons of text..]
CrpE/OFX0qWv0OlIwOuk54NZ2SOz2Lg1S9WE25yQ/2Hq+P8VorU2n5lObNvgDDBA
Ggg8vzWrCS3QUD8mSn8oQ1S7AsrHi7VuGlL8JluCETSy2QP06WBw3/9xY5sL1fWY
b8MaBpCJ+XFZrqWHTxGwH2RTaw==
-----END PRIVATE KEY-----
</key>
<tls-auth>
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
7c1149d26035a1da9161553a4a7c7ec3
2e0706370d1ef87b82718ba350a47278
[..snip..]
b1dcfa460b5e5e5d13c182a5c1640fbb
11e28b44af3cac731600f271abe8d90d
-----END OpenVPN Static key V1-----
</tls-auth>


Mao Tsé-Tung 毛澤東 - Flickr
(c) Mao Tsé-Tung 毛澤東 – Flickr

Finally, create an IP tables rule to NAT the traffic to the subnet behind the server

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
This will send traffic out to the VPC instances. You should now be able to ping the private IP addresses of instances behind the OpenVPN server. Only instances residing on the subnets you added routes to will be accessible.

Preparing the instance for connections

  1. Disable source/destination check for the instances
    1. Right click on the instance –> Networking –> Change source/dest. check –> Click on the blue ‘Disable’ button
  2. Open UDP port 1194 in the security groups to world.

Connecting the clients

Linux:

  1. Install OpenVPN or OpenVPN-NL
  2. Extract the client configuration files, certificates and keys into the /etc/openvpn directory
  3. Start the OpenVPN service

Debian / Ubuntu

service openvpn start

Arch Linux

# replace 'client' with the name of your  
# client.conf file minus the '.conf' part.
systemctl start openvpn@client

Apple Macbook:

Use Tunnelblick (https://tunnelblick.net/); Import the ovpn file into the app.

  1. Install and launch Tunnelblick
  2. Select the “I have configuration files” button; then select “OpenVPN configuratin(s)” button.
  3. In the configurations directory that opens, copy the .ovpn file
  4. You should be able to launch it from the context menu from the Tunnelblick taskbar applet.

FreeBSD

  • Load the tap interface kernel module
kldload if_tap
  • Add the following line to /boot/loader.conf to persist the tap interface
if_tap_load="YES"
  • Ensure that OpenVPN is enabled in /etc/rc.conf
openvpn_enable="YES"
openvpn_if="tap"
  • Copy the client configuration file, keys and certificates to /usr/local/etc/openvpn
  • Start OpenVPN
/usr/local/etc/rc.d/openvpn start

Happy VPNing.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s