Ubuntu 上安装配置 OpenVPN



OpenVPN

OpenVPN is an TLS/SSL VPN. it utilizes certificates in order to encrypt traffic between the server and clients.

Ubuntu 16.04 Server 上安装 OpenVPN

Install OpenVPN

1
2
sudo apt-get update
sudo apt-get install openvpn easy-rsa

easy-rsa package 用来配置 an internal CA (certificate authority).

Set Up the CA Directory

In order to issue trusted certificates, we will need to set up our own simple certificate authority (CA).

copy the easy-rsa template directory into our home directory with the make-cadir command:

1
2
make-cadir ~/openvpn-ca
cd ~/openvpn-ca

Configure the CA Variables

1
nano ~/openvpn-ca/vars

Edit the values in red to whatever you’d prefer, but do not leave them blank:

  • ~/openvpn-ca/vars
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    . . .
    
    export KEY_COUNTRY="US"
    export KEY_PROVINCE="NY"
    export KEY_CITY="New York City"
    export KEY_ORG="DigitalOcean"
    export KEY_EMAIL="admin@example.com"
    export KEY_OU="Community"
    
    . . .
    

KEY_NAME的值改成自定义的名字,这里改成“server”:

  • ~/openvpn-ca/vars
    1
    export KEY_NAME="server"
    

Build the Certificate Authority

1
2
3
4
5
6
7
8
cd ~/openvpn-ca
source vars

# Make sure we're operating in a clean environment by typing:
./clean-all

# Now, we can build our root CA by typing:
./build-ca

