Centos7 部署OpenVpn 证书和密码双重认证

openvpn配置  

一、生成证书

  • 安装证书生成工具
yum -y install easy-rsa  
  • 创建证书环境目录
mkdir -p /opt/easy-rsa  
cp -a /usr/share/easy-rsa/3.0.8/* /opt/easy-rsa/  
cp -a /usr/share/doc/easy-rsa-3.0.8/vars.example /opt/easy-rsa/vars  
  • 修改vars配置文件,取消下面配置的注释
vi /opt/easy-rsa/vars  
set_var EASYRSA_DN      "cn_only"  
set_var EASYRSA_REQ_COUNTRY     "CN"  
set_var EASYRSA_REQ_PROVINCE    "GuangDong"  
set_var EASYRSA_REQ_CITY        "GuangZhou"  
set_var EASYRSA_REQ_ORG         "IT"  
set_var EASYRSA_REQ_EMAIL       "IT@qq.com"  
set_var EASYRSA_NS_SUPPORT      "yes"  
  • 初始化,创建pki目录用于存储证书(以下都在/opt/easy-rsa目录下操作)
cd /opt/easy-rsa/  
./easyrsa init-pki

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars  
init-pki complete; you may now create a CA or requests.  
Your newly created PKI dir is: /opt/easy-rsa/pki  
  • 创建根证书,根证书用于ca对之后生成的server和client证书签名时使用
./easyrsa build-ca

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

Enter New CA Key Passphrase: 输入密码  
Re-Enter New CA Key Passphrase: 输入密码  
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:  
/opt/easy-rsa/pki/ca.crt
  • 创建server端证书和密钥文件(./easyrsa gen-req server nopass表示不加密密钥文件,生成过程中直接默认回车)
./easyrsa gen-req server # 我这里使用密码加密

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars  
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017  
Generating a 2048 bit RSA private key  
........+++
.......+++
writing new private key to '/opt/easy-rsa/pki/easy-rsa-31712.0vvQUI/tmp.UMfp6y'  
Enter PEM pass phrase:输入密码  
Verifying - Enter PEM pass phrase:输入密码  
-----
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) [server]:

Keypair and certificate request completed. Your files are:  
req: /opt/easy-rsa/pki/reqs/server.req  
key: /opt/easy-rsa/pki/private/server.key  
  • 给server端证书签名
./easyrsa sign server server

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


You are about to sign the following certificate.  
Please check over the details shown below for accuracy. Note that this request  
has not been cryptographically verified. Please be sure it came from a trusted  
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 825 days:

subject=  
    commonName                = server


Type the word 'yes' to continue, or any other input to abort.  
  Confirm request details: yes
Using configuration from /opt/easy-rsa/pki/easy-rsa-31792.n6EWQg/tmp.9BgK2v  
Enter pass phrase for /opt/easy-rsa/pki/private/ca.key:  
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 Aug 13 10:39:48 2025 GMT (825 days)

Write out database with 1 new entries  
Data Base Updated

Certificate created at: /opt/easy-rsa/pki/issued/server.crt
  • 创建Diffie-Hellman文件,密钥交换时的Diffie-Hellman算法
./easyrsa gen-dh

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars  
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017  
Generating DH parameters, 2048 bit long safe prime, generator 2  
This is going to take a long time  
.+...+...........................+...............................................................+.......................................++*++*

DH parameters of size 2048 created at /opt/easy-rsa/pki/dh.pem
  • 创建client端证书和密钥文件(nopass表示不加密密钥文件,生成过程中直接默认回车)
./easyrsa gen-req client

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars  
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017  
Generating a 2048 bit RSA private key  
...................+++
.........................................+++
writing new private key to '/opt/easy-rsa/pki/easy-rsa-31915.upgsBV/tmp.7qt1m8'  
Enter PEM pass phrase:输入密码  
Verifying - Enter PEM pass phrase: 输入密码  
-----
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) [client]:

Keypair and certificate request completed. Your files are:  
req: /opt/easy-rsa/pki/reqs/client.req  
key: /opt/easy-rsa/pki/private/client.key  
  • 给client端证书签名
./easyrsa sign client client

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


You are about to sign the following certificate.  
Please check over the details shown below for accuracy. Note that this request  
has not been cryptographically verified. Please be sure it came from a trusted  
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a client certificate for 825 days:

subject=  
    commonName                = client


Type the word 'yes' to continue, or any other input to abort.  
  Confirm request details: yes
Using configuration from /opt/easy-rsa/pki/easy-rsa-31948.N19ZEm/tmp.aSAVMl  
Enter pass phrase for /opt/easy-rsa/pki/private/ca.key:  
Check that the request matches the signature  
Signature ok  
The Subject's Distinguished Name is as follows  
commonName            :ASN.1 12:'client'  
Certificate is to be certified until Aug 13 10:44:24 2025 GMT (825 days)

Write out database with 1 new entries  
Data Base Updated

Certificate created at: /opt/easy-rsa/pki/issued/client.crt

二、OpenVPN服务端部署

  • 安装openvpn
yum install -y openvpn  
  • 创建TLS认证密钥
openvpn --genkey --secret /etc/openvpn/ta.key  
  • 创建新的配置文件/etc/openvpn/server.conf
#监听本机端口
port 1194  
#指定采用的传输协议,可选tcp或udp
proto tcp  
#指定创建的通信隧道类型,可选tun或tap
dev tun  
#指定CA证书的文件路径
ca ca.crt  
#指定服务器端的证书文件路径
cert server.crt  
#指定服务器端的私钥文件路径
key server.key  
#指定迪菲赫尔曼参数的文件路径,也就是交换证书
dh dh.pem  
#给客户端分配地址池,注意:不能和VPN服务器内网网段有相同
server 10.8.0.0 255.255.255.0  
#允许客户端访问内网网段
push "route 192.168.240.0 255.255.255.0"  
#服务器自动给客户端分配IP后,客户端下次连接时,仍然采用上次的IP地址"第一次分配的IP保存在ipp.txt中,下一次分配其中保存的IP"
ifconfig-pool-persist ipp.txt  
#存活时间,10秒ping一次,120如未收到响应则视为断线
keepalive 10 120  
#最多允许100个客户端连接
max-clients 100  
#日志记录位置
status  /var/log/openvpn/openvpn-status.log  
#openvpn版本
verb 3  
#允许客户端与客户端相连接,默认情况下客户端只能与服务器相连接
client-to-client  
#openvpn日志记录位置
log /var/log/openvpn.log  
#通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-key  
#检测超时后,重新启动VPN,一直保持tun是linkup的.否则网络会先linkdown然后再linkup
persist-tun  
#开启TLS-auth,使用ta.key防御攻击.服务器端的第二个参数值为0,客户端的为1
tls-auth /etc/openvpn/ta.key 0  
  • 拷贝证书到openvpn主配置文件目录下
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 start openvpn@server  
Broadcast message from root@tx-office-centos7-240-58 (Thu 2023-05-11 19:01:48 CST):

Password entry required for 'Enter Private Key Password:' (PID 32222).  
Please enter password with the systemd-tty-ask-password-agent tool!  加密的会有这个错误

systemctl status  openvpn@server

# 如果出现以上错误先执行
systemd-tty-ask-password-agent  
Enter Private Key Password: ******  
# 再启动即可
systemctl start openvpn@server  
  • OpenVPN客户端访问内网
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

sysctl -p  
net.ipv4.ip_forward = 1  
  • 修改防火墙配置
*nat
:PREROUTING ACCEPT [44:4087]
:INPUT ACCEPT [16:2408]
:OUTPUT ACCEPT [1:78]
:POSTROUTING ACCEPT [1:78]
-A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE
COMMIT  

客户端配置

  • 获取刚生成客户端证书,放在客户端安装目录下
/opt/easy-rsa/pki/ca.crt 
/opt/easy-rsa/pki/issued/client.crt
/opt/easy-rsa/pki/private/client.key
/etc/openvpn/ta.key
  • 客户端配置(电脑端)
#指定当前VPN是客户端
client  
#使用tun隧道传输协议
dev tun  
#使用udp协议传输数据
proto tcp  
#openvpn服务器IP地址端口号
remote 10.5.10.202 1194  
#断线自动重新连接,在网络不稳定的情况下非常有用
resolv-retry infinite  
#不绑定本地特定的端口号
nobind  
#指定CA证书的文件路径
ca ca.crt  
#指定当前客户端的证书文件路径
cert client.crt  
#指定当前客户端的私钥文件路径
key client.key  
#指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
verb 3  
#通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-key  
#检测超时后,重新启动VPN,一直保持tun是linkup的。否则网络会先linkdown然后再linkup
persist-tun  
# 使用ta.key防御攻击。服务器端的第二个参数值为0,客户端的为1,IOS可以不开此配置
# tls-auth ta.key 1
  • 客户端配置(ios.mac)端修改三个配置即可
#指定CA证书的文件路径
<ca>  
...
</ca>

#指定当前客户端的证书文件路径
<cert>  
</cert>  
#指定当前客户端的私钥文件路径
<key>  
</key>  
  • 打开客户连接发现已经可以连接上了

证书+密码认证

  • 修改OpenVPN服务端配置文件
#在最后增加以下配置
[root@openvpn ~]# vi /etc/openvpn/server.conf
#允许使用自定义脚本
script-security 3  
#脚本路径
auth-user-pass-verify /etc/openvpn/check.sh via-env  
#用户密码登陆方式验证
username-as-common-name  

加上client-cert-not-required则代表只使用用户名密码方式验证登录,如果不加,则代表需要证书和用户名密码双重验证登录,部分版本已经修改为verify-client-cert none

  • 添加脚本/etc/openvpn/check.sh
vi  /etc/openvpn/check.sh  
#!/bin/sh
###########################################################
PASSFILE="/etc/openvpn/openvpnpass"  
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  
  • 增加用户密码文件
vi /etc/openvpn/openvpnpass  
leoiceo leoiceo  
  • 重启客户端
systemctl restart openvpn@server  
  • 修改客户端安装路径config目录下的client.opvn配置文件,在最后增加
auth-user-pass