OpenVPN on Amazon Linux EC2

OpenVPN on an AWS EC2 T2.Nano Instance

The T2.Nano instance is the smallest instance generally available for AWS EC2. As of 17-June-2017, the Nano includes the following resources:

  • 512mb RAM
  • 1 vcpu (30 credits + 3/hr, up to 72 credits)
  • 1gb network out traffic

Amazon Linux AMI

For those who prefer RHEL/CentOS, these are not available for the T2.Nano instance, rather Amazon Linux AMI is the only RHEL-derrived OS available. Note that Amazon AMI Linux is akin to CentOS 6.x (no systemd). Alternatively, Ubuntu is also available for the Nano.

Amazon Lightsail as an Alternative to EC2 T2.Nano

Amazon Lightsail is a VPS package that provides simplified control panel, and greater resources. For $5 USD/month, the smallest Lightsail instance is essentially a T2.Nano plus Elastic IP address, 20gb EBS storage, 1tb of outbound data, and Route53 DNS interface. Since outbound data can run 0.10/gb (with elastic IP), this is potentially $10/mo in database. The EBS storage is ~$2 USD, Route53 is $0.50 USD, and a nano instance with 1 year contract is ~$3.50 USD. This means for $5 USD/mo, one gets between $6-106 USD in AWS resources. For the $10 USD Lightsail, the value consists of a T2.Micro, and all the rest, which is worth $11-$211 USD in services due to an increase to 30gb EBS and 2TB data transfer out.

Steps to install OpenVPN on AMI - Pre-Installation

These steps are similar for a Nano instance. This should work on a Lightsail instance, though some control panel settings may be in different places.

Adjust PATH

Edit the PATH in ~/.bash_profile

nano /root/.bash_profile

Use the following:

# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin:~/.local/bin:/usr/local/bin

Then load that profile

source ~/.bash_profile

Also add some helpful shortcuts lx and rx

nano /etc/profile

add to end of file:

alias lx='ls -la --color=auto'
alias rx='rm -rf'

User and SSH Cert

  • Download, move, and rename cert
chmod 400 ~/.ssh/key.pem
ssh -v -i ~/.ssh/key.pem ec2-user@host.domain.tld
sudo su
yum -y update
useradd newuser
passwd newuser
usermod -aG wheel newuser
su - newuser
mkdir .ssh
chmod 700 .ssh
exit
cp /home/ec2-user/.ssh/authorized_keys /home/newuser/.ssh/authorized_keys
chown newuser:newuser /home/newuser/.ssh/authorized_keys
nano /etc/sudoers.d/cloud-init

replace ec2-user with newuser

Set the hostname, timezone, nameservers

hostname server.domain.tld

Set the timezone

nano /etc/sysconfig/clock

Change the ZONE line to appropriate continent/city, e.g.,

ZONE="Continent/City"
UTC=false
ARC=false

Create a symbolic link

rm -rf /etc/localtime
ln -sf /usr/share/zoneinfo/Continent/City /etc/localtime

Update nameservers

echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 8.8.4.4" >> /etc/resolv.conf

Edit the network sysconfig

nano /etc/sysconfig/network

Change HOSTNAME to server.domain.tld

Check to ensure the change with the command:

hostname

Don't worry about /etc/hosts for now...

reboot

Update yum, configure EPEL

Note that we want the Amazon EPEL Repository

yum clean all
yum update
yum -y install epel-release
yum -y install yum-utils
yum-config-manager --enable epel

Update AMI without EPEL

This is done by disabling the repositories, which can be enabled later, including:

yum-config-manager --disable epel
yum clean all
yum update
cat /etc/system-release
uname -r

After the update version is confirmed, then re-enable the repositories with:

yum-config-manager --enable epel

Secure SSHD

nano /etc/ssh/sshd_config

make sure of the following:

PasswordAuthentication no
PermitRootLogin no

If you want to do fancy stuff like have an sftp login inside of a web directory, and need different than 700, 750, or 755 rights (say, for example, having the group be apache, and the user be a login) then include:

StrictModes no

Restart sshd

service sshd restart

Install and enable MOSH

yum -y install mosh

Mosh makes connections more resilient, but there is a cost of disabling the ability to scroll up in the console.

firewalld or ufw

This may or may not be desirable, in addition to the AWS firewall configuration. Likely desirable.

Steps to install OpenVPN on AMI - Installation

yum -y install openvpn
yum -y install easy-rsa --enablerepo=epel
mkdir -p /etc/openvpn/easy-rsa/keys
cp -R /usr/share/easy-rsa/2.0/ /etc/openvpn/easy-rsa/

NAT routing using iptables

Put in nat routing, ensure that the network on the masquarade is the same as in /etc/openvpn/server.conf

First edit the iptables-config file

nano /etc/sysconfig/iptables-config

Change most things to yes, with a final config looking like:

