一、介绍
1、定义
OpenVPN是一个用于创建虚拟专用网络加密通道的软件包
2、原理
OpenVPN的技术核心是虚拟网卡,其次是SSL协议实现
虚拟网卡是使用网络底层编程技术实现的一个驱动软件。安装此类程序后主机上会增加一个非真实的网卡,并可以像其它网卡一样进行配置。服务程序可以在应用层打开虚拟网卡,如果应用软件(如网络浏览器)向虚拟网卡发送数据,则服务程序可以读取到该数据。如果服务程序写合适的数据到虚拟网卡,应用软件也可以接收得到。虚拟网卡在很多的操作系统中都有相应的实现,这也是OpenVPN能够跨平台使用的一个重要原因。
在OpenVPN中,如果用户访问一个远程的虚拟地址(属于虚拟网卡配用的地址系列,区别于真实地址),则操作系统会通过路由机制将数据包(TUN模式)或数据帧(TAP模式)发送到虚拟网卡上,服务程序接收该数据并进行相应的处理后,会通过SOCKET从外网上发送出去。这完成了一个单向传输的过程,反之亦然。当远程服务程序通过SOCKET从外网上接收到数据,并进行相应的处理后,又会发送回给虚拟网卡,则该应用软件就可以接收到。
3、加密和身份验证
(1)加密
OpenVPN使用OpenSSL库来加密数据与控制信息。这意味着,它能够使用任何OpenSSL支持的算法。它提供了可选的数据包HMAC功能以提高连接的安全性。此外,OpenSSL的硬件加速也能提高它的性能。2.3.0以后版本引入PolarSSL。
(2)身份验证
OpenVPN提供了多种身份验证方式,用以确认连接双方的身份,包括:
① 预享私钥
② 第三方证书
③ 用户名/密码组合
预享密钥最为简单,但同时它只能用于创建点对点的VPN;基于PKI的第三方证书提供了最完善的功能,但是需要额外维护一个PKI证书系统。OpenVPN2.0后引入了用户名/口令组合的身份验证方式,它可以省略客户端证书,但是仍需要一份服务器证书用作加密。
二、在linux上搭建openvpn
1、安装openvpn 和easy-rsa(该包用来制作ca证书)
(1)安装epel 仓库源
yum install epel-release -y
(2)安装openvpn
[root@localhost ~]# yum -y install openvpn
(3)在github 上,下载最新的easy-rsa
① https://github.com/OpenVPN/easy-rsa 下载包
wget https://gitcode.net/mirrors/OpenVPN/easy-rsa/-/archive/master/easy-rsa-master.tar.gz
② 解压缩
[root@localhost ~]# mkdir openvpn
[root@localhost openvpn]# tar -xzvf easy-rsa-master.tar.gz
[root@localhost openvpn]# mv easy-rsa-master easy-rsa
2、配置/etc/openvpn/ 目录
(1)创建目录,并复制easy-rsa 目录
[root@localhost ~]# mkdir -p /etc/openvpn/
[root@localhost openvpn]# cp -Rp easy-rsa /etc/openvpn/
(2)配置,编辑vars文件,根据自己环境配置
[root@localhost test]# cd /etc/openvpn/easy-rsa/easyrsa3
[root@localhost easyrsa3]# cp vars.example vars
[root@localhost easy-rsa3]# vim vars (将下面6行写入文件)
set_var EASYRSA_REQ_COUNTRY "CN"
set_var EASYRSA_REQ_PROVINCE "Beijing"
set_var EASYRSA_REQ_CITY "Beijing"
set_var EASYRSA_REQ_ORG "username"
set_var EASYRSA_REQ_EMAIL "username@163.com"
set_var EASYRSA_REQ_OU "My OpenVPN"
3、创建服务端证书及key
进入/etc/openvpn/easy-rsa/easyrsa3/
① 初始化
[root@localhost ~]# cd /etc/openvpn/easy-rsa/easyrsa3/
[root@localhost easyrsa3]# ./easyrsa init-pki
Note: using Easy-RSA configuration from: ./vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/easy-rsa/easyrsa3/pki
② 创建根证书
[root@localhost easyrsa3]# ./easyrsa build-ca
#如果不想设置密码后面加上 nopass
[root@localhost easyrsa3]# ./easyrsa build-ca nopass
注意:在上述部分需要输入PEM密码 PEM pass phrase,输入两次,此密码必须记住,不然以后不能为证书签名。还需要输入common name 通用名,这个你自己随便设置个独一无二的。
③ 创建服务器端证书
[root@localhost easyrsa3]# ./easyrsa gen-req server nopass
该过程中需要输入common name,随意但是不要跟之前的根证书的一样
④ 签约服务端证书
[root@localhost easyrsa3]# ./easyrsa sign server server
该命令中.需要你确认生成,要输入yes,还需要你提供我们当时创建CA时候的密码。如果你忘记了密码,那你就重头开始再来一次吧
⑤ 创建Diffie-Hellman,确保key穿越不安全网络的命令
[root@localhost easyrsa3]# ./easyrsa gen-dh
4、创建客户端证书
① 进入root目录新建client文件夹,文件夹可随意命名,然后拷贝前面解压得到的easy-ras文件夹到client文件夹,进入下列目录
[root@localhost ~]# mkdir client
[root@localhost ~]# cp /etc/openvpn/easy-rsa client -Rp
[root@localhost ~]# cd client/easy-rsa/easyrsa3/
② 初始化
[root@localhost easyrsa3]# ./easyrsa init-pki //需输入yes 确定
③ 创建客户端key及生成证书(记住生成是自己客户端登录输入的密码)
[root@localhost easyrsa3]# ./easyrsa gen-req client nopass #名字自己定义,要设置密码就去掉nopass
④ 将得到的用户req导入然后签约证书
a. 进入到/etc/openvpn/easy-rsa/easyrsa3/
[root@localhost easyrsa3]# cd /etc/openvpn/easy-rsa/easyrsa3/
b. 导入req
[root@localhost easyrsa3]# ./easyrsa import-req /root/client/easy-rsa/easyrsa3/pki/reqs/username.req client_username
c. 签约证书
[root@localhost easyrsa3]# ./easyrsa sign client client_username
注:这里生成client所以必须为client,client_username要与步骤b导入名字一致
上面签约证书跟server类似,就不截图了,但是期间还是要输入CA的密码
5、把服务器端必要文件放到etc/openvpn/ 目录下
ca的证书、服务端的证书、秘钥
[root@localhost ~]# cp /etc/openvpn/easy-rsa/easyrsa3/pki/ca.crt /etc/openvpn/
[root@localhost ~]# cp /etc/openvpn/easy-rsa/easyrsa3/pki/private/server.key /etc/openvpn/
[root@localhost ~]# cp /etc/openvpn/easy-rsa/easyrsa3/pki/issued/server.crt /etc/openvpn/
[root@localhost ~]# cp /etc/openvpn/easy-rsa/easyrsa3/pki/dh.pem /etc/openvpn/
6、把客户端必要文件放到root/client/ 目录下
客户端的证书、秘钥&如果想用key模式登陆,将其复制进客户端,并需改登陆模式即可,本文使用用户名密码登陆
[root@localhost ~]# cp /etc/openvpn/easy-rsa/easyrsa3/pki/ca.crt /root/client/
[root@localhost ~]# cp /etc/openvpn/easy-rsa/easyrsa3/pki/issued/client_name.crt /root/client/
[root@localhost ~]# cp /root/client/easy-rsa/easyrsa3/pki/private/client_name.key /root/client
查看客户端ca文件,用于复制到客户端配置文件
7、为服务端编写配置文件
(1)当你安装好了openvpn时候,他会提供一个server配置的文件例子,在/usr/share/doc/openvpn/sample/sample-config-files/ 下会有一个server.conf文件,我们将这个文件复制到/etc/openvpn
[root@localhost ~]# rpm -ql openvpn |grep server.conf
[root@localhost ~]# cp /usr/share/doc/openvpn-2.4.11/sample/sample-config-files/server.conf /etc/openvpn/
(2)修改配置文件
[root@localhost ~]# vim /etc/openvpn/server.conf
[root@localhost ~]# grep '^[^#|;]' /etc/openvpn/server.conf 修改的地方如下:
A、key登陆模式配置文件,需要复制key,cert
local 0.0.0.0
port 1194
proto tcp
dev tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key # This file should be kept secret
dh /etc/openvpn/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
client-to-client
keepalive 10 120
cipher AES-256-GCM
comp-lzo
max-clients 100
user openvpn
group openvpn
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log /var/log/openvpn/openvpn.log
verb 3
B、用户名密码登陆模式配置文件(这种方式好像行不通)
local 0.0.0.0
port 1194
proto tcp
dev tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key # This file should be kept secret
dh /etc/openvpn/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
client-to-client
keepalive 10 120
cipher AES-256-GCM
comp-lzo
max-clients 100
user openvpn
group openvpn
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log /var/log/openvpn/openvpn.log
verb 3
# 该指令提供对OpenVPN使用外部程序和脚本的策略级别的控制。较低的 水平 值更具限制性,较高的值更宽松。级别设置
# 0- 完全不调用外部程序。
# 1- (默认)仅调用内置可执行文件,例如ifconfig,ip,route或netsh。
# 2- 允许调用内置的可执行文件和用户定义的脚本。
# 3- 允许通过环境变量将密码传递给脚本(可能不安全)。
# 特别注意如果没有这个配置项会导致服务端校验密码时无法获取到密码,导致校验失败
script-security 3
auth-user-pass-verify /etc/openvpn/checkpw.sh via-env #指定用户认证脚本
# 新加此行,使用客户提供的UserName作为Common Name
username-as-common-name
verify-client-cert none
# 加上client-cert-not-required代表只使用用户密码方式验证登录,不加则代表需要证书和用户名密码双重验证登录
client-cert-not-required
(3)配置用户文件&检查脚本
#检查脚本
[root@localhost ~]# vim /etc/openvpn/checkpw.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/pw-file"
LOG_FILE="/var/log/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
#密码文件
[root@localhost ~]# vim /etc/openvpn/pw-file
user1 passwd1
user2 passwd2
(4)配置权限
[root@localhost ~]# mkdir /var/log/openvpn
[root@localhost ~]# chown -R openvpn.openvpn /var/log/openvpn/
[root@localhost ~]# chown -R openvpn.openvpn /etc/openvpn/*
8、iptables 设置nat 规则和打开路由转发
# -o eth0 加不加都行,不过最好加上
[root@localhost ~]# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
#注意添加tun0到eth0和eth0到tun0的forward,有来有回嘛!
[root@localhost ~]# iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
[root@localhost ~]# iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT
[root@localhost ~]# vim /etc/sysctl.conf //打开路由转发
net.ipv4.ip_forward = 1
[root@localhost ~]# sysctl -p
MASQUERADE的作用:
假如当前系统用的是ADSL动态拨号方式,那么每次拨号,出口ip192.168.5.3都会改变,而且改变的幅度很大,不一定是192.168.5.3到192.168.5.5范围内的地址
这个时候如果按照现在的方式来配置iptables就会出现问题了。因为每次拨号后,服务器地址都会变化,而iptables规则内的ip是不会随着自动 变化的,每次地址变化后都必须手工修改一次iptables,把规则里边的固定ip改成新的ip。这样是非常不好用的。MASQUERADE就是针对这种 场景而设计的,他的作用是,从服务器的网卡上,自动获取当前ip地址来做NAT。
# 查看配置后的信息
[root@localhost ~]# iptables -vnL -t nat
[root@localhost ~]# iptables -vnL -t filter
9、开启openvpn 服务
[root@localhost ~]# openvpn /etc/openvpn/server.conf &
[root@localhost ~]# netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:1194 0.0.0.0:* LISTEN 14948/openvpn
三、客户端连接openvpn
1、下载openvpn客户端安装
OpenVPN - Free - download for Windows
下载安装即可
2、配置client 端配置文件,并导入
client
proto tcp
remote 服务器ip 1194
dev tun
nobind
persist-key
persist-tun
cipher AES-256-GCM
verb 3
comp-lzo
auth-user-pass
<ca>
将上文二.6中ca密码在上文中有直接复制进来,即可
</ca>
3、登陆
四、openvpn优化
1、配置路由&dns
在openvpn的主配置文件中添加路由,当客户端访问指定网段才使用vpn线路,其它时候使用本机原网络,避免不必要操作占用vpn线路流量
添加dhcp自动获得dns,可指定内网dns
push "route 10.0.0.0 255.0.0.0"
#push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 202.106.0.20"
push "dhcp-option DNS 94.140.14.14"
2、禁用压缩 comp-lzo
在服务端和客户端都将comp-lzo压缩功能去掉,性能提高了2-4倍
3、更改协议proto tcp---->proto udp
众所周知udp要比tcp快的多,更改协议与端口号不仅提速,还提高了安全性
port 21194
proto udp
4、配置一账号多人登陆
duplicate-cn
五、错误
1、No server certificate
Fri Apr 14 17:49:21 2023 WARNING: No server certificate verification method has been enabled. See http://openvpn.net/howto.html#mitm for more info.
解决在客户端文件中添加
remote-cert-tls server
2、导入文件的时候发现报错:missing external certificate
解决在客户端文件中添加
client-cert-not-required
————————————————
参考:
openvpn (用户名密码模式)_疯飙的蜗牛的博客-CSDN博客