Last Updated: 01 Apr 2018

   |   

Author: dordal

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
server-tech:centos:setting-up-openvpn-server-on-centos [Apr 1, 2018 05:15 AM]
dordal
server-tech:centos:setting-up-openvpn-server-on-centos [Apr 1, 2018 05:35 AM] (current)
dordal [Configure IPTables]
Line 1: Line 1:
 += Setting up OpenVPN Server on CentOS 7 using EasyRSA 3=
 +
 +If you travel frequently, it can be handy to use a VPN service with an endpoint back home, particularly if you don't want somebody spying on you in an Internet cafe or airport. Properly setup, a VPN will encrypt all traffic originating from your machine, send it out over the Internet to the VPN server, and then it will go from //there// to the wider Internet. ​
 +
 +There are a number of [[https://​www.pcmag.com/​article2/​0,​2817,​2403388,​00.asp|commercially available VPN services]], but if you're technically inclined, you might want to setup your own. This document tells you how, using [[https://​www.centos.org/​|CentOS 7]], [[https://​openvpn.net/​|OpenVPN]],​ [[https://​github.com/​OpenVPN/​easy-rsa|EasyRSA 3]], and [[https://​www.sparklabs.com/​viscosity/​|Viscosity]],​ an excellent VPN client for Mac & Windows.
 +
 +First, big thanks to [[https://​www.digitalocean.com/​community/​tutorials/​how-to-setup-and-configure-an-openvpn-server-on-centos-7|Digital Ocean'​s VPN setup guide]], as well as the [[https://​eligible.com/​community/​setting-up-openvpn-on-centos-7-using-digitalocean/​|guide and config files provided by Tyler Duzan]]. ​
 +
 +== Basic CentOS Setup ==
 +
 +First, you'll need a CentOS 7 server. You can use one from almost anywhere -- a machine with Digital Ocean, AWS or Azure, or one in your friend'​s apartment. Assuming you're starting from scratch, you'll need to get the software updated and the EPEL repo installed.
 +
 +<​code>​
 +# sudo yum update -y
 +# sudo yum install epel-release -y
 +# sudo yum update -y
 +</​code>​
 +
 +Then you'll want to install openvpn, easyrsa, iptables and (recommended) a few network troubleshooting tools.
 +
 +<​code>​
 +# sudo yum install -y openvpn easy-rsa iptables iptables-services wget yum-cron net-tools bind-utils nc mtr
 +</​code>​
 +
 +== Setting up OpenVPN ==
 +
 +Now, you'll want to configure the OpenVPN server. To do this, copy the following file to ''/​etc/​openvpn/​server.conf''​. Thanks to the [[https://​gist.github.com/​Tristor/​b939b830c6426926696a49d4789031e8|hardened config from Tristor]], which I used as a starting point.
 +
 +<​code>​
 +# Secure OpenVPN Server Config
 +
 +# Basic Connection Config
 +dev tun
 +proto udp
 +port 1194
 +keepalive 10 120
 +max-clients 5
 +
 +# Certs
 +ca ca.crt
 +cert server.crt
 +key server.key
 +dh dh.pem
 +tls-auth ta.key 0
 +
 +# Ciphers and Hardening
 +reneg-sec 0
 +remote-cert-tls client
 +crl-verify crl.pem
 +tls-version-min 1.2
 +cipher AES-256-CBC
 +auth SHA512
 +tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:​TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:​TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:​TLS-DHE-RSA-WITH-AES-128-CBC-SHA256
 +
 +# Drop Privs
 +user nobody
 +group nobody
 +
 +# IP pool
 +server 172.31.100.0 255.255.255.0
 +topology subnet
 +ifconfig-pool-persist ipp.txt
 +client-config-dir ccd
 +
 +# Misc
 +persist-key
 +persist-tun
 +comp-lzo
 +
 +# DHCP Push options force all traffic through VPN and sets DNS servers
 +push "​redirect-gateway def1 bypass-dhcp"​
 +push "​dhcp-option DNS 8.8.8.8"​
 +push "​dhcp-option DNS 8.8.4.4"​
 +
 +# Logging
 +log-append /​var/​log/​openvpn.log
 +verb 3
 +</​code>​
 +
 +=== Make the Client Config Directory ===
 +
 +This directory can hold client-specific configs, if desired:
 +
 +<​code>​
 +# mkdir /​etc/​openvpn/​ccd
 +</​code>​
 +
 +== Generating the Keys and Certificates ==
 +
 +OpenVPN provides a tool called EasyRSA, which lets you generate the keys you need. You installed it above, so time to get going:
 +
 +First, Init PKI:
 +<​code>​
 +# cd ~
 +# /​usr/​share/​easy-rsa/​3/​easyrsa init-pki
 +</​code>​
 +
 +Now, build the certificate authority. You'll be asked for a common name; I use '​VPN'​. If you want to be extra secure, you can set this to be the FQDN of your host, and then turn on an option to make sure that the CN of the certificate matches the FQDN of the server, but I prefer not to do this, so my certificates are portable:
 +
 +<​code>​
 +# /​usr/​share/​easy-rsa/​3/​easyrsa build-ca nopass
 +</​code>​
 +
 +Generate the Diffie-Helllman parameters:
 +
 +<​code>​
 +# /​usr/​share/​easy-rsa/​3/​easyrsa gen-dh
 +</​code>​
 +
 +Generate the server keys (**vpn-server** should be the name of your server):
 +
 +<​code>​
 +# /​usr/​share/​easy-rsa/​3/​easyrsa build-server-full vpn-server nopass
 +</​code>​
 +
 +Generate one or more client keys (**vpn-client-01** should be the name of your client machine):
 +
 +<​code>​
 +# /​usr/​share/​easy-rsa/​3/​easyrsa build-client-full vpn-client-01 nopass
 +</​code>​
 +
 +Generate the certificate revocation list:
 +
 +<​code>​
 +# /​usr/​share/​easy-rsa/​3/​easyrsa gen-crl
 +</​code>​
 +
 +Generate a pre-shared key. This helps harden your VPN; for details see the details about ''​--tls-auth''​ on [[https://​community.openvpn.net/​openvpn/​wiki/​Hardening|the OpenVPN Hardening page]].
 +
 +<​code>​
 +# openvpn --genkey --secret pki/ta.key
 +</​code>​
 +
 +=== Copying the Keys ===
 +
 +Now you need to copy your keys to the OpenVPN config directory. Everything should be in ''​~/​pki'':​
 +
 +<​code>​
 +# sudo cp pki/ca.crt /​etc/​openvpn/​ca.crt
 +# sudo cp pki/dh.pem /​etc/​openvpn/​dh.pem
 +# sudo cp pki/​issued/​vpn-server.crt /​etc/​openvpn/​server.crt
 +# sudo cp pki/​private/​vpn-server.key /​etc/​openvpn/​server.key
 +# sudo cp pki/ta.key /​etc/​openvpn/​ta.key
 +# sudo cp pki/crl.pem /​etc/​openvpn/​crl.pem
 +</​code>​
 +
 +== Setup OpenVPN to Start Automatically ==
 +
 +Next up, you'll want to startup OpenVPN. To do so:
 +
 +<​code>​
 +# sudo systemctl -f enable openvpn@server.service
 +# sudo systemctl start openvpn@server.service
 +</​code>​
 +
 +If it doesn'​t start, check the log for clues:
 +
 +<​code>​
 +# sudo tail -f /​var/​log/​openvpn.log
 +</​code>​
 +
 +Optionally, you may want to skip ahead to **Setting up the Client**, so you can test things out. At this point you should be able to connect to your VPN server, and ping it from your client ( ''​172.31.100.1''​ if you've followed the steps above ). You won't be able to pass live traffic through the VPN until you complete the routing steps below, but this can be a good point to make sure that everything is working.
 +
 +== Setting up Routing w/ iptables ==
 +
 +Since your server will be a VPN server, you probably want to block most inbound connections,​ except over SSH and the OpenVPN port. You'll also want to allow packet forwarding from VPN clients to the wider internet, or else your client could only talk to your VPN server itself. We do that with iptables.
 +
 +=== Enable IPv4 Forwarding ===
 +First, edit ''/​etc/​sysctl.conf''​ and add the following lines:
 +
 +<​code>​
 +# Packet forwarding
 +net.ipv4.ip_forward = 1
 +</​code>​
 +
 +Save the file, and then run ''​sysctl -p''​ to load the changes. You can verify forwarding is enabled by doing ''​more /​proc/​sys/​net/​ipv4/​ip_forward''​ which should return 1 if its enabled.
 +
 +=== Configure IPTables ===
 +
 +Now, we run a series of commands to configure ''​iptables''​. Thanks again to [[https://​gist.github.com/​Tristor|Tristor]] for his work here, which forms the basis of this. Note that **you MUST do this as part of a bash script which gets run all at once**, if you type these commands line by line you'll cut yourself off from SSH access before you can enter the commands to open it up. Also, if you're not using ''​172.31.100.0/​24''​ for your VPN subnet, you'll need to change that below. ​
 +
 +<​code>​
 +#!/bin/bash
 +
 +# REMEMBER: Run this as a single bash script or you'll lock yourself out of your machine.
 +
 +# Flushing all rules
 +iptables -F FORWARD
 +iptables -F INPUT
 +iptables -F OUTPUT
 +iptables -X
 +# Setting default filter policy
 +iptables -P INPUT DROP
 +iptables -P OUTPUT DROP
 +iptables -P FORWARD DROP
 +# Allow unlimited traffic on loopback
 +iptables -A INPUT -i lo -j ACCEPT
 +iptables -A OUTPUT -o lo -j ACCEPT
 +# Accept outbound on the primary interface
 +iptables -I OUTPUT -o eth0 -d 0.0.0.0/0 -j ACCEPT
 +# Accept inbound TCP packets
 +iptables -I INPUT -i eth0 -m state --state ESTABLISHED,​RELATED -j ACCEPT
 +# Allow incoming SSH
 +iptables -A INPUT -p tcp --dport 22 -m state --state NEW -s 0.0.0.0/0 -j ACCEPT
 +# Allow incoming OpenVPN
 +iptables -A INPUT -p udp --dport 1194 -m state --state NEW -s 0.0.0.0/0 -j ACCEPT
 +# Enable NAT for the VPN
 +iptables -t nat -A POSTROUTING -s 172.31.100.0/​24 -o eth0 -j MASQUERADE
 +# Allow TUN interface connections to OpenVPN server
 +iptables -A INPUT -i tun0 -j ACCEPT
 +# Allow TUN interface connections to be forwarded through other interfaces
 +iptables -A FORWARD -i tun0 -j ACCEPT
 +iptables -A OUTPUT -o tun0 -j ACCEPT
 +iptables -A FORWARD -i tun0 -o eth0 -m state --state RELATED,​ESTABLISHED -j ACCEPT
 +iptables -A FORWARD -i eth0 -o tun+ -m state --state RELATED,​ESTABLISHED -j ACCEPT
 +# Allow outbound access to all networks on the Internet from the VPN
 +iptables -A FORWARD -i tun0 -s 172.31.100.0/​24 -d 0.0.0.0/0 -j ACCEPT
 +# Block client-to-client routing on the VPN
 +iptables -A FORWARD -i tun0 -s 172.31.100.0/​24 -d 172.31.100.0/​24 -j DROP
 +</​code>​
 +
 +Finally, enable that config as a service.
 +
 +<​code>​
 +sudo systemctl enable iptables
 +sudo systemctl start iptables
 +sudo service iptables save
 +</​code>​
 +
 +== Setting up the Client ==
 +
 +Getting the VPN server running is only half the battle. Actually, it's about 90% of the battle, but you still have to do the client side work. Assuming you're using Mac or Windows, you pretty much want to use [[https://​www.sparklabs.com/​viscosity/​|Viscosity]]. It's an excellent third party VPN client, and my favorite. It's $9, but pay it. It's worth it.
 +
 +First, on the server, make a directory and copy the client config and client certificates into it:
 +
 +<​code>​
 +# cd ~
 +# mkdir vpn-client-01-config
 +# cp pki/ca.crt vpn-client-01-config/​ca.crt
 +# cp pki/​issued/​vpn-client-01.crt vpn-client-01-config/​client.crt
 +# cp pki/​private/​vpn-client-01.key vpn-client-01-config/​client.key
 +# cp pki/ta.key vpn-client-01-config/​ta.key
 +</​code>​
 +
 +Now, create the config file, at ''​vpn-client-01-config/​client.ovpn''​. **Be sure to change the remote line to point to your vpn server!**
 +
 +<​code>​
 +# Secure OpenVPN Client Config
 +
 +#viscosity dns full
 +#viscosity usepeerdns true
 +#viscosity dhcp true
 +tls-client
 +pull
 +client
 +dev tun
 +proto udp
 +remote 123.123.123.123 1194
 +redirect-gateway def1
 +nobind
 +persist-key
 +persist-tun
 +comp-lzo
 +verb 3
 +ca ca.crt
 +cert client.crt
 +key client.key
 +tls-auth ta.key 1
 +remote-cert-tls server
 +ns-cert-type server
 +key-direction 1
 +cipher AES-256-CBC
 +tls-version-min 1.2
 +auth SHA512
 +tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:​TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:​TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:​TLS-DHE-RSA-WITH-AES-128-CBC-SHA256
 +</​code>​
 +
 +Now tar up the config, and download it to your Mac or Windows machine:
 +
 +<​code>​
 +# tar cvfz vpn-client-01-config.tgz vpn-client-01-config
 +</​code>​
 +
 +Then, simply import the ''​client.opvn''​ into Viscosity, and you'll be all set.
 +