Centos7部署openvpn

OpenVPN是一个用于创建虚拟专用网络加密通道的软件包。
OpenVPN可以使用公开密钥、电子证书、或者用户名/密码来进行身份验证。它大量使用了OpenSSL加密库中的SSLv3/TLSv1协议函数库。
OpenVPN可以在Solaris、Linux、OpenBSD、FreeBSD、NetBSD、Mac OS X以及Windows、Android和ios上运行。

一、安装openvpn

系统环境为centos7,采用yum方式安装:

1
2
3
yum install epel-release -y
yum install iptables-services openssl ca-certificates -y
yum install openvpn easy-rsa -y

二、生成CA证书

1、复制easy-rsa文件

1
2
3
4
cp -r /usr/share/easy-rsa/ /etc/openvpn/easy-rsa
cd /etc/openvpn/easy-rsa/
\rm 3 3.0
cd 3.0.3/

2、创建一个新的 PKI 和 CA

1
2
3
cd /etc/openvpn/easy-rsa/3.0.3/
./easyrsa init-pki
./easyrsa --batch build-ca nopass

三、创建服务端和客户端证书

1
2
3
4
5
6
7
8
9
cd /etc/openvpn/easy-rsa/3.0.3/
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-server-full server nopass
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full client nopass
# 生成CRL文件
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
# 创建 Diffie-Hellman
./easyrsa gen-dh
# 生成 tls-auth 所需要的 ta.key 文件,tls-auth 在 SSL/TLS 握手包的基础上增加了额外的签名,以提供更高的安全性
openvpn --genkey --secret /etc/openvpn/ta.key

整理服务端所需证书文件:

1
2
3
cd /etc/openvpn/easy-rsa/3.0.3/
cp pki/ca.crt pki/issued/server.crt pki/private/server.key pki/crl.pem pki/dh.pem /etc/openvpn
chown openvpn:openvpn /etc/openvpn/crl.pem

四、服务端配置文件

/etc/openvpn/server.conf

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
port 11904
# 端口协议,默认udp
proto udp
# openvpn有两种运行模式tun(路由模式)和tap(桥接模式)
dev tun
sndbuf 0
rcvbuf 0
# CA证书文件
ca ca.crt
# 服务器证书
cert server.crt
# 服务器密钥(必须严格控制其安全性)
key server.key
# 定义Diffie hellman文件
dh dh.pem
# 吊销客户端证书使用
crl-verify crl.pem
# SSL/TLS额外提供的HMAC防火墙,打开会更安全
# ta.key文件增强安全性,防DDos攻击、UDP淹没等恶意攻击,默认不开启;此key文件在服务端/客户端各1份,服务端参数为"0",客户端参数为"1"
tls-auth ta.key 0
# 数据通道的认证摘要,默认SHA-1
auth SHA512
;auth RSA-SHA512
# 选择一个密码加密算法,如果服务器端启用了cipher指令选项,那客户端必须一致
# 该配置项也必须复制到每个客户端配置文件中。
cipher AES-256-CBC
;cipher BF-CBC # Blowfish (默认)
;cipher AES-128-CBC # AES
;cipher DES-EDE3-CBC # Triple-DES

topology subnet
# 定义openvpn在使用tun路由模式时,分配给client端分配的IP地址段
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt"
# 重定向客户端的网关
push "redirect-gateway def1 bypass-dhcp"
# 向客户端推送的DNS信息
push "dhcp-option DNS 208.67.220.220"
push "dhcp-option DNS 208.67.222.222"
# 使客户端之间能相互访问
client-to-client
# 一个证书在同一时刻是否允许多个客户端接入
duplicate-cn
# 默认每10秒钟ping一次,如果120秒内都没有收到对方的回复,则表示远程连接已经关闭
keepalive 10 120
user openvpn
group openvpn
# 允许并发连接的客户端的最大数量
max-clients 100
# 通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-key
# 通过keepalive检测vpn超时后,当重新启动vpn后,保持tun或者tap设备自动连接状态
persist-tun
# 状态日志(客户端IP)
status openvpn-status.log
# 日志文件
log-append openvpn.log
# 日志级别(0~9),越大越详细
verb 3
# 在VPN连接上启用压缩。如果你在此处启用了该指令,那么也应该在每个客户端配置文件中启用它
comp-lzo
;comp-lzo adaptive 默认,后面不带参数也是默认
;comp-lzo yes
;comp-lzo no

