OpenVpn搭建

一、openvpn原理

openvpn通过使用公开密钥(非对称密钥,加密解密使用不同的key,一个称为Publice key,另外一个是Private key)对数据进行加密的。这种方式称为TLS加密。

openvpn使用TLS加密的工作过程是,首先VPN Sevrver端和VPN Client端要有相同的CA证书,双方通过交换证书验证双方的合法性,用于决定是否建立VPN连接。然后使用对方的CA证书,把自己目前使用的数据加密方法加密后发送给对方,由于使用的是对方CA证书加密,所以只有对方CA证书对应的Private key才能解密该数据,这样就保证了此密钥的安全性,并且此密钥是定期改变的,对于窃听者来说,可能还没有破解出此密钥,VPN通信双方可能就已经更换密钥了。

参考:

https://www.jianshu.com/p/17a56994b74f

二、安装openvpn和easy-rsa

1.yum安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1、安装openvpn
yum -y install openvpn libssl-dev openssl easy-rsa
rpm -ql easy-rsa
rpm -ql openvpn
# copy配置文件
cp /usr/share/doc/openvpn-2.4.9/sample/sample-config-files/server.conf /etc/openvpn/
cp -r /usr/share/easy-rsa/ /etc/openvpn/
cp /usr/share/doc/easy-rsa-3.0.7/vars.example /etc/openvpn/easy-rsa/3.0.7/vars
/etc/openvpn/
├── easy-rsa
│   ├── 3 -> 3.0.7
│   ├── 3.0 -> 3.0.7
│   └── 3.0.7
│   ├── easyrsa
│   ├── openssl-easyrsa.cnf
│   ├── vars
│   └── x509-types
│   ├── ca
│   ├── client
│   ├── code-signing
│   ├── COMMON
│   ├── email
│   ├── kdc
│   ├── server
│   └── serverClient
└── server.conf
2、创建PKI和CA签发机构
1
2
3
4
5
6
7
8
cd /etc/openvpn/easy-rsa/3.0.7/
./easyrsa init-pki
[root@vpn 3.0.7]# ll pki/
total 24
-rw------- 1 root root 4616 Sep 21 11:32 openssl-easyrsa.cnf
drwx------ 2 root root 4096 Sep 21 11:32 private #私钥目录
drwx------ 2 root root 4096 Sep 21 11:32 reqs
-rw------- 1 root root 4700 Sep 21 11:32 safessl-easyrsa.cnf
3、创建CA机构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@vpn 3.0.7]# ./easyrsa build-ca nopass

Note: using Easy-RSA configuration from: /etc/openvpn/easy-rsa/3.0.7/vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Generating RSA private key, 2048 bit long modulus
..........................................+++
........................................................................................................................................+++
e is 65537 (0x10001)
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.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]: #直接回车

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/etc/openvpn/easy-rsa/3.0.7/pki/ca.crt

[root@vpn 3.0.7]# ll pki/ca.crt
# 验证CA的私钥
ll /etc/openvpn/easy-rsa/3.0.7/pki/private/ca.key
4、创建服务端证书(私钥)
1
2
3
4
5
6
7
8
9
[root@vpn 3.0.7]# ./easyrsa gen-req server nopass #直接回车
# 验证CA证书
[root@vpn 3.0.7]# ll ./pki/private/
total 8
-rw------- 1 root root 1679 Sep 21 11:34 ca.key
-rw------- 1 root root 1704 Sep 21 11:37 server.key # serverd的私钥,保密
[root@vpn 3.0.7]# ll ./pki/reqs/
total 4
-rw------- 1 root root 887 Sep 21 11:37 server.req # 用于签发证书
5、签发服务端证书

生成服务端crt公钥

1
2
[root@vpn 3.0.7]# ./easyrsa sign server server
# 输入yes

验证服务端公钥

1
2
3
[root@vpn 3.0.7]# ll /etc/openvpn/easy-rsa/3.0.7/pki/issued/server.crt
# 验证生成的秘钥文件
-rw------- 1 root root 4547 Sep 21 11:40 /etc/openvpn/easy-rsa/3.0.7/pki/issued/server.crt
6、创建Diffie-Hellman

