openvpn部署

        由于公司内部系统比较多,而且这部分系统都是只能在公司内网访问,当人员出差或者不在办公室的时候就没办法访问,根据需求搭建vpn,来提供给员工访问,之前做的ipsec vpn,由于不是特别的稳定的,于是就选择使用openvpn。这里采用tls认证登录,根据每个员工进行建立账号。

环境准备

         OpenVPN 是一个用于创建虚拟专用网络加密通道的软件包,OpenVPN 允许创建的 VPN 使用公开密钥、电子证书、或者用户名/密码来进行身份验证。它大量使用了 OpenSSL 加密库中的 SSLv3/TLSv1 协议函数库。

        目前 OpenVPN 能在 Solaris、Linux、OpenBSD、FreeBSD、NetBSD、Mac OS X 与 Microsoft Windows 以及 Android 和 iOS 上运行,并包含了许多安全性的功能。它并不是一个基于 Web 的 VPN 软件,也不与 IPsec 及其他 VPN 软件包兼容。

        OpenVPN 的技术核心是虚拟网卡,其次是 SSL 协议实现。

openvpn有两种模式

        数据包(TUN模式)或数据帧(TAP模式)

  • TUN模式: TUN模拟了网络层设备,操作第三层数据包比如IP数据封包,创建的是三层路由隧道
  • TAP模式: 等同于一个以太网设备,它操作第二层数据包如以太网数据帧,创建一个以太网桥接,相对复杂
            TAP 接口的好处在于,客户端可以获得 VPN 服务器所处子网的 IP(忽略物理上的区别,可以完全将客户端看做是与VPN服务器处于同一子网的另一台机器),而TUN 接口下所有的客户端则处于一个完全独立的子网内,与 VPN 服务器所在的子网没有关系,这种使用比较好,和公司的网络区分开,完全一个虚拟的网络。

安装环境

1
2
3
4
5
cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

uname -a
Linux k8s-nfs-data.kxl 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

添加yum源

1
2
3
4
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
yum makecache

安装 openvpn和easy-rsa

1
2
yum -y install openvpn easy-rsa lzop
yum install -y net-tools.x86_64 ntp ntpdate bridge-utils gcc openssl-devel pam-devel zip

开启系统系统IP转发

1
2
3
4
5
6
vi /etc/sysctl.conf
#修改或添加参数
net.ipv4.ip_forward=1

# 执行生效
sysctl -p

证书准备

配置easy-rsa-3.0

        使用 easy-rsa 生成需要的证书及相关文件,在这个阶段会产生一些 key 和证书:

  • CA 根证书
  • OpenVPN 服务器 ssl 证书
  • Diffie-Hellman 算法用到的 key

复制文件

        将 easy-rsa 脚本复制到 /etc/openvpn/,该脚本主要用来方便地生成 CA 证书和各种 key,也可以根据版本号来进行复制,只复制需要的部分。查看 easy-rsa 版本号:yum info 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.6/

编辑vars 文件

        vars 文件中定义的变量是用于生成证书的基本信息,没这个文件可新建,填写如下内容(变量值根据实际情况随便填写)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pwd
/etc/openvpn/easy-rsa/3.0.6

vim vars
export KEY_SIZE=2048 //生成密钥的位数
export KEY_COUNTRY="CN" //你所在国家码,2个字符
export KEY_PROVINCE="CQ" //你所在省份
export KEY_CITY="CHONGQING" //你所在城市
export KEY_ORG="xxlaila" //你所在组织
export KEY_EMAIL=admin@xxlaila.cn //你的邮箱地址
export KEY_CN=ceshi //随意
export KEY_NAME=ceshi //随意
export KEY_OU=xxlaila //你所在的单位

# 使变量生效
source ./vars

生成 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
25
26
27
28
29
30
31
#初始化 pki 相关目录
./easyrsa init-pki

#生成 CA 根证书, 输入 Common Name,名字随便起。
./easyrsa build-ca nopass

Note: using Easy-RSA configuration from: ./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]:xxlaila.cn

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.6/pki/ca.crt

