0. 当前 网络拓扑 环境图示(VMware 环境)
image-20221017105326630.png
1. 配置并生成 证书、公私钥和算法等文件
1.1 安装软件包
# 安装 软件包(前提配置好Base和epel源,这里不做赘述)
yum install openvpn easy-rsa -y
1.2 创建证书等文件生成目录
# 创建一个生成证书等文件的 目录
mkdir -p /opt/easy-rsa
cp -a /usr/share/easy-rsa/3.0.8/* /opt/easy-rsa/
# 创建日志所在目录
mkdir -p /var/log/openvpn
1.3 编写生成ca证书的变量和内容等文件
# 创建ca证书使用的变量和内容,充当权威机构
# cp /usr/share/doc/easy-rsa-3.0.8/vars.example /opt/easy-rsa/vars
cat >/opt/easy-rsa/vars<<'EOF'
if [ -z "$EASYRSA_CALLER" ]; then
echo "You appear to be sourcing an Easy-RSA 'vars' file." >&2
echo "This is no longer necessary and is disallowed. See the section called" >&2
echo "'How to use this file' near the top comments for more details." >&2
return 1
fi
set_var EASYRSA_DN "cn_only"
set_var EASYRSA_REQ_COUNTRY "CN"
set_var EASYRSA_REQ_PROVINCE "Beijing"
set_var EASYRSA_REQ_CITY "Beijing"
set_var EASYRSA_REQ_ORG "域名"
set_var EASYRSA_REQ_EMAIL "邮箱地址"
set_var EASYRSA_NS_SUPPORT "yes"
EOF
1.4 创建 ca 证书
# 初始化,当前目录创建 pki 目录,用于存放证书,创建完位置:/opt/easy-rsa/pki
cd /opt/easy-rsa
./easyrsa init-pki
# 创建根证书,会提示设置密码,用于CA对 之后生成的 server 和 client 证书签名时使用
# 设置密码 & 输入域名
# 创建完证书位置:/opt/easy-rsa/pki/ca.crt
./easyrsa build-ca
1.5 创建 server 端的证书和私钥
# 创建请求文件及服务端私钥, nopass 表示不加密私钥文件,其他可默认
# 创建完请求文件位置:/opt/easy-rsa/pki/reqs/server.req
# 创建完私钥位置:/opt/easy-rsa/pki/private/server.key
./easyrsa gen-req server nopass
# 根据 req 文件生成 CA 证书文件
# 输入 yes 和 CA 证书的密码
# 创建完server端证书位置:/opt/easy-rsa/pki/issued/server.crt
./easyrsa sign server server
1.6 创建 client 端证书和私钥(跳过)
# 创建client端证书请求文件和私钥文件
# 创建完请求文件位置:/opt/easy-rsa/pki/reqs/client.req
# 创建完私钥位置:/opt/easy-rsa/pki/private/client.key
# ./easyrsa gen-req client nopass
./easyrsa gen-req zs nopass
# 给client端证书签名,首先对一些信息进行确认(输入yes),然后输入创建CA根证书时设置的密码,创建client端的证书
# 创建完client端证书位置:/opt/easy-rsa/pki/issued/client.crt
# ./easyrsa sign client client
./easyrsa sign client zs
1.7 创建 dh-pem 算法文件
# 创建 Diffie-Hellman 文件,密钥交换时的 Diffie-Hellman 算法
# 仅创建 1 次
# 创建完存放位置:/opt/easy-rsa/pki/dh.pem
./easyrsa gen-dh
1.8 创建 ta.key
# 创建 ta.key
# 加强认证方式,防攻击。如果配置文件中启用此项(默认是启用的)
openvpn --genkey --secret ta.key
2. 配置 openvpn 服务端
2.1 openvpn 目录结构说明
OpenVPN 软件目录结构 |
说明 |
/etc/openvpn |
1. openvpn配置文件目录<br />2. client 客户端配置文件的目录,配置文件,证书,私钥<br />3. serve服务端配置文件目录,配置文件,证书,私钥,算法文件 |
/usr/sbin/openvpn |
openvpn命令目录 |
2.2 复制服务端的 证书等文件 至 配置目录下
# 01. 将ca证书文件复制到 配置目录下
cp /opt/easy-rsa/pki/ca.crt /etc/openvpn/server
# 02. 将服务端证书复制到 配置目录下
cp /opt/easy-rsa/pki/issued/server.crt /etc/openvpn/server
# 03. 将服务端私钥文件复制到 配置目录下
cp /opt/easy-rsa/pki/private/server.key /etc/openvpn/server
# 04. 将算法文件复制到 配置目录下
cp /opt/easy-rsa/pki/dh.pem /etc/openvpn/server
# 05. 将 ta.key 复制到 配置目录下
cp /opt/easy-rsa/ta.key /etc/openvpn/server/
2.3 编写服务端配置文件
cat >/etc/openvpn/server/server.conf <<'EOF'
port 1194
# 可以使用TCP或者UDP协议
proto udp
dev tun
ca server/ca.crt
cert server/server.crt
key server/server.key
dh server/dh.pem
server 10.8.0.0 255.255.255.0
push "route 172.16.1.0 255.255.255.0"
#ifconfig-pool-persist ipp.txt
keepalive 10 120
max-clients 100
status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 3
client-to-client
persist-key
persist-tun
duplicate-cn
# 允许使用自定义脚本
script-security 3
# 指定认证脚本
auth-user-pass-verify /etc/openvpn/check.sh via-env
# 用户密码登录方式验证
username-as-common-name
tls-auth /etc/openvpn/server/ta.key 0
cipher AES-256-CBC
compress lz4-v2
push "compress lz4-v2"
EOF
2.4 编写用户检测脚本 并 修改权限
# 01. 编写脚本
cat >/etc/openvpn/check.sh <<'EOF'
#!/bin/bash
#Desc: openvpn用户认证检测脚本
#Author: yunxi
###########################################################
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
EOF
# 02. 修改脚本权限
chmod 700 /etc/openvpn/check.sh
2.5 创建认证文件 并 修改权限
# 创建认证文件
touch /etc/openvpn/openvpnfile
# 修改认证文件权限
chmod 600 /etc/openvpn/openvpnfile
2.6 修改 openvpn 使用 systemd 启动的配置文件
cat >/usr/lib/systemd/system/openvpn@.service <<'EOF'
[Unit]
Description=OpenVPN Robust And Highly Flexible Tunneling Application On %I
After=network.target
[Service]
Type=notify
PrivateTmp=true
ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/ --config %i/%i.conf
[Install]
WantedBy=multi-user.target
EOF
# 重新加载 配置文件
systemctl daemon-reload
2.7 服务端最终 配置文件所在目录结构
cd /etc/openvpn
# 目录结构如下
[root@openvpn openvpn]# pwd
/etc/openvpn
[root@openvpn openvpn]# tree -F
.
├── check.sh*
├── client/
├── openvpnfile
└── server/
├── ca.crt
├── dh.pem
├── server.conf
├── server.crt
├── server.key
└── ta.key
2 directories, 8 files
3. 启动服务
3.1 启动 openvpn
systemctl enable --now openvpn@server
3.2 检查服务
ss -lntup|grep 1194
ps -ef|grep openvpn
ip a s tun0
# 服务端日志
/var/log/openvpn.log
4. 创建 openvpn 用户脚本
# 创建保存脚本的目录
mkdir -p /server/scripts
# 编写脚本
vim /server/scripts/create_vpn_user.sh
#!/bin/bash
#Author: yunxi
#Time: 2022-10-14
#Version: v1.0
#Description: 创建 openvpn 账号,生成对应证书文件
dir="/opt/easy-rsa"
ca_dir="/server/openvpn"
user_file="/etc/openvpn/openvpnfile"
parameter_num=$#
user=$1
pass=$2
vpn_server_ip=10.0.0.10
port=1194
function Usage(){
if [ ! $parameter_num -eq 2 ];then
echo "The Script Usage: ./$0 新建账号名称 新建账号密码"
exit 1
fi
}
function user_is_exist(){
if [ ! -e $user_file ]; then
touch ${user_file}
chmod 600 ${user_file}
fi
grep -w $user $user_file &>/dev/null
if [ $? -eq 0 ];then
echo "用户 $user 已经存在"
exit 1
fi
}
function create_ca(){
# 创建 客户端证书目录
mkdir -p ${ca_dir}/$user
if [ -d $dir ];then
cd $dir
echo "创建客户端证书请求文件(输入对应的账户名)"
./easyrsa gen-req $user nopass
[ $? -eq 0 ] && echo "客户端证书请求文件创建成功!" || echo "客户端证书请求文件创建失败!"
echo "创建客户证书(确认 并 输入证书密码)"
./easyrsa sign client $user
[ $? -eq 0 ] && echo "客户端证书创建成功!" || echo "客户端证书创建失败!"
cp $dir/pki/issued/${user}.crt ${ca_dir}/$user
cp $dir/pki/private/${user}.key ${ca_dir}/$user
cp $dir/pki/ca.crt ${ca_dir}/$user
cp $dir/ta.key ${ca_dir}/$user
fi
}
function modify_user_file(){
echo "$user $pass" >> ${user_file}
echo "结果如下:"
tail -1 ${user_file}
}
function client_cfg(){
cat > ${ca_dir}/$user/${user}.ovpn <<EOF
client
dev tun
proto udp
# 服务端IP 和 端口
remote ${vpn_server_ip} ${port}
resolv-retry infinite
nobind
ca ca.crt
cert ${user}.crt
key ${user}.key
verb 3
persist-key
auth-user-pass
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
compress lz4-v2
EOF
cat >${ca_dir}/$user/readme.txt <<EOF
1. VPN账号: ${user}, 密码是: ${pass}
2. 将除 readme 文件外的其他文件,全部存放至openvpn客户端的config目录下即可
3. 打开openvpn客户端,点击连接,使用上面账号和密码登录连接即可
EOF
# 打包文件
cd ${ca_dir}
zip -rq ${user}.zip ${user} &>/dev/null
}
function send_email(){
read -p '请输入您的邮箱地址:' email
echo 'VPN账号相关信息在附件中,请详细阅读 readme 文档' | mail -a ${ca_dir}/${user}.zip -s 'VPN账号信息' ${email}
[ $? -eq 0 ] && echo "邮件已发送成功!" || echo "邮件发送失败!"
}
function main(){
# 检测 参数是否正确
Usage
# 检查用户是否已经存在
user_is_exist
# 创建证书
create_ca
# 修改账号文件
modify_user_file
# 生成客户端配置文件
client_cfg
# 发邮件(前提配置好邮箱)
send_email
}
main
# 脚本使用注意:需要传参
# bash /server/scripts/create_vpn_user.sh 账号 口令
5. 客户端配置(Windows 为例)
5.1 安装 openvpn 客户端
略
5.2 获取客户端配置文件
创建 openvpn 账号时会生成 配置文件
5.3 获取用户私钥,证书等文件
创建openvpn账号时会提示保存目录,下载并保存在 本地配置目录即可
5.4 客户端 配置文件目录 结构
image-20221017113036543.png
5.5 客户端 可建立连接,并进行测试
# 显示如下图标,表示 登录openvpn 成功,也可以查看对应日志
image-20221017105503842.png
# 测试结果
[C:\~]$ ping 172.16.1.10
正在 Ping 172.16.1.10 具有 32 字节的数据:
来自 172.16.1.10 的回复: 字节=32 时间<1ms TTL=64
来自 172.16.1.10 的回复: 字节=32 时间=1ms TTL=64
来自 172.16.1.10 的回复: 字节=32 时间=1ms TTL=64
来自 172.16.1.10 的回复: 字节=32 时间<1ms TTL=64
172.16.1.10 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 0ms,最长 = 1ms,平均 = 0ms
6. 附件(额外内容)
6.1 邮件服务配置
# 配置 postfix 服务文件
cat >>/etc/mail.rc<<EOF
set from=发送邮件的账号
set smtp=邮件服务器
set smtp-auth-user=发送者账号
set smtp-auth-password=授权码
set smtp-auth=login
EOF
# 重启postfix
systemctl restart postfix.service
6.2 测试
mail -s '邮件主题' 对方的邮箱 < 文件(邮件内容)
cat file | mail -s '主题' 对方邮箱
mail -a file -s '主题' 对方邮箱 < 文件(邮件内容)