密钥交换方法,由惠特菲尔德·迪菲(Bailey Whitfield Diffie)、马丁·赫尔曼(Martin Edward Hellman)于1976年发表。它是一种安全协议,让双方在完全没有对方任何预先信息的条件下通过不安全信道建立起一个密钥,这个密钥一般作为“对称加密”的密钥而被双方在后续数据传输中使用。DH数学原理是base离散对数问题。做类似事情的还有非对称加密类算法,如:RSA。其应用非常广泛,在SSH、VPN、Https…都有应用,勘称现代密码基石。

1
2
3
[root@vpn 3.0.7]# ./easyrsa gen-dh
[root@vpn 3.0.7]# ll /etc/openvpn/easy-rsa/3.0.7/pki/dh.pem
-rw------- 1 root root 424 Sep 21 11:44 /etc/openvpn/easy-rsa/3.0.7/pki/dh.pem
7、创建客户端证书
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[root@vpn 3.0.7]# mkdir /etc/openvpn/client
[root@vpn 3.0.7]# cp -r /usr/share/easy-rsa/ /etc/openvpn/client/easy-rsa
[root@vpn 3.0.7]# ll /etc/openvpn/client
total 4
drwxr-xr-x 3 root root 4096 Sep 21 11:49 easy-rsa
[root@vpn 3.0.7]# cp /usr/share/doc/easy-rsa-3.0.7/vars.example /etc/openvpn/client/easy-rsa/vars
# 生成PKI目录
[root@vpn 3.0.7]# cd /etc/openvpn/client/easy-rsa/3.0.7/
[root@vpn 3.0.7]# ./easyrsa init-pki

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/client/easy-rsa/3.0.7/pki
# 验证PKI目录
[root@vpn 3.0.7]# ll ./pki/
total 24
-rw------- 1 root root 4616 Sep 21 11:50 openssl-easyrsa.cnf
drwx------ 2 root root 4096 Sep 21 11:50 private
drwx------ 2 root root 4096 Sep 21 11:50 reqs
-rw------- 1 root root 4770 Sep 21 11:50 safessl-easyrsa.cnf
[root@vpn 3.0.7]# ll ./pki/private/
total 0
# 生成客户端证书
[root@vpn 3.0.7]# pwd
/etc/openvpn/client/easy-rsa/3.0.7
[root@vpn 3.0.7]# ./easyrsa gen-req quhui nopass #用户名quhui,不设置密码
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Generating a 2048 bit RSA private key
................................................................+++
....................................................................................+++
writing new private key to '/etc/openvpn/client/easy-rsa/3.0.7/pki/easy-rsa-26662.y3oE1K/tmp.Od73e6'
-----
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.
-----
Common Name (eg: your user, host, or server name) [quhui]:

Keypair and certificate request completed. Your files are:
req: /etc/openvpn/client/easy-rsa/3.0.7/pki/reqs/quhui.req #用户的申请
key: /etc/openvpn/client/easy-rsa/3.0.7/pki/private/quhui.key #用户的私钥
[root@vpn 3.0.7]# tree /etc/openvpn/client/easy-rsa/3.0.7/pki/
/etc/openvpn/client/easy-rsa/3.0.7/pki/
├── openssl-easyrsa.cnf
├── private
│   └── quhui.key
├── reqs
│   └── quhui.req
└── safessl-easyrsa.cnf

2 directories, 4 files
8、签发客户端证书
1
2
3
4
5
6
7
8
9
10
11
12
13
# 注意切换目录
[root@vpn 3.0.7]# pwd
/etc/openvpn/easy-rsa/3.0.7
# 导入req文件
[root@vpn 3.0.7]# ./easyrsa import-req /etc/openvpn/client/easy-rsa/3.0.7/pki/reqs/quhui.req quhui

Note: using Easy-RSA configuration from: /etc/openvpn/easy-rsa/3.0.7/vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017