# 生成证书如下
# find ./ -name ca*
./x509-types/ca
./pki/private/ca.key
./pki/ca.crt

生成 OpenVPN 服务器证书和密钥

        第一个参数 server 为证书名称,可以随便起,比如 ./easyrsa build-server-full openvpn nopass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# ./easyrsa build-server-full server nopass

Note: using Easy-RSA configuration from: ./vars

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/easy-rsa/3.0.6/pki/private/server.key.7zl4ekqsBM'
-----
Using configuration from /etc/openvpn/easy-rsa/3.0.6/pki/safessl-easyrsa.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'server'
Certificate is to be certified until Feb 14 07:19:05 2023 GMT (1080 days)

Write out database with 1 new entries
Data Base Updated

生成 Diffie-Hellman 算法需要的密钥文件

1
2
3
4
5
6
7
8
9
./easyrsa gen-dh

# 生成文件
find ./ -name server*
./x509-types/server
./x509-types/serverClient
./pki/private/server.key
./pki/reqs/server.req
./pki/issued/server.crt

生成 tls-auth key

         这个 key 主要用于防止 DoS 和 TLS 攻击,这一步其实是可选的,但为了安全还是生成一下,该文件在后面配置 open VPN 时会用到。

1
openvpn --genkey --secret ta.key

生成自动吊销用户证书

1
2
3
4
5
6
7
8
./easyrsa gen-crl
Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Using configuration from /etc/openvpn/easy-rsa/3.0.6/pki/safessl-easyrsa.cnf

An updated CRL has been created.
CRL file: /etc/openvpn/easy-rsa/3.0.6/pki/crl.pem

:crl.pem证书的不能移动,否则在后期删除用户认证的时候不生效,保持该目录即可

整理证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mkdir /etc/openvpn/server/certs && cd /etc/openvpn/server/certs/
cp /etc/openvpn/easy-rsa/3.0.6/pki/dh.pem ./
cp /etc/openvpn/easy-rsa/3.0.6/pki/ca.crt ./
cp /etc/openvpn/easy-rsa/3.0.6/pki/issued/server.crt ./
cp /etc/openvpn/easy-rsa/3.0.6/pki/private/server.key ./
cp /etc/openvpn/easy-rsa/3.0.6/ta.key ./

ls -ltrh
total 24K
-rw------- 1 root root 424 Mar 1 15:27 dh.pem
-rw------- 1 root root 1.2K Mar 1 15:27 ca.crt
-rw------- 1 root root 4.5K Mar 1 15:28 server.crt
-rw------- 1 root root 1.7K Mar 1 15:28 server.key
-rw------- 1 root root 636 Mar 1 15:28 ta.key

openvpn server配置

创建 open VPN 日志目录

1
2
mkdir -p /var/log/openvpn/
chown openvpn:openvpn /var/log/openvpn

