OpenVPN部署与应用

  • VPN直译就是虚拟专用通道,是提供给企业之间或者个人与公司之间安全数据传输的隧道,OpenVPN无疑是Linux下开源VPN的先锋,提供了良好的性能和友好的用户GUI.
  • OpenVPN大量使用了OpenSSL加密库中的SSLv3/TLSv1协议函数库.
  • OpenVPN是一个基于OpenSSL库的应用层 VPN 实现.和传统 VPN 相比,它的优点是简单易用.
  • 出处地址
  • 文档地址
  • 其他vpn部署脚本setup-ipsec-vpn

生成证书

安装证书生成工具easy-rsa

#yum安装
yum -y install easy-rsa
#rpm安装
rpm -ivh easy-rsa-3.0.7-1.el7.noarch.rpm

创建证书环境目录

  • 以3.0.7版本为例
mkdir -p /opt/easy-rsa
cp -a /usr/share/easy-rsa/3.0.7/* /opt/easy-rsa/
cp -a /usr/share/doc/easy-rsa-3.0.7/vars.example /opt/easy-rsa/vars

准备vars文件

  • 修改文件/opt/easy-rsa/vars中的如下配置(要取消注释)

QQ截图20200825160437.png

vi /opt/easy-rsa/vars

set_var EASYRSA_DN      "cn_only"
set_var EASYRSA_REQ_COUNTRY     "CN"
set_var EASYRSA_REQ_PROVINCE    "Shanghai"
set_var EASYRSA_REQ_CITY        "Shanghai"
set_var EASYRSA_REQ_ORG         "1997sty"
set_var EASYRSA_REQ_EMAIL       "admin@1997sty.com"
set_var EASYRSA_NS_SUPPORT      "yes"

初始化

  • 在当前目录下创建pki目录,用于存储证书

QQ截图20200825160422.png

cd /opt/easy-rsa/
/opt/easy-rsa/easyrsa init-pki

创建根证书

  • 根证书用于ca对之后生成的server和client证书签名时使用.

QQ截图20200825160642.png

/opt/easy-rsa/easyrsa build-ca

创建server端证书和私钥文件

  • nopass表示不加密私钥文件,生成过程中直接回车默认

QQ截图20200825160748.png

/opt/easy-rsa/easyrsa gen-req server nopass

给server证书签名

QQ截图20200825161017.png

/opt/easy-rsa/easyrsa sign server server

创建Diffie-Hellman文件

  • 创建Diffie-Hellman文件,秘钥交换时的Diffie-Hellman算法

QQ截图20200825161220.png

/opt/easy-rsa/easyrsa gen-dh

创建client端证书和私钥文件

  • nopass表示不加密私钥文件,生成过程中直接回车默认

QQ截图20200825161313.png

/opt/easy-rsa/easyrsa gen-req client nopass

给client端证书签名

  • 给client端证书签名

QQ截图20200825161441.png

/opt/easy-rsa/easyrsa sign client client

OpenVPN服务端部署

安装openvpn软件

#yum安装
yum -y install openvpn
#rpm安装openvpn和依赖
rpm -ivh openvpn-2.4.9-1.el7.x86_64.rpm pkcs11-helper-1.11-3.el7.x86_64.rpm

修改配置文件

  • 自行创建配置文件/etc/openvpn/server.conf,并加入如下配置
cat >> /etc/openvpn/server.conf << EOF
port 1194 #端口
proto udp #协议
dev tun #采用路由隧道模式tun
ca ca.crt #ca证书文件位置
cert server.crt #服务端公钥名称
key server.key #服务端私钥名称
dh dh.pem #交换证书
server 10.8.0.0 255.255.255.0 #给客户端分配地址池,注意:不能和VPN服务器内网网段有相同
push "route 172.16.1.0 255.255.255.0" #允许客户端访问内网172.16.1.0网段
#push "redirect-gateway def1 bypass-dhcp" #重定向网关 客户端要通过服务端代理上网(本机对外 IP显示为服务端的IP)
#push "dhcp-option DNS 192.168.50.1" #指定DNS服务器可加可不加
ifconfig-pool-persist ipp.txt #地址池记录文件位置
keepalive 10 120 #存活时间,10秒ping一次,120 如未收到响应则视为断线
max-clients 100 #最多允许100个客户端连接
status openvpn-status.log #日志记录位置
verb 3 #openvpn版本
client-to-client #客户端与客户端之间支持通信log /var/log/openvpn.log #openvpn日志记录位置
persist-key #通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys.
persist-tun #检测超时后,重新启动VPN,一直保持tun是linkup的.否则网络会先linkdown然后再linkup
duplicate-cn
EOF

拷贝证书到openvpn主配置文件目录下

证书密码均为1997sty

cp -a /opt/easy-rsa/pki/ca.crt /etc/openvpn/
cp -a /opt/easy-rsa/pki/issued/server.crt /etc/openvpn/
cp -a /opt/easy-rsa/pki/private/server.key /etc/openvpn/
cp -a /opt/easy-rsa/pki/dh.pem /etc/openvpn/

启动openvpn

systemctl -f enable openvpn@server.service
systemctl start openvpn@server.service

OpenVPN客户端部署

windows系统安装OpenVPN客户端软件

这里是在windows环境下部署OpenVPN的客户端的,首先需要下载安装OpenVPN客户端软件

配置客户端

  • 拷贝服务端生成的证书到OpenVPN安装目录的config目录下

QQ截图20200825163027.png

/opt/easy-rsa/pki/ca.crt
/opt/easy-rsa/pki/issued/client.crt
/opt/easy-rsa/pki/private/client.key
  • 在OpenVPN安装目录的config目录下,新建一个client.ovpn文件

QQ截图20200825163507.png

remote 10.0.0.5 1194 #openvpn服务器IP地址端口号
nobind #不绑定本地特定的端口号
proto udp #使用udp协议传输数据
dev tun #使用tun隧道传输协议
client #指定当前VPN是客户端
resolv-retry infinite #断线自动重新连接,在网络不稳定的情况下非常有用
ca ca.crt #指定CA证书的文件路径
cert client.crt #指定当前客户端的证书文件路径
key client.key #指定当前客户端的私钥文件路径
verb 3 #指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
persist-key #通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-tun #检测超时后,重新启动VPN,一直保持tun是linkup的.否则网络会先linkdown然后再linkup
  • 也可以将证书信息直接写入client.ovpn
remote 10.0.0.5 1194 #openvpn服务器IP地址端口号
nobind #不绑定本地特定的端口号
proto udp #使用udp协议传输数据
dev tun #使用tun隧道传输协议
client #指定当前VPN是客户端
resolv-retry infinite #断线自动重新连接,在网络不稳定的情况下非常有用
verb 3 #指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
persist-key #通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-tun #检测超时后,重新启动VPN,一直保持tun是linkup的.否则网络会先linkdown然后再linkup


#指定CA证书
<ca>
-----BEGIN CERTIFICATE-----
MIIDNTCCAh2gAwIBAgIJAP0BLkJBb6lnMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV
BAMMC0Vhc3ktUlNBIENBMB4XDTIwMDgyNTA4MDYxM1oXDTMwMDgyMzA4MDYxM1ow
FjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCrtECZf+xl2MA3xnJ+H+U34Zcx+sQo83K3dk+zNo6c6VDdk1SA7dId
gpixS8X1MHWOFmSWuKF6199du+affzvyCwW8TL68QBp2CZMU7mKKDzAvo9Z0/Odd
8PrGgdfjBfBen4grVpw3ai7ZrPj0Tmn/Th+Cye8CTzSwfuqMbfqhsIg21OEbrDXi
mBmjOeyhVMEbmhQmyS017Og29KMJDjD6aCYevAY53h07ZOvYGljXlg61IIu+1X1q
y47IoxzFccQjQAvBs2ujBWqSVBTvlrbUJ6Qwzze/ASbY4+gTwVlQbUwMUjREIHLy
5qWC5n2rURqNkoegOQ8D/uoq+4tQNQR1AgMBAAGjgYUwgYIwHQYDVR0OBBYEFPVZ
ePhCKPjO3eTr1D5dZPT4WOioMEYGA1UdIwQ/MD2AFPVZePhCKPjO3eTr1D5dZPT4
WOiooRqkGDAWMRQwEgYDVQQDDAtFYXN5LVJTQSBDQYIJAP0BLkJBb6lnMAwGA1Ud
EwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQCgclPlyxLP
1nvaOpIT7uhFvwY8l7NtB/V0ijgc9rxmBrjUg58AtqyQn85kqWhxfrSPam9NNeFc
1rlwaNd0Xbp7wHNELclz/Wou6o0tDFlcqXRkdBZQFEra8ToxWpYhOs8A+BryqbEt
MAqmPT7qKM+PvRfTWcSmUsYYoHj7e5uOiexWnOOB9Q2XibRcEvHGgCDJZnGj/x+b
UBJWEJSG/4sn7fq5TOXm2q/W9qNkhyJRETYitDNSU1wv2zEx5FZc1DFhEPIankOH
sXaPWR+0HX9OR93BKKPLP3L6BFVDhbMpZKoUF87uuapwzOmslUNVVDGYXaTQ5XZl
EB22o5VMHo26
-----END CERTIFICATE-----
</ca>

#指定当前客户端的证书

<cert>
-----BEGIN CERTIFICATE-----
MIIDlDCCAnygAwIBAgIRAO0t/5YJNt6ol5qS/JcAipswDQYJKoZIhvcNAQELBQAw
FjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0EwHhcNMjAwODI1MDgxNDA2WhcNMjIxMTI4
MDgxNDA2WjARMQ8wDQYDVQQDDAZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQCzipo3N9NKH9NT/YLfd4f2O7euFkCNpmAA5nKytzfMQJAzBPt0
W8QOCPYeygpnFbGca+JyUfEpRPFR2G8Fak4DIqgcQKeJ7IiH6DkM2JryDH2sHExO
ysHWXaUaifbD/LLnE65J5bHl5cv833c0zeB2c1eSiI6g/lSzFWlUNE8J3qhVrBd5
fRaOcHBTsRMr7aEYsSykIyT41sotmt6e0lH7MHNY0NutL5/2HtZym1RC+hYxvJji
ev+PFez/4rYyDAeeMcuqFx68LfmMh6Umq609ln54txGnFWl6nznpyYbL/kUE8Qpu
1HH8Wo5ngKMrqSrIgGN8JsfT6ZY8NDVP1yG1AgMBAAGjgeEwgd4wCQYDVR0TBAIw
ADAdBgNVHQ4EFgQUEBIl3lQtqoyIv4FaWlphUdV3mqUwRgYDVR0jBD8wPYAU9Vl4
+EIo+M7d5OvUPl1k9PhY6KihGqQYMBYxFDASBgNVBAMMC0Vhc3ktUlNBIENBggkA
/QEuQkFvqWcwEwYDVR0lBAwwCgYIKwYBBQUHAwIwCwYDVR0PBAQDAgeAMDUGCWCG
SAGG+EIBDQQoFiZFYXN5LVJTQSAoMy4wLjcpIEdlbmVyYXRlZCBDZXJ0aWZpY2F0
ZTARBglghkgBhvhCAQEEBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAII4qE3hm6kJ
BIqN2mmnrkEpthmqMQw58z1KJAONtNPUd/nHsa89gMx3Qzr4KSRp8elXtNIFHyvE
ATOeirurcu2PKQ4Yf2QYSoqo/uypDssiOcKrCSmnVCXjIdCFeccVcXHRKJvFU87V
N6S3cLQ8oLWH3Cm9JpMzZnt9pZoC4OPnXqYDnLVr/a+dAsd0x9/WnxCPfpOlCv7u
xJk6qmhLyLM0V7TYyr8nwjiGjD3bLePA6N1zMSdQrhSniy+JRkt2cVgjPGDiacis
TgWj+uRspUJOdFEqCGHtjnT/DTgRsGlWn6NBCExl3qnwoEudk3yijg0s7jRrIstS
F+3pS4HWznY=
-----END CERTIFICATE-----
</cert>

#指定当前客户端的私钥

<key>
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzipo3N9NKH9NT
/YLfd4f2O7euFkCNpmAA5nKytzfMQJAzBPt0W8QOCPYeygpnFbGca+JyUfEpRPFR
2G8Fak4DIqgcQKeJ7IiH6DkM2JryDH2sHExOysHWXaUaifbD/LLnE65J5bHl5cv8
33c0zeB2c1eSiI6g/lSzFWlUNE8J3qhVrBd5fRaOcHBTsRMr7aEYsSykIyT41sot
mt6e0lH7MHNY0NutL5/2HtZym1RC+hYxvJjiev+PFez/4rYyDAeeMcuqFx68LfmM
h6Umq609ln54txGnFWl6nznpyYbL/kUE8Qpu1HH8Wo5ngKMrqSrIgGN8JsfT6ZY8
NDVP1yG1AgMBAAECggEASwAeVezDHdbXn+Fp91HmgQ0HOPjgtIuI1TdvOIrjCzb5
RebR6BShfL9vmQMLf26HiHFk4h6q4HOFX4xLLHbw6cxjb5HuquYdTrDKjDw71dsz
8F7N3ahDevoZi1GQvORmE7Ob/hCu1Pu+z/7FvFA4cSLTtUnIUyaLWVgbbOqBDfy6
sjcas7w1oefk5/FWu21MpEgY9KjAUSA8Y4eDrXsHa/37475GBrn3W1wyYHTCNWOv
uyjLAgdntyKQAl2ngvTEu9D4ZRmhXIu/oO1mwQIV3pVj9jZa71o/1cFsH8eRhI9p
Sw4qEktmYvAlNsOxF5G3B0hO1D2tCYx4e/a0UWBfgQKBgQDnNjUkniLCWyhzGTfx
5N2DgAGgF4Qtprjv7B5xr+o+c3FX/FL/VsaR6VTMmWudJ4WbBZEx8QEU9lScsXtU
ogqFo2waoeu1BQvtLvQR6KhEgSRpi/c3WgQXMsR5UG+Pw2JHQ7qo3+VEDcBdTvv7
I6neXQ9jZKBjBWS9KaozZeEyYQKBgQDGykLPCPVFJ1NojOYxWDserPrLKlFJzAdX
EI25B/ESoeNLyGsa25YPX+6v6h6f+yYJAjdoOduZM4dkjTn3AM2o6UxS86J+FuBA
7hg2JmnBi3tX6LwjmKPZNt7u7lEULeH79Hqt0fKpM7W/XIc9ErJOjT3n6iZNGZyD
ybspoGGX1QKBgD8DSgZ5xpVbjLGZrOKS8j/1cfv0jMR4TKyumDl5rQhqI/jLvr7y
Iln/0mmUYnzJGaN/J+wJd7cDz1mJEUimhOGZAUxc1sVV48M3abM7yigpXggZ6j0+
niDIaD17y3vNzwoHDmcZ5fzfFo8XiJsQRCpjCF+ZPBDglmzrXwR0/qPhAoGATBno
Q5v5UXUBoFe4VBGj6FVuWVKk9exuruz+ZGRe7LQe8McUAZ8orlAabyvgd3xNDkvT
7EmiAN9SKLNMCnw7Pzu45VSx0zVsuk6r5CcGe3qrSHcndzUbHK+93phLX79E8RCh
2mMyU4YhQNXqS/4ZVqsJlPv1l7SDT4xt4zyrv9UCgYEA2vbkcbVcyZYCkIkNw4mI
rx0JwIy/CvRwwURqDBzIeTpg2bvKJ87sjTdfKfIwTU/n8ABsENieXzz+KPBpEUep
JlZJNfMsoPmRdYq5YEqDUo8mv9gin+1Q7QNJWth5FcugARaYzd3u28q/BzuNX/Nc
3DWaHY+kyL/iPbSF/DqMOJk=
-----END PRIVATE KEY-----
</key>
  • 忽略服务器推送的redirect-gateway指令

OpenVPN服务器经常会被配置成向客户端推送redirect-gateway指令,使客户端将缺省网关设置为OpenVPN服务器端的IP地址.但有时我们不想将客户端系统的缺省网关设置为OpenVPN对端的IP地址,而只想让目的地址为服务器端网段的报文走VPN隧道.这时,我们可以在客户端配置文件中加入route-nopull参数,并配置服务器端网段的路由

#在客户端配置文件中加入以下命令忽略redirect-gateway指令
route-nopull #忽略服务器推送的redirect-gateway指令用route指定路由

#在客户端手动指定路由访问内网
route 10.8.0.0 255.255.255.0 vpn_gateway #指定路由
route 192.168.50.0 255.255.255.0 vpn_gateway #指定路由

启动OpenVPN客户端软件

  • 双击安装好后的OpenVPN软件,然后右键点击连接.连接成功后,在托任务栏位置的OpenVPN图标会变绿色,则说明OpenVPN已经连接成功
  • OpenVPN会分配一个IP地址给客户端,客户端会使用该虚拟网络IP地址与服务端进行通信.

QQ截图20200825163507.png

OpenVPN客户端访问内网

在OpenVPN服务端开启内核转发

  • 无论用哪种方式访问内部网络,都必须开启内核转发
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

添加路由规则方式访问内部网络

在内网主机上添加一条路由规则,让内网主机有回到OpenVPN客户端的路由.如果不添加,那内网主机只能接受到来自客户端的包,但是没法把响应的包传回去.

  • 弊端:如果有成白上千台主机时,每一台主机都要添加路由规则,这样任务量是比较大的.
route add -net 10.8.0.0/24 gw 172.16.1.41

添加防火墙方式访问内部网络

在服务端开启防火墙,放行openvpn服务,并且开启masquerade.

  • 优点:只需在OpenVPN服务端配置防火墙规则,内部网络主机无需配置.
systemctl start firewalld
firewall-cmd --add-masquerade --permanent
firewall-cmd --add-service=openvpn --permanent
firewall-cmd --reload

双重验证登录

修改server端配置

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

  • 在配置文件/etc/openvpn/server.conf中添加以下配置
port 1194 #端口
proto udp #协议
dev tun #采用路由隧道模式tun
ca ca.crt #ca证书文件位置
cert server.crt #服务端公钥名称
key server.key #服务端私钥名称
dh dh.pem #交换证书
server 10.8.0.0 255.255.255.0 #给客户端分配地址池,注意:不能和VPN服务器内网网段有相同
push "route 172.16.1.0 255.255.255.0" #允许客户端访问内网172.16.1.0网段
ifconfig-pool-persist ipp.txt #地址池记录文件位置
keepalive 10 120 #存活时间,10秒ping一次,120 如未收到响应则视为断线
max-clients 100 #最多允许100个客户端连接
status openvpn-status.log #日志记录位置
verb 3 #openvpn版本
client-to-client #客户端与客户端之间支持通信log /var/log/openvpn.log #openvpn日志记录位置
persist-key #通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys.
persist-tun #检测超时后,重新启动VPN,一直保持tun是linkup的.否则网络会先linkdown然后再linkup
duplicate-cn

#新增内容
script-security 3              #允许使用自定义脚本
auth-user-pass-verify /etc/openvpn/check.sh via-env
username-as-common-name         #用户密码登陆方式验证

添加脚本

vi /etc/openvpn/check.sh

#!/bin/sh
###########################################################
PASSFILE="/etc/openvpn/openvpnfile"
LOG_FILE="/var/log/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

#赋予脚本执行权限
chmod +x /etc/openvpn/check.sh

编写用户密码文件

cat >> /etc/openvpn/openvpnfile << EOF
1997sty 123456
1997sty2 123456
EOF

重启openvpn服务

systemctl restart openvpn@server.service

修改客户端配置

  • 在安装目录下config目录下的client.ovpn文件中添加如下配置
remote 10.0.0.5 1194 #openvpn服务器IP地址端口号
nobind #不绑定本地特定的端口号
proto udp #使用udp协议传输数据
dev tun #使用tun隧道传输协议
client #指定当前VPN是客户端
resolv-retry infinite #断线自动重新连接,在网络不稳定的情况下非常有用
ca ca.crt #指定CA证书的文件路径
cert client.crt #指定当前客户端的证书文件路径
key client.key #指定当前客户端的私钥文件路径
verb 3 #指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
persist-key #通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-tun #检测超时后,重新启动VPN,一直保持tun是linkup的.否则网络会先linkdown然后再linkup

auth-user-pass #使用密码认证
  • 然后重启OpenVPN客户端软件,再次使用就会跳出用户登录窗口了

QQ截图20200825165928.png