The request has been successfully imported with a short name of: quhui
You may now use this name to perform signing operations on this request.
# 签发
./easyrsa sign client quhui
9、复制证书到server目录
1
2
3
4
5
6
7
8
9
10
11
12
13
$ mkdir /etc/openvpn/certs    #服务端
$ cp /etc/openvpn/easy-rsa/3.0.7/pki/dh.pem .
$ cp /etc/openvpn/easy-rsa/3.0.7/pki/ca.crt .
$ cp /etc/openvpn/easy-rsa/3.0.7/pki/issued/server.crt .
$ cp /etc/openvpn/easy-rsa/3.0.7/pki/private/server.key .
$ tree
.
├── ca.crt
├── dh.pem
├── server.crt
└── server.key

0 directories, 4 files
10、整理客户端公钥和私钥
1
2
3
4
5
6
7
8
9
10
11
12
$ cd /etc/openvpn/client/  
$ cd /etc/openvpn/client/quhui/
$ cp /etc/openvpn/easy-rsa/3.0.7/pki/ca.crt . # ca证书
$ cp /etc/openvpn/easy-rsa/3.0.7/pki/issued/quhui.crt . #用户证书
$ cp /etc/openvpn/client/easy-rsa/3.0.7/pki/private/quhui.key . #用户私钥
$ tree
.
├── ca.crt
├── quhui.crt
└── quhui.key

0 directories, 3 files
11、server端配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
$ vim /etc/openvpn/server.conf 
local 0.0.0.0 #本机监听IP
port 1194 #端口
proto tcp #协议,指定VPN创建的通信隧道类型
#proto udp

#dev tap #创建一个以太网隧道,以太网使用tap
dev tun #创建一个路由IP隧道,互联网使用tun一个TUN设备大多时候,
#被用于基于IP协议的通讯。一个TAP设备允许完整的以太网帧通过Openvp隧道,
#因此提供非ip协议的支持,比如IPX协议和AppleTalk协议

#dev-node MyTap #非windows不需要

ca /etc/openvpn/certs/ca.crt #证书路径
cert /etc/openvpn/certs/server.crt
key /etc/openvpn/certs/server.key
dh /etc/openvpn/certs/dh.pem

#topology subnet #网络拓扑,不需要配置

server 10.8.0.0 255.255.255.0 #OpenVPN生成的网络,分配给客户端,服务器默认会占用第一个IP 10.8.0.1

#ifconfig-pool-persist ipp.txt #为客户端分配固定IP,不需要配置

#server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100 #配置网桥模式,不需要
#server-bridge


push "route 192.168.0.0 255.255.248.0" #给客户端生成的静态路由表,下一跳为openvpn服务器的10.8.0.1

#client-config-dir ccd #为指定的客户端添加路由,改路由通常是客户端后面的内网网段而不是服务端的,也不需要设置
#route 192.168.40.128 255.255.255.248

#learn-address ./script #运行外部脚本,创建不同组的iptables 规则,不配置

#push "redirect-gateway def1 bypass-dhcp" #启用后,客户端所有流量都将通过VPN服务器,因此不需要配置

#push "dhcp-option DNS 208.67.222.222" #推送DNS服务器,不需要配置

client-to-client #运行不同的client直接通信

#duplicate-cn #多个用户共用一个账户,一般用于测试环境,生产环境都是一个用户一个证书

keepalive 10 120 #设置服务端检测的间隔和超时时间,默认为每10秒ping一次如果120秒没有回应则认为对方已经 down

#tls-auth ta.key 0

cipher AES-256-CBC #加密算法

#compress lz4-v2 #压缩
#push "compress lz4-v2"
#comp-lzo #旧版本兼容的压缩,

max-clients 100 #最大客户端并发连接数

user nobody
group nobody

persist-key #重启VPN服务,你重新读取keys文件,保留使用第一次的keys文件
persist-tun #重启vpn服务,一直保持tun或者tap设备是up的,否则会先down然后再up

