1. 安装 OpenVPN (主节点与子节点):
apt update
apt install openvpn easy-rsa
2. 配置OpenVPN服务器 (主节点):
- 初始化 PKI 并生成 CA、服务器证书和密钥
make-cadir ~/openvpn-ca cd ~/openvpn-ca # 初始化 pki 目录 ./easyrsa init-pki # 生成ca证书 ./easyrsa build-ca # 创建连接秘钥 ./easyrsa gen-req server nopass ./easyrsa sign-req server server
- 创建 OpenVPN 服务器配置文件
(/etc/openvpn/server.conf)
# 指定服务器监听的端口号 port 1194 # 指定使用的协议(TCP 或 UDP),这里使用 TCP proto tcp # 指定使用的设备类型,tun 表示隧道设备 dev tun # 指定 CA 证书文件路径,用于验证客户端和服务器的身份 ca ca.crt # 指定服务器的证书文件路径 cert server.crt # 指定服务器的私钥文件路径 key server.key # 指定 Diffie-Hellman 参数文件路径,用于密钥交换 dh dh2048.pem # 定义 VPN 服务器的 IP 地址池和子网掩码,分配给客户端 server 10.25.0.0 255.255.192.0 # 指定客户端配置目录,用于为特定客户端设置自定义配置 client-config-dir /etc/openvpn/ccd # 推送路由到客户端,使客户端能够访问指定网段 push "route 10.25.0.0 255.255.192.0" # 设置保活机制,10 秒发送一次 ping,120 秒未收到回应则认为连接断开 keepalive 10 120 # 保持密钥在重启时不重新生成 persist-key # 保持隧道设备在重启时不关闭 persist-tun # 设置日志的详细级别,4 表示较详细的日志 verb 4 # 指定日志文件路径,日志会追加到该文件 log-append /var/log/openvpn.log
- 创建
/etc/openvpn/ccd
目录,为客户端指定固定ipmkdir /etc/openvpn/ccd # node1 文件名为 gen-req 时设置的节点的名称 vim /etc/openvpn/ccd/node1
/etc/openvpn/ccd/node1
ifconfig-push 10.25.0.3 255.255.192.0
- 复制证书和密钥到
/etc/openvpn/
cp pki/ca.crt pki/issued/server.crt pki/private/server.key /etc/openvpn/ openssl dhparam -out /etc/openvpn/dh2048.pem 2048
3. 配置 OpenVPN 客户端(主节点):
-
为每个节点生成客户端证书:
# client1 为节点配置文件名称,可修改 ./easyrsa gen-req client1 nopass ./easyrsa sign-req client client1
-
创建客户端配置文件(client1.ovpn)
client dev tun proto tcp remote <master-public-ip> 1194 resolv-retry infinite nobind persist-key persist-tun ca /etc/openvpn/client/ca.crt cert /etc/openvpn/client/client1.crt key /etc/openvpn/client/client1.key remote-cert-tls server
-
将证书和配置文件分发到客户端节点,保存到
/etc/openvpn/client
目录。
4. 启动服务端(主节点)
sudo systemctl enable openvpn@server
sudo systemctl start openvpn@server
5. 配置客户端并启动(子节点)
将
ca.crt
client1.crt
client1.key
三个文件放入/etc/openvpn/client
目录后
- 创建 systemd 服务,执行
vim /etc/systemd/system/openvpn-client@client1.service
[Unit]
Description=OpenVPN Client for %i
After=network.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
[Service]
Type=forking
ExecStart=/usr/sbin/openvpn --daemon --config /etc/openvpn/client/%i.ovpn
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
ProtectSystem=full
PrivateTmp=true
[Install]
WantedBy=multi-user.target
systemctl enable openvpn-client@client1.service
systemctl start openvpn-client@client1.service
附:自动化客户端证书创建脚本
mkClient.sh
自动创建证书并且打包为zip
bash mkClient.sh 节点名称 ca证书密码 节点IP
#!/bin/bash
# 检查是否提供了足够的参数
if [ "$#" -lt 2 ]; then
echo "用法: $0 <NODE_NAME> <CA_PASS>"
echo "示例: $0 node2 mysecretpass"
exit 1
fi
# 从参数获取变量
NODE_NAME="$1" # 节点名称
CA_PASS="$2" # CA 密钥的密码短语
NODE_IP="$3" # 节点使用ip
IP_MASK="255.255.192.0"
EASYRSA_DIR="/root/openvpn-ca" # easy-rsa 目录
MASTER_PUBLIC_IP="server_a_00026.hostidc.net" # 主服务器ip或者域名
# 切换到 easy-rsa 目录
cd "$EASYRSA_DIR" || { echo "无法进入 $EASYRSA_DIR 目录"; exit 1; }
# 1. 生成证书请求(gen-req),自动确认 'yes' 和节点名称
echo -e "$NODE_NAME" | ./easyrsa gen-req "$NODE_NAME" nopass
if [ $? -ne 0 ]; then
echo "生成证书请求失败"
exit 1
fi
# 2. 签名证书请求(sign-req),自动确认 'yes' 并提供 CA 密码
expect << EOF
spawn ./easyrsa sign-req client "$NODE_NAME"
expect "Confirm request details:"
send "yes\r"
expect "Enter pass phrase for"
send "$CA_PASS\r"
expect eof
EOF
if [ $? -ne 0 ]; then
echo "签名证书请求失败"
exit 1
fi
# 配置节点ip
mkdir -p "/etc/openvpn/ccd"
cat > "/etc/openvpn/ccd/$NODE_NAME" << EOF
ifconfig-push $NODE_IP $IP_MASK
EOF
# 重启服务
systemctl restart openvpn@server
# 生成ovpn文件
cat << EOF > "${NODE_NAME}.ovpn"
client
dev tun
proto tcp
remote ${MASTER_PUBLIC_IP} 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca /etc/openvpn/client/ca.crt
cert /etc/openvpn/client/${NODE_NAME}.crt
key /etc/openvpn/client/${NODE_NAME}.key
remote-cert-tls server
EOF
# 3. 打包证书文件和 CA 证书到 ZIP
CERT_FILES=(
"$EASYRSA_DIR/pki/reqs/$NODE_NAME.req"
"$EASYRSA_DIR/pki/private/$NODE_NAME.key"
"$EASYRSA_DIR/pki/issued/$NODE_NAME.crt"
"$EASYRSA_DIR/pki/ca.crt"
"$NODE_NAME.ovpn"
)
# 检查所有文件是否存在
for file in "${CERT_FILES[@]}"; do
if [ ! -f "$file" ]; then
echo "错误: 文件 $file 不存在"
exit 1
fi
done
# 创建 ZIP 文件
mkdir client
zip -j "client/$NODE_NAME.zip" "${CERT_FILES[@]}"
if [ $? -ne 0 ]; then
echo "打包 ZIP 文件失败"
exit 1
fi
echo "证书生成和打包完成:"
echo "请求文件: $EASYRSA_DIR/pki/reqs/$NODE_NAME.req"
echo "密钥文件: $EASYRSA_DIR/pki/private/$NODE_NAME.key"
echo "证书文件: $EASYRSA_DIR/pki/issued/$NODE_NAME.crt"
echo "CA 证书: $EASYRSA_DIR/pki/ca.crt"
echo "ZIP 文件: client/$NODE_NAME.zip"
clientStart.sh
节点自动解压部署脚本
#!/bin/bash
# 检查是否提供了节点名称参数
if [ "$#" -ne 1 ]; then
echo "用法: $0 <NODE_NAME>"
echo "示例: $0 node2"
exit 1
fi
# 参数
NODE_NAME="$1" # 节点名称
ZIP_FILE="$NODE_NAME.zip" # ZIP 文件名
TARGET_DIR="/etc/openvpn/client" # 目标解压目录
SERVICE_FILE="/etc/systemd/system/openvpn-client@.service" # systemd 服务文件
# 检查 unzip 命令是否可用
if ! command -v unzip &> /dev/null; then
echo "错误: unzip 命令未找到。正在安装 unzip(apt-get install unzip)"
apt-get install unzip -y
fi
# 检查 openvpn 命令是否可用
if ! command -v openvpn &> /dev/null; then
echo "错误: openvpn 命令未找到。正在安装 openvpn(apt-get install openvpn)"
apt-get install openvpn -y
fi
# 检查 ZIP 文件是否存在
if [ ! -f "$ZIP_FILE" ]; then
echo "错误: ZIP 文件 $ZIP_FILE 不存在"
exit 1
fi
# 创建目标目录(如果不存在)
mkdir -p "$TARGET_DIR" || { echo "无法创建目录 $TARGET_DIR"; exit 1; }
# 解压 ZIP 文件到目标目录
unzip -o "$ZIP_FILE" -d "$TARGET_DIR"
if [ $? -ne 0 ]; then
echo "解压 $ZIP_FILE 失败"
exit 1
fi
# 检查必要的文件是否解压成功
REQUIRED_FILES=("$TARGET_DIR/$NODE_NAME.key" "$TARGET_DIR/$NODE_NAME.crt" "$TARGET_DIR/ca.crt" "$TARGET_DIR/$NODE_NAME.ovpn")
for file in "${REQUIRED_FILES[@]}"; do
if [ ! -f "$file" ]; then
echo "错误: 必要文件 $file 未找到"
exit 1
fi
done
# 创建 systemd 服务文件
cat > "$SERVICE_FILE" << 'EOF'
[Unit]
Description=OpenVPN Client for %i
After=network.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
[Service]
Type=forking
ExecStart=/usr/sbin/openvpn --daemon --config /etc/openvpn/client/%i.ovpn
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
ProtectSystem=full
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
if [ $? -ne 0 ]; then
echo "创建 systemd 服务文件失败"
exit 1
fi
# 重新加载 systemd 配置
systemctl daemon-reload
if [ $? -ne 0 ]; then
echo "重新加载 systemd 配置失败"
exit 1
fi
# 启用 OpenVPN 客户端服务
systemctl enable "openvpn-client@$NODE_NAME.service"
if [ $? -ne 0 ]; then
echo "启用 openvpn-client@$NODE_NAME.service 失败"
exit 1
fi
# 启动 OpenVPN 客户端服务
systemctl start "openvpn-client@$NODE_NAME.service"
if [ $? -ne 0 ]; then
echo "启动 openvpn-client@$NODE_NAME.service 失败"
exit 1
fi
# 检查服务状态
echo "检查服务状态..."
systemctl status "openvpn-client@$NODE_NAME.service" --no-pager
echo "OpenVPN 客户端设置完成:"
echo "证书和配置文件已解压到: $TARGET_DIR"
echo "服务已启用并启动: openvpn-client@$NODE_NAME.service"
echo "ZIP 文件: $ZIP_FILE"
评论区