IPTABLES_MODULES=""
IPTABLES_MODULES_UNLOAD="yes"
IPTABLES_SAVE_ON_STOP="yes"
IPTABLES_SAVE_ON_RESTART="yes"
IPTABLES_SAVE_COUNTER="no"
IPTABLES_STATUS_NUMERIC="yes"
IPTABLES_STATUS_VERBOSE="yes"
IPTABLES_STATUS_LINENUMBERS="yes"

Now do the rest of the iptables configuration

touch /etc/sysconfig/iptables
chkconfig iptables on
service iptables start
modprobe iptable_nat
echo 1 | tee /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -s 10.9.0.0/24 -j MASQUERADE
service iptables restart

Edit the Easy RSA settings

nano /etc/openvpn/easy-rsa/2.0/vars

Find and modify these values:

# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="CA"
export KEY_PROVINCE=""
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_OU="MyOrganizationalUnit"

Also change

export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`

to

export KEY_CONFIG=/etc/openvpn/easy-rsa/2.0/openssl-1.0.0.cnf

Initialize Easy RSA and create Certs and Keys

cd /etc/openvpn/easy-rsa/2.0
chmod 0755 *
source ./vars
./clean-all
./build-ca

Verify success

ls -la keys

Now build the cert and key

./build-key-server server

Note: leave the challenge password and optional company name blank

Next, Verify success

ls -la keys

Next build a cert and key for each vpn user:

./build-key username

Provide this with a challenge password

Next, build the .pem

./build-dh

Next, build the ta.key

// rather forget about this, just comment out, it is trouble // get this going later

openvpn --genkey --secret /etc/openvpn/easy-rsa/2.0/keys/ta.key

Copy the keys and certs

cd /etc/openvpn/easy-rsa/2.0/keys
cp dh2048.pem ca.crt server.crt server.key username.crt username.key /etc/openvpn

Create OpenVPN Config File

Copy the sample config to start, then set security

cp /usr/share/doc/openvpn-2.4.3/sample/sample-config-files/server.conf /etc/openvpn/server.conf
cd /etc/openvpn
chmod 0644 dh2048.pem ca.crt server.crt server.key server.conf username.crt username.key

Next, edit config file

nano /etc/openvpn/server.conf

Uncomment push "redirect-gateway def1 bypass-dhcp"

Next, add the following settings after dev tun

dev tun
tun-mtu 1500
tun-mtu-extra 32
mssfix 1450
reneg-sec 0

Then uncomment these lines:

; push "dhcp-option DNS 208.67.222.222"
; push "dhcp-option DNS 208.67.220.220"

Also add DNS values as well:

push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

Then uncomment these lines:

user nobody
group nobody

Add compression by uncommenting:

comp-lzo

Change exit notify to zero:

explicit-exit-notify 0

Here is an example of server.conf. Just ensure the masquarade iptables and server configuration are identical.

port 1194
proto udp
dev tun
tun-mtu 1500
tun-mtu-extra 32
mssfix 1450
reneg-sec 0
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh2048.pem

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 8.8.4.4"
duplicate-cn
keepalive 10 120

;cipher BF-CBC        # Blowfish (default)
;cipher AES-128-CBC   # AES
;cipher DES-EDE3-CBC  # Triple-DES

comp-lzo
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 3
explicit-exit-notify 0

Enable Routing

nano /etc/sysctl.conf

Change ip forwarding to 1

net.ipv4.ip_forward = 1

Restart networking services

service network restart

Configure Firewalld if needed

firewall-cmd --add-service openvpn
firewall-cmd --permanent --add-service openvpn

Check to see if configured properly

firewall-cmd --list-services

Enable masquerade and make it permanent

firewall-cmd --add-masquerade
firewall-cmd --permanent --add-masquerade

Check to see if enabled

firewall-cmd --query-masquerade

Enable and start the OpenVPN service

chkconfig openvpn on
service openvpn restart

Install and Configure OpenVPN Client

For OSX, there is Tunnelblick, which sucks, and Viscosity which sucks less (but costs $9).

An example Viscosity config file looks like:

#viscosity startonopen false
#viscosity protocol openvpn
#viscosity dns off
#viscosity usepeerdns false
#viscosity autoreconnect true
#viscosity name host.domain.tld
#viscosity dhcp true
remote 12.34.56.78 1194 udp
nobind
dev tun
redirect-gateway def1
tun-mtu 1500
pull
tls-client
ca ca.crt
cert cert.crt
key key.key
push "redirect-gateway def1"
comp-lzo
mssfix 1450
resolv-retry infinite
tun-mtu-extra 32
reneg-sec 0

For installing an OVPN command line client on Linux, simply taking the config.conf file, along with ca.crt, cert.crt, and key.key files.

Installation on a Debian system looks like:

sudo apt-get update
apt-get install openvpn

Then scp the four files into the home directory and run:

openvpn config.conf

After this works, then set up OVPN as a service with scripts for automation.

Resources Consulted

No comments yet.

Leave a Reply