执行 build-ca 之后会开始创建 the root certificate authority key and certificate. 之前已经配置好了 vars 文件,这里只要一路 ENTER确认就好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Generating a 2048 bit RSA private key
..........................................................................................+++
...............................+++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [NY]:
Locality Name (eg, city) [New York City]:
Organization Name (eg, company) [DigitalOcean]:
Organizational Unit Name (eg, section) [Community]:
Common Name (eg, your name or your server's hostname) [DigitalOcean CA]:
Name [server]:
Email Address [admin@email.com]:

Create the Server Certificate, Key, and Encryption Files

generating the OpenVPN server certificate and key pair. 一路回车或者输’y’确认。

1
./build-key-server server

Note: If you choose a name other than server here, you will have to adjust some of the instructions below. For instance, when copying the generated files to the /etc/openvpn directroy, you will have to substitute the correct names. You will also have to modify the /etc/openvpn/server.conf file later to point to the correct .crt and .key files.

1
2
3
4
5
6
7
8
9
. . .

Certificate is to be certified until May  1 17:51:16 2026 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

generate a strong Diffie-Hellman keys to use during key exchange by typing:
命令执行要花个几分钟。

1
./build-dh

generate an HMAC signature to strengthen the server’s TLS integrity verification capabilities:

1
openvpn --genkey --secret keys/ta.key

Generate a Client Certificate and Key Pair

if you have more than one client, you can repeat this process as many times as you’d like. Pass in a unique value to the script for each client.

We will use client1 as the value for our first certificate/key pair for this guide.

To produce credentials without a password, to aid in automated connections, use the build-key command like this:

1
2
3
cd ~/openvpn-ca
source vars
./build-key client1

If instead, you wish to create a password-protected set of credentials, use the build-key-pass command

1
2
3
cd ~/openvpn-ca
source vars
./build-key-pass client1

Configure the OpenVPN Service

Copy the Files to the OpenVPN Directory /etc/openvpn

刚刚的证书和密钥文件都放在 ~/openvpn-ca/keys

move our CA cert, our server cert and key, the HMAC signature, and the Diffie-Hellman file:

1
2
cd ~/openvpn-ca/keys
sudo cp ca.crt server.crt server.key ta.key dh2048.pem /etc/openvpn

copy and unzip a sample OpenVPN configuration file into configuration directory so that we can use it as a basis for our setup:

1
gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz | sudo tee /etc/openvpn/server.conf

Adjust the OpenVPN Configuration

编辑 /etc/openvpn/server.conf

First, find the HMAC section by looking for the tls-auth directive. Remove the “;” to uncomment the tls-auth line. Below this, add the key-direction parameter set to “0”:

1
2
tls-auth ta.key 0 # This file is secret
key-direction 0

Next, find the section on cryptographic ciphers by looking for the commented out cipher lines.

The AES-128-CBC cipher offers a good level of encryption and is well supported. Remove the “;” to uncomment the cipher AES-128-CBC line:

1
cipher AES-128-CBC

Below this, add an auth line to select the HMAC message digest algorithm. For this, SHA256 is a good choice:

1
auth SHA256

Finally, find the user and group settings and remove the “;” at the beginning of to uncomment those lines:

1
2
user nobody
group nogroup

(Optional) Push DNS Changes to Redirect All Traffic Through the VPN

If you wish to use the VPN to route all of your traffic, you will likely want to push the DNS settings to the client computers.

编辑 /etc/openvpn/server.conf

Find the redirect-gateway section and remove the semicolon “;” from the beginning of the redirect-gateway line to uncomment it:

1
push "redirect-gateway def1 bypass-dhcp"

Just below this, find the dhcp-option section. Again, remove the “;” from in front of both of the lines to uncomment them:

1
2
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"

This should assist clients in reconfiguring their DNS settings to use the VPN tunnel for as the default gateway.

(Optional) Adjust the Port and Protocol

By default, the OpenVPN server uses port 1194 and the UDP protocol to accept client connections.

编辑 /etc/openvpn/server.conf

1
2
# Optional!
port 443

Often if the protocol will be restricted to that port as well. If so, change proto from UDP to TCP:

1
2
# Optional!
proto tcp

(Optional) Point to Non-Default Credentials

If you selected a different name during the ./build-key-server command earlier, modify the cert and key lines that you see to point to the appropriate .crt and .key files. If you used the default server, this should already be set correctly:

1
2
cert server.crt
key server.key

Adjust the Server Networking Configuration

Allow IP Forwarding

First, we need to allow the server to forward traffic. This is fairly essential to the functionality we want our VPN server to provide.

修改文件 /etc/sysctl.conf

look for the line that sets net.ipv4.ip_forward. Remove the “#” character from the beginning of the line to uncomment that setting:

1
net.ipv4.ip_forward=1

To read the file and adjust the values for the current session, type:

1
sudo sysctl -p

Adjust the UFW Rules to Masquerade Client Connections

Before we open the firewall configuration file to add masquerading, we need to find the public network interface of our machine. To do this, type:

1
ip route | grep default

Your public interface should follow the word “dev”. For example, this result shows the interface named wlp11s0, which is highlighted below:

1
2
Output
default via 203.0.113.1 dev wlp11s0  proto static  metric 600

When you have the interface associated with your default route, open the /etc/ufw/before.rules file to add the relevant configuration:

编辑 /etc/ufw/before.rules

This file handles configuration that should be put into place before the conventional UFW rules are loaded. Towards the top of the file, add the highlighted lines below. This will set the default policy for the POSTROUTING chain in the nat table and masquerade any traffic coming from the VPN:

Note: Remember to replace wlp11s0 in the -A POSTROUTING line below with the interface you found in the above command.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-before-input
#   ufw-before-output
#   ufw-before-forward
#

# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0] 
# Allow traffic from OpenVPN client to wlp11s0 (change to the interface you discovered!)
-A POSTROUTING -s 10.8.0.0/8 -o wlp11s0 -j MASQUERADE
COMMIT
# END OPENVPN RULES

# Don't delete these required lines, otherwise there will be errors
*filter

We need to tell UFW to allow forwarded packets by default as well. To do this, we will open the /etc/default/ufw file:

find the DEFAULT_FORWARD_POLICY directive. We will change the value from DROP to ACCEPT:

1
DEFAULT_FORWARD_POLICY="ACCEPT"

Open the OpenVPN Port and Enable the Changes

If you did not change the port and protocol in the /etc/openvpn/server.conf file, you will need to open up UDP traffic to port 1194. If you modified the port and/or protocol, substitute the values you selected here.

1
2
sudo ufw allow 1194/udp
sudo ufw allow OpenSSH

Now, we can disable and re-enable UFW to load the changes from all of the files we’ve modified:

1
2
sudo ufw disable
sudo ufw enable

Start and Enable the OpenVPN Service

We need to start the OpenVPN server by specifying our configuration file name as an instance variable after the systemd unit file name. Our configuration file for our server is called /etc/openvpn/server.conf, so we will add @server to end of our unit file when calling it:

1
sudo systemctl start openvpn@server

Double-check that the service has started successfully by typing:

1
sudo systemctl status openvpn@server

If everything went well, your output should look something that looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Output
● openvpn@server.service - OpenVPN connection to server
   Loaded: loaded (/lib/systemd/system/openvpn@.service; disabled; vendor preset: enabled)
   Active: active (running) since Tue 2016-05-03 15:30:05 EDT; 47s ago
     Docs: man:openvpn(8)
           https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
           https://community.openvpn.net/openvpn/wiki/HOWTO
  Process: 5852 ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/%i.conf --writepid /run/openvpn/%i.pid (code=exited, sta
 Main PID: 5856 (openvpn)
    Tasks: 1 (limit: 512)
   CGroup: /system.slice/system-openvpn.slice/openvpn@server.service
           └─5856 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/server.conf --writepid /run/openvpn/server.pid

May 03 15:30:05 openvpn2 ovpn-server[5856]: /sbin/ip addr add dev tun0 local 10.8.0.1 peer 10.8.0.2
May 03 15:30:05 openvpn2 ovpn-server[5856]: /sbin/ip route add 10.8.0.0/24 via 10.8.0.2
May 03 15:30:05 openvpn2 ovpn-server[5856]: GID set to nogroup
May 03 15:30:05 openvpn2 ovpn-server[5856]: UID set to nobody
May 03 15:30:05 openvpn2 ovpn-server[5856]: UDPv4 link local (bound): [undef]
May 03 15:30:05 openvpn2 ovpn-server[5856]: UDPv4 link remote: [undef]
May 03 15:30:05 openvpn2 ovpn-server[5856]: MULTI: multi_init called, r=256 v=256
May 03 15:30:05 openvpn2 ovpn-server[5856]: IFCONFIG POOL: base=10.8.0.4 size=62, ipv6=0
May 03 15:30:05 openvpn2 ovpn-server[5856]: IFCONFIG POOL LIST
May 03 15:30:05 openvpn2 ovpn-server[5856]: Initialization Sequence Completed

You can also check that the OpenVPN tun0 interface is available by typing:

1
ip addr show tun0

You should see a configured interface:

1
2
3
4
5
Output
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 100
    link/none 
    inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
       valid_lft forever preferred_lft forever

If everything went well, enable the service so that it starts automatically at boot:

1
sudo systemctl enable openvpn@server

Create Client Configuration Infrastructure

Creating the Client Config Directory Structure

1
2
mkdir -p ~/client-configs/files
chmod 700 ~/client-configs/files

Creating a Base Configuration

1
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf

编辑 ~/client-configs/base.conf

  • First, locate the remote directive.
    • This points the client to our OpenVPN server address. This should be the public IP address of your OpenVPN server.
    • If you changed the port that the OpenVPN server is listening on, change 1194 to the port you selected:
    1
    2
    3
    4
    5
    6
    . . .
    # The hostname/IP and port of the server.
    # You can have multiple remote entries
    # to load balance between the servers.
    remote server_IP_address 1194
    . . .
    
    • Be sure that the protocol matches the value you are using in the server configuration:
      1
      proto udp
      
  • Next, uncomment the user and group directives by removing the “;”:
    1
    2
    3
    # Downgrade privileges after initialization (non-Windows only)
    user nobody
    group nogroup
    

    Find the directives that set the ca, cert, and key. Comment out these directives since we will be adding the certs and keys within the file itself:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # SSL/TLS parms.
    # See the server config file for more
    # description.  It's best to use
    # a separate .crt/.key file pair
    # for each client.  A single ca
    # file can be used for all clients.
    
    # COMMENT OUT FOLLOWING 3 LINES
    #ca ca.crt
    #cert client.crt
    #key client.key
    

    Mirror the cipher and auth settings that we set in the /etc/openvpn/server.conf file:

    1
    2
    cipher AES-128-CBC
    auth SHA256
    
  • Next, add the key-direction directive somewhere in the file. This must be set to “1” to work with the server:
    1
    key-direction 1
    
  • Finally, add a few commented out lines. We want to include these with every config, but should only enable them for Linux clients that ship with a /etc/openvpn/update-resolv-conf file. This script uses the resolvconf utility to update DNS information for Linux clients.

    1
    2
    3
    # script-security 2
    # up /etc/openvpn/update-resolv-conf
    # down /etc/openvpn/update-resolv-conf
    

Creating a Configuration Generation Script

Next, we will create a simple script to compile our base configuration with the relevant certificate, key, and encryption files. This will place the generated configuration in the ~/client-configs/files directory.

创建并修改 ~/client-configs/make_config.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

# First argument: Client identifier

KEY_DIR=~/openvpn-ca/keys
OUTPUT_DIR=~/client-configs/files
BASE_CONFIG=~/client-configs/base.conf

cat ${BASE_CONFIG} \
    <(echo -e '<ca>') \
    ${KEY_DIR}/ca.crt \
    <(echo -e '</ca>\n<cert>') \
    ${KEY_DIR}/${1}.crt \
    <(echo -e '</cert>\n<key>') \
    ${KEY_DIR}/${1}.key \
    <(echo -e '</key>\n<tls-auth>') \
    ${KEY_DIR}/ta.key \
    <(echo -e '</tls-auth>') \
    > ${OUTPUT_DIR}/${1}.ovpn
1
chmod 700 ~/client-configs/make_config.sh

Generate Client Configurations

1
2
cd ~/client-configs
./make_config.sh client1

If everything went well, we should have a client1.ovpn file in our ~/client-configs/files directory:

1
ls ~/client-configs/files

Install the Client Configuration

Windows

下载 OpenVPN 的客户端: https://openvpn.net/index.php/open-source/downloads.html

安装好 OpenVPN 后将 .ovpn file 拷贝到 C:\Program Files\OpenVPN\config

客户端必须右键菜单中选择“以管理员身份运行”。

Each time you launch the OpenVPN GUI, Windows will ask if you want to allow the program to make changes to your computer. Click Yes.

右键点击屏幕右下角OpenVPN任务栏图标,Select client1 at the top of the menu (that’s our client1.ovpn profile) and choose Connect.

Disconnect from the VPN the same way: Go into the system tray applet, right-click the OpenVPN applet icon, select the client profile and click Disconnect.