status status /var/log/openvpn/openvpn-status.log #openVPN状态记录文件,每分钟会记录一次,
#/var/log/openvpn/ 手动建立并赋予nobody
#log openvpn.log #log会在openvpn启动的时候清空日志文件
log-append /var/log/openvpn/openvpn.log #重启openvpn后在之前的日志后面追加新的日志

verb 3 #日志级别
mute 50 #相同类别的信息只有前50条会输出到日志文件中

#explicit-exit-notify 1 #通知客户端,在服务端重启后可以自动重新连接,仅能用于udp模式,tcp模式不需要配置即可实现断开重连接
12、客户端配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
port 1194
proto udp
dev tun
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/server.crt
key /etc/openvpn/certs/server.key
dh /etc/openvpn/certs/dh.pem
# OpenVPN Server Certificate - CA, server key and certificate
#注意本文没有跳过了丢消证书的检测
#crl-verify /etc/openvpn/server/crl.pem

# Redirect all Connection through OpenVPN Server
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"

route 192.168.220.0 255.255.255.0 net_gateway # 220网段不使用vpn

# Using the DNS from https://dns.watch
push "dhcp-option DNS 8.8.8.8"

#Enable multiple client to connect with same Certificate key
#duplicate-cn

# TLS Security
cipher AES-128-GCM
#tls-version-min 1.2
#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
#auth SHA512
#auth-nocache

# Other Configuration
#keepalive 20 60
#persist-key
#persist-tun
comp-lzo yes
daemon
user nobody
group nobody

client-to-client
log-append /var/log/openvpn.log
verb 3

# 用户密码验证
script-security 3
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
username-as-common-name
client-cert-not-required
13、启动openvpn服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ systemctl stop firewalld
$ systemctl disable firewalld
$ yum -y install iptables-service iptables #openvpn使用iptables

$ systemctl enable iptables.service
$ systemctl start iptables.service

$ iptables -F
$ iptables -X
$ iptables -Z
$ iptables -t nat -F
$ iptables -t nat -X
$ iptables -t nat -Z
$ vim /etc/sysctl.conf #开启路由转发
net.ipv4.ip_forward = 1
$ sysctl -p

$ service iptables save #保存当前操作



$ systemctl start openvpn@server
$ systemctl enable openvpn@server
tcp流量
1
2
3
4
5
6
创建iptables规则
$ iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -j MASQUERADE
$ iptables -A INPUT -p TCP --dport 1194 -j ACCEPT
$ iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
udp流量

如果你的网关是使用iptable,并且iptable默认情况下阻止该服务,那么请使用以下配置使openvpn正常运行。 首先,让我们在openvpn端口上进行tcp连接。 如果您使用的是udp或其他端口号,请相应地更改此行。

1
$ iptables -A INPUT -i eth0 -m state --state NEW -p udp --dport 1194 -j ACCEPT

允许TUN接口连接到OpenVPN服务器

1
$ iptables -A INPUT -i tun+ -j ACCEPT

允许通过其他接口转发TUN接口连接

1
2
3
iptables -A FORWARD -i tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT

NAT VPN客户端流量到Internet。 运行“ ifconfig”命令时,根据您的tun0结果信息更改IP地址掩码。

1
$ iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

如果您的默认iptables OUTPUT的值不是ACCEPT的话,则还需要以下行:

1
$ iptables -A OUTPUT -o tun+ -j ACCEPT

最后记得保存iptables的防火墙配置

1
$ sudo iptables-save > /etc/sysconfig/iptables
14、windows PC安装openvpn客户端
1
2
官方客户端下载地址: https://openvpn.net/community-downloads/
非官方地址:https://sourceforge.net/projects/securepoint/files/
15、OpenVPN 使用账号+密码方式登陆
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 服务端配置
# 修改服务端配置文件,文件最后追加几行
vim /etc/openvpn/server.conf

script-security 3
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
username-as-common-name
client-cert-not-required
# 如果加上client-cert-not-required则代表只使用用户名密码方式验证登录,如果不加,则代表需要证书和用户名密码双重验证登录!
# /etc/openvpn/checkpsw.sh 文件内容:
#!/bin/sh
###########################################################
# checkpsw.sh (C) 2004 Mathias Sundman <mathias@openvpn.se>
#
# This script will authenticate OpenVPN users against
# a plain text file. The passfile should simply contain
# one row per user with the username first followed by
# one or more space(s) or tab(s) and then the password.

PASSFILE="/etc/openvpn/psw-file"
LOG_FILE="/etc/openvpn/openvpn-password.log"
TIME_STAMP=`date "+%Y-%m-%d %T"`

###########################################################

if [ ! -r "${PASSFILE}" ]; then
echo "${TIME_STAMP}: Could not open password file \"${PASSFILE}\" for reading." >> ${LOG_FILE}
exit 1
fi

CORRECT_PASSWORD=`awk '!/^;/&&!/^#/&&$1=="'${username}'"{print $2;exit}' ${PASSFILE}`

if [ "${CORRECT_PASSWORD}" = "" ]; then
echo "${TIME_STAMP}: User does not exist: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
exit 1
fi

if [ "${password}" = "${CORRECT_PASSWORD}" ]; then
echo "${TIME_STAMP}: Successful authentication: username=\"${username}\"." >> ${LOG_FILE}
exit 0
fi

echo "${TIME_STAMP}: Incorrect password: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
exit 1

# 配置 账号/密码,新增账号/密码增加到这里即可,一行一个账号,密码用空格隔开:
$ cat psw-file
quhui 123456

# 重置权限,安全着想吧
$ chmod 400 psw-file
$ chown nobody.nobody psw-file

# 重启服务openvpn
systemctl restart openvpn@server.service
# 客户端配置
# 注释掉这两行即可
;cert laptop.crt
;key laptop.key

# 新增验证方式
auth-user-pass

2.源码安装

下载 OpenVPN 的源码包:https://www.techspot.com/downloads

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
yum -y install rpm-build openssl easy-rsa libssl-dev gcc openssl-devel pam-devel camke
# configure: error: lzo enabled but missing
# 注意:yum安装的无效,需要手动下载源码安装。
wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.06.tar.gz
tar zxvf lzo-2.06.tar.gz
cd lzo-2.06
./configure --prefix=/usr/local/
make && make install

cd openvpn
./configure --prefix=/usr/local/vpn
make && make install
mkdir /etc/openvpn
cp -r /root/openvpn/openvpn-2.4.9/sample/ /etc/openvpn/\
cp /etc/openvpn/sample/sample-config-files/server.conf /etc/openvpn/
cd /etc/openvpn/ && git clone git://github.com/OpenVPN/easy-rsa
cp vars.example vars

vim vars 根据实际情况,修改以下字段:

set_var EASYRSA_REQ_COUNTRY "cn"
set_var EASYRSA_REQ_PROVINCE "beijing"
set_var EASYRSA_REQ_CITY "quhui"
set_var EASYRSA_REQ_ORG "none"
set_var EASYRSA_REQ_EMAIL "xxxxxx"
set_var EASYRSA_REQ_OU "openvpn"
配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
client
dev tun
proto udp
#真实的ip地址自己填写
remote 47.242.136.192 1194

ca /root/ca.crt
#cert quhui.crt
#key quhui.key

auth-user-pass

cipher AES-256-GCM

resolv-retry infinite
#compress lzo
nobind
persist-key
persist-tun
mute-replay-warnings
verb 3



port 1194
proto udp
dev tun
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/server.crt
key /etc/openvpn/certs/server.key
dh /etc/openvpn/certs/dh.pem

server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"

route 10.128.0.0 255.255.254.0 net_gateway
route 10.192.0.0 255.255.252.0 net_gateway


# Using the DNS from https://dns.watch
push "dhcp-option DNS 8.8.8.8"

cipher AES-256-GCM

duplicate-cn

daemon
user nobody
group nobody
#log-append /var/log/openvpn.log
#verb 3

script-security 3
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
username-as-common-name
client-cert-not-required