# 相同类别的信息只有前20条会输出到日志文件中。
mute 20

:在GCE上部署openvpn TCP模式,客户端无法连接,一直报reset,在服务端开启 tls-auth 后才可以,分析可能是GFW限制。
UDP模式正常,所以建议开启 tls-auth

五、系统其它配置

1、开启路由转发

1
2
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p

2、关闭selinux

1
2
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0

3、配置iptables防火墙

1
2
3
4
5
# $IP为服务器ip
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP
iptables -I INPUT -p udp --dport 1194 -j ACCEPT
iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT
iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

六、启动openvpn

1
2
systemctl start openvpn@server
systemctl enable openvpn@server

七、客户端配置文件

1、整理客户端所需证书文件:

1
2
3
4
cd /etc/openvpn/client/
cp /etc/openvpn/easy-rsa/3.0.3/pki/ca.crt .
cp /etc/openvpn/easy-rsa/3.0.3/pki/issued/client.crt .
cp /etc/openvpn/easy-rsa/3.0.3/pki/private/client.key .

2、创建客户端配置文件
/etc/openvpn/client/cilent.ovpn

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
client
# openvpn运行的模式,与服务器一致
dev tun
proto udp
sndbuf 0
rcvbuf 0
remote 1.2.3.4 1194
# 始终重新解析Server的IP地址(如果remote后面跟的是域名)
resolv-retry infinite
# 定义在本机不邦定任何端口监听incoming数据
nobind
persist-key
persist-tun
# 指定采用服务器校验方式
remote-cert-tls server
auth SHA512
cipher AES-256-CBC
key-direction 1
verb 3
# 启用允许数据压缩,与服务器一致
comp-lzo
ca ca.crt
cert client.crt
key client.key
# 启用tls-auth
tls-auth ta.key 1

八、配置账号密码登陆

1、创建用户认证脚本(checkpsw.sh)

/etc/openvpn/checkpsw.sh

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
#!/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

给予脚本执行权限:

1
chmod +x /etc/openvpn/checkpsw.sh

2、配置用户密码文件

/etc/openvpn/psw-file

1
2
user1 passwd1
user2 passwd2

3、修改服务端配置文件

/etc/openvpn/server.conf

1
2
3
4
5
6
script-security 3
# 指定用户认证脚本
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
# 使用客户提供的UserName作为Common Name
username-as-common-name
verify-client-cert none

注:如果加上client-cert-not-required则代表只使用用户名密码方式验证登录。
如果不加,则代表需要证书和用户名密码双重验证登录!

4、修改客户端配置文件

注释掉cert和key(客户端不需要crt和key文件,但是需要服务器的CA证书)

1
2
;cert client.crt
;key client.key

添加如下配置项

1
auth-user-pass

九、配置文件模板

server.conf

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
port 23
proto udp
dev tun
sndbuf 0
rcvbuf 0
auth SHA512
cipher AES-256-CBC
topology subnet
ca ca.crt
cert server.crt
key server.key
dh dh.pem
crl-verify crl.pem
server 10.88.88.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 223.5.5.5"
push "dhcp-option DNS 223.6.6.6"
keepalive 10 120
comp-lzo
duplicate-cn
user openvpn
group openvpn
max-clients 100
persist-key
persist-tun
status openvpn-status.log
log-append openvpn.log
verb 3
mute 20
script-security 3
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
username-as-common-name
verify-client-cert none
tls-auth ta.key 0

client.ovpn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
client
proto udp
dev tun
sndbuf 0
rcvbuf 0
remote 35.231.6.93 23
ca ca.crt
resolv-retry infinite
nobind
mute-replay-warnings
keepalive 20 120
comp-lzo
persist-key
persist-tun
status openvpn-status.log
log-append openvpn.log
verb 3
mute 20
cipher AES-256-CBC
auth SHA512
auth-user-pass
setenv opt block-outside-dns
key-direction 1
;tls-auth ta.key 1

十、openvpn调优

1、禁用 comp-lzo
2、cipher 设置成 none
3、auth 设置为 none