配置 OpenVPN

         可以从 /usr/share/doc/openvpn-/sample/sample-config-files 复制一份 demo 到 /etc/openvpn/(openvpn 版本号查看:yum info 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
cd /etc/openvpn/

vim server.conf
port 1194 # 监听的端口号
proto udp # 服务端用的协议,udp,默认udp
dev tun
ca /etc/openvpn/server/certs/ca.crt # CA 根证书路径
cert /etc/openvpn/server/certs/server.crt # open VPN 服务器证书路径
key /etc/openvpn/server/certs/server.key # open VPN 服务器密钥路径,This file should be kept secret
dh /etc/openvpn/server/certs/dh.pem # Diffie-Hellman 算法密钥文件路径
tls-auth /etc/openvpn/server/certs/ta.key 0 # 开启TLS-auth,使用ta.key防御攻击。服务器端的第二个参数值为0,客户端的为1。
ifconfig-pool-persist ipp.txt #服务器自动给客户端分配IP后,客户端下次连接时,仍然采用上次的IP地址(第一次分配的IP保存在ipp.txt中,下一次分配其中保存的IP)。
push "route 10.0.0.0 255.0.0.0" # # 推送路由和DNS到客户端
push "route 172.21.16.0 255.255.240.0" # 推送路由到客户端,如果内网服务器地址是172.21.16.0的网段,可以增加此行,然后就可以ping通内网地址的所有服务器
server 10.8.0.0 255.255.255.0 # 该网段为 open VPN 虚拟网卡网段,不要和内网网段冲突即可。open VPN 默认为 10.8.0.0/24
push "dhcp-option DNS 8.8.8.8" # DNS 服务器配置,可以根据需要指定其他 ns
push "dhcp-option DNS 8.8.4.4"
# push "redirect-gateway def1" # 客户端所有流量都通过 open VPN 转发,类似于代理开全局,VPN服务器本身要通过客户端原来的网关访问(取消redirect-gateway def1 bypass-dhcp选项后这项必须开启,否则无法访问OpenVPN服务器)
compress lzo
duplicate-cn # 如果客户端都使用相同的证书和密钥连接VPN,一定要打开这个选项,否则每个证书只允许一个人连接VPN
keepalive 10 120 # 每10秒ping一次,连接超时时间设为120秒。
comp-lzo # 开启VPN连接压缩,如果服务器端开启,客户端也必须开启
client-to-client #设置客户端是否可以访问客户端
persist-key # 持久化选项可以尽量避免访问在重启时由于用户权限降低而无法访问的某些资源。
persist-tun
max-clients 100 # 允许最大的客户端连接数,默认100
user openvpn # open VPN 进程启动用户,openvpn 用户在安装完 openvpn 后就自动生成了
group openvpn
log /var/log/openvpn/server.log # 指定 log 文件位置
log-append /var/log/openvpn/server.log
status /var/log/openvpn/status.log
verb 3
explicit-exit-notify 1 # 设置断线重连功能
cipher AES-256-CBC #指定数据对称加密算法
reneg-sec 0 #reneg-sec服务器端会定期检查认证情况,默认3600秒一小时,使用OTP的话尽量时间长一些,否则客户端需要重新输入用户名密码和OTP一次性密码。
auth-nocache #断线后防止内存中保存用户名和密码来提高安全性

注意

  • openvpn 2.4.8 版本启动协议需要使用udp,否则无法启动,启动的时候会提示Options error: --explicit-exit-notify can only be used with --proto udp,而且默认配置文件里面协议也是udp。udp协议有很多好处,可以参考说明
  • push “redirect-gateway def1”: 参数,如果添加该参数,所有客户端的默认网关都将重定向到VPN,这将导致诸如web浏览器、DNS查询等所有客户端流量都经过这里。但是在实际的应用中,我们期望的是只有需要进过vpn流量的时候才走vpn,其他的就正常走我们自己的网络就可以啦。所以在server.conf文件里面这行就需要注释掉。

防火墙相关配置

禁用 Centos7 默认的 firewalld和SELinux
1
2
3
4
5
6
7
8
systemctl stop firewalld
systemctl disable firewalld

# 马上生效
setenforce 0

# 永久关闭(需要重启服务器生效)
sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/g’ /etc/selinux/config
启用iptables
1
2
3
4
5
systemctl enable iptables
systemctl start iptables

# 清理所有防火墙规则
iptables -F
添加防火墙规则
1
2
3
4
5
6
7
8
# 将 openvpn 的网络流量转发到公网:snat 规则
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE

# iptables 规则持久化保存
iptables-save > /etc/sysconfig/iptables

# 或者
sudo /usr/libexec/iptables/iptables.init save
规则查看
1
iptables -nvL -t nat

启动 open VPN

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

验证

1
2
netstat -antpu | grep openvpn
udp 0 0 0.0.0.0:1194 0.0.0.0:* 1787/openvpn

路由器端口映射

        由于公司只有一个公网Ip,所以只能在路由器上做端口映射,端口映射参考

openvpn client

OpenVPN客户端配置

        要连接到 open VPN 服务端首先得需要一个客户端软件,在 Mac 下推荐使用 Tunnelblick。Tunnelblick 是一个开源、免费的 Mac 版 open VPN 客户端软件。如果Tunnelblick安装失败,不要用常见的方式进行卸载,要在Tunnelblick的官方下载一个Tunnelblick的卸载安装包进行Tunnelblick的卸载,否则不成功。

        下面在服务端创建一个 open VPN 用户:其实创建用户的过程就是生成客户端 SSL 证书的过程,然后将其他相关的证书文件、key、.ovpn 文件(客户端配置文件)打包到一起供客户端使用。由于创建一个用户的过程比较繁琐,所以在此将整个过程写成了一个脚本 vpn_user.sh,然后定义一个客户端基础的模版文件 sample.ovpn。

        首先创建一个客户端配置模板文件 sample.ovpn,该文件在脚本中会用到,放到 /etc/openvpn/client/ 目录,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat sample.ovpn
client
proto udp
dev tun
remote [open VPN服务端公网 ip,根据实际情况填写] 1194 //openvpn服务器的外网IP和端口(可以写多个做到高可用)
ca ca.crt
cert admin.crt
key admin.key
tls-auth ta.key 1
remote-cert-tls server //指定采用服务器校验方式
comp-lzo
verb 3 //调试信息级别
mute-replay-warnings
resolv-retry infinite //断线自动重新连接
nobind //不绑定特定的本地端口号
persist-key //与服务器端的保持一致
persist-tun //与服务器端的保持一致
cipher AES-256-CBC //指定数据对称加密算法

: client.key 和 client.crt 替换为用户的key。

linux 客户端

        需要在linux服务器上安装openvpn,安装完成以后增加配置文件即可。client.ovpn配置文件和上述mac 配置文件一致,下面贴出有区别后的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 安装openvpn
yum -y install openvpn

cd /etc/openvpn/client
# 把生成后的配置文件解压到该目录

# 启动openvpn 客户端
nohup /usr/sbin/openvpn --config /etc/openvpn/client/usernmae.ovpn --log-append /tmp/openvpn.log &

# 如果使用账号和密码登录,需要使用systemd-tty-ask-password-agent来进行账号和密码输入登录认证,如下

Password entry required for 'Enter Auth Username:' (PID 4699).
Please enter password with the systemd-tty-ask-password-agent tool!

systemd-ask-password
systemd-ask-password: required argument missing.
Enter Auth Username: username


Broadcast message from root@VM_11-11_centos (Fri 2020-03-13 10:24:49 CST):
Password entry required for 'Enter Auth Password:' (PID 4762).
Please enter password with the systemd-tty-ask-password-agent tool!
systemd-tty-ask-password-agent
Enter Auth Password: *********

        可以查看/tmp/openvpn.log日志输出的记录信息。里面包含了一些路由的添加

linux 下结果验证

1
2
3
4
5
6
7
8
ifconfig tun0
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.8.0.10 netmask 255.255.255.255 destination 10.8.0.9
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

windows下的client.ovpn配置文件

        windows 客户端在官方下载对应的系统的客户端进行安装,安装完成后会在当前的用户目录下面有一个C:\Users\username\OpenVPN\config\的路径,吧在服务器上生成的username.zip解压到该目录下面即可。然后点击链接。windows 客户端的配置文件如下,和上面的一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat sample.ovpn
client
dev tun
proto udp
remote [open VPN服务端公网 ip,根据实际情况填写] 1194 //openvpn服务器的外网IP和端口(可以写多个做到高可用)
resolv-retry infinite
# redirect-gateway def1#让客户端发起的所有IP请求都通过OpenVPN服务器
nobind
persist-key
persist-tun
ca ca.crt
cert admin.crt
key admin.key
#auth-user-pass //用用户名密码登陆认证方式
remote-cert-tls server
tls-auth ta.key 1#ta.key
tls-client#TLS加密传输
comp-lzo
verb 3
mute 20

注释:

  • auth-user-pass: 该参数是注释掉的,如果开启该参数,任意的账户和密码都可以链接vpn,非常的不安全,如果客户端开启这个参数,服务器端一定要启用用户认证。用户认证参考

创建 open VPN 用户脚本

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
cat vpn_user.sh
set -e

OVPN_USER_KEYS_DIR=/etc/openvpn/client/keys
EASY_RSA_VERSION=3.0.6
EASY_RSA_DIR=/etc/openvpn/easy-rsa/
PKI_DIR=$EASY_RSA_DIR/$EASY_RSA_VERSION/pki

for user in "$@"
do
if [ -d "$OVPN_USER_KEYS_DIR/$user" ]; then
rm -rf $OVPN_USER_KEYS_DIR/$user
rm -rf $PKI_DIR/reqs/$user.req
sed -i '/'"$user"'/d' $PKI_DIR/index.txt
fi
cd $EASY_RSA_DIR/$EASY_RSA_VERSION
# 生成客户端 ssl 证书文件
./easyrsa build-client-full $user nopass
# 整理下生成的文件
mkdir -p $OVPN_USER_KEYS_DIR/$user
cp $PKI_DIR/ca.crt $OVPN_USER_KEYS_DIR/$user/ # CA 根证书
cp $PKI_DIR/issued/$user.crt $OVPN_USER_KEYS_DIR/$user/ # 客户端证书
cp $PKI_DIR/private/$user.key $OVPN_USER_KEYS_DIR/$user/ # 客户端证书密钥
cp /etc/openvpn/client/sample.ovpn $OVPN_USER_KEYS_DIR/$user/$user.ovpn # 客户端配置文件
sed -i 's/admin/'"$user"'/g' $OVPN_USER_KEYS_DIR/$user/$user.ovpn
cp /etc/openvpn/server/certs/ta.key $OVPN_USER_KEYS_DIR/$user/ta.key # auth-tls 文件
cd $OVPN_USER_KEYS_DIR
zip -r $user.zip $user
done
exit 0

        执行上面脚本创建一个用户:sh vpn_user.sh,会在 /etc/openvpn/client/keys 目录下生成以用户名命名的 zip 打包文件,将该压缩包下载到本地解压,然后将里面的 .ovpn 文件拖拽到 Tunnelblick 客户端软件即可使用。客户端目录随意存放。生产的内容如下

1
2
3
4
5
6
.
├── ca.crt
├── username.crt
├── username.key
├── username.ovpn
└── ta.key

删除一个 OpenVPN 用户

        上面介绍了如何添加一个用户,如果公司员工离职了或者其他原因,想删除对应用户 OpenVPN 的使用权,只要吊销对应用户的 SSL 证书即可。因为OpenVPN 的客户端和服务端的认证主要通过 SSL 证书进行双向认证。

编辑 OpenVPN 服务端配置 server.conf 添加如下配置:
1
crl-verify /etc/openvpn/easy-rsa/3.0.6/pki/crl.pem
吊销用户证书
1
2
3
cd /etc/openvpn/easy-rsa/3.0.6/
./easyrsa revoke username
./easyrsa gen-crl
重启 OpenVPN 服务端使其生效
1
systemctl restart openvpn@server
一键删除用户
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat del_vpn_user.sh
# ! /bin/bash

set -e
OVPN_USER_KEYS_DIR=/etc/openvpn/client/keys
EASY_RSA_VERSION=3.0.6
EASY_RSA_DIR=/etc/openvpn/easy-rsa/
for user in "$@"
do
cd $EASY_RSA_DIR/$EASY_RSA_VERSION
echo -e 'yes\n' | ./easyrsa revoke $user
./easyrsa gen-crl
# 吊销掉证书后清理客户端相关文件
if [ -d "$OVPN_USER_KEYS_DIR/$user" ]; then
rm -rf $OVPN_USER_KEYS_DIR/${user}*
fi
systemctl restart openvpn@server
done
exit 0

        上述配置完成了用户流量的分配,必要的地址都vpn,其余的走正常的自己的网络。不会全部走vpn。

引用: https://www.yeboyzq.com/linux/fuwuqipeizhi/989.html
https://qhh.me/2019/06/16/Cenos7-%E4%B8%8B%E6%90%AD%E5%BB%BA-OpenVPN-%E8%BF%87%E7%A8%8B%E8%AE%B0%E5%BD%95/

坚持原创技术分享,您的支持将鼓励我继续创作!
0%