openvpn社区版服务端部署文档

目录

Anolis 8.10 系统 OpenVPN 服务端完整部署流程(优化版)

📋 目录


一、环境准备

1.1 系统信息检查

# 查看系统版本
cat /etc/os-release

# 查看内核版本
uname -r

# 检查 TUN 模块支持
lsmod | grep tun
modprobe tun
echo "tun" >> /etc/modules-load.d/tun.conf

# 确认 TUN 设备存在
ls -l /dev/net/tun

1.2 安装依赖包

# 更新系统
dnf update -y

# 安装 EPEL 仓库
dnf install epel-release -y

# 安装编译工具链
dnf groupinstall -y "Development Tools"

# 安装 OpenVPN 编译依赖
dnf install -y \
   gcc \
   make \
  rpm-build \
  pkgconfig \
   wget \
  tar \
  openssl-devel \
  zlib-devel \
  pam-devel \
  systemd-devel \
  krb5-devel \
  libnl3-devel \
  lzo-devel \
  lz4-devel \
  libcap-ng-devel \
  net-tools \
  iptables-services \
  pkcs11-helper \
  pkcs11-helper-devel

# 安装 Easy-RSA
dnf install easy-rsa -y
#或直接下载
wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.2.4/EasyRSA-3.2.4.tgz
tar -xvf EasyRSA-3.2.4.tgz -C /server/tools

# 验证关键依赖
rpm -qa | grep -E "(gcc|openssl-devel|lz4-devel|easy-rsa)"

1.3 创建工作目录(用于编译安装)

# 创建工具目录
mkdir -p /server/tools
cd /server/tools

二、编译安装 OpenVPN

2.1 下载源码

# 下载 OpenVPN 2.6.17(推荐使用国内镜像加速)
wget https://github.com/OpenVPN/openvpn/releases/download/v2.6.17/openvpn-2.6.17.tar.gz

# 如下载慢,使用镜像加速
# wget https://ghproxy.com/https://github.com/OpenVPN/openvpn/releases/download/v2.6.17/openvpn-2.6.17.tar.gz

# 验证下载完整性(可选)
sha256sum openvpn-2.6.17.tar.gz

2.2 编译安装

# 解压源码
tar -zxf openvpn-2.6.17.tar.gz -C /server/tools
cd /server/tools/openvpn-2.6.17

# 配置编译参数
./configure \
   --prefix=/usr/local \
   --sysconfdir=/etc/openvpn \
   --enable-systemd \
   --enable-lz4 \
   --enable-lzo \
   --enable-pkcs11 \
   --enable-async-push

# 查看配置摘要
# 确认显示:
# systemd support: yes
# LZ4 compression: yes

# 编译(使用多核加速)
make -j$(nproc)

# 安装
make install

# 验证安装
/usr/local/sbin/openvpn --version
# 应显示:OpenVPN 2.6.17

# 创建符号链接(方便使用)
ln -sf /usr/local/sbin/openvpn /usr/sbin/openvpn

2.3 创建必要目录

# 创建配置目录结构
mkdir -p /etc/openvpn/server/{keys,ccd,logs}
mkdir -p /etc/openvpn/client
mkdir -p /var/log/openvpn

# 目录说明:
# /etc/openvpn/server/       - 服务器配置根目录
# /etc/openvpn/server/keys/ - 证书和密钥存放目录
# /etc/openvpn/server/ccd/   - 客户端特定配置目录
# /etc/openvpn/server/logs/ - 日志目录
# /var/log/openvpn/         - 系统日志目录

2.4 配置 systemd 服务

# 创建 systemd 服务文件
cat > /etc/systemd/system/openvpn-server@.service <<'EOF'
[Unit]
Description=OpenVPN service for %I
After=network-online.target
Wants=network-online.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage

[Service]
Type=notify
PrivateTmp=true
WorkingDirectory=/etc/openvpn/server
ExecStart=/usr/local/sbin/openvpn --status /var/log/openvpn/%i-status.log --status-version 2 --cd /etc/openvpn/server --config %i.conf
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
LimitNPROC=100
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
ProtectSystem=true
ProtectHome=true
KillMode=process
RestartSec=5s
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

# 重新加载 systemd
systemctl daemon-reload

# 验证服务文件
systemctl cat openvpn-server@server

三、配置 PKI 证书体系

3.1 初始化 Easy-RSA

# 进入工作目录
cd /etc/openvpn/server
mkdir -p easy-rsa
cd easy-rsa

# 复制 Easy-RSA 脚本
#(yum安装)
cp -r /usr/share/easy-rsa/3/* .
#(github下载)
cp -r /server/tools/EasyRSA-3.2.4/* .
# 确认复制成功
ls -l easyrsa
./easyrsa --version

3.2 配置 PKI 参数(推荐)

# 创建 vars 配置文件
cat > vars <<'EOF'
# Easy-RSA 配置变量

# 证书信息(根据实际情况修改)
set_var EASYRSA_REQ_COUNTRY    "CN"
set_var EASYRSA_REQ_PROVINCE   "Shanghai"
set_var EASYRSA_REQ_CITY       "Shanghai"
set_var EASYRSA_REQ_ORG        "linuxjk.cn"
set_var EASYRSA_REQ_EMAIL      "zhangpeng@linuxjk.cn"
set_var EASYRSA_REQ_OU         "IT Department"

# 证书有效期(天)
set_var EASYRSA_CA_EXPIRE      3650    # CA证书10年
set_var EASYRSA_CERT_EXPIRE    3650    # 服务器/客户端证书10年

# 密钥参数
set_var EASYRSA_KEY_SIZE       2048
set_var EASYRSA_ALGO           rsa
set_var EASYRSA_CURVE         secp384r1
set_var EASYRSA_DIGEST         "sha256"

# CRL 有效期
set_var EASYRSA_CRL_DAYS       3650
EOF

# 让配置生效
chmod +x vars

3.3 初始化 PKI 并创建 CA

# 初始化 PKI 目录结构
./easyrsa init-pki

# 构建 CA(无密码模式,适合自动化)
./easyrsa build-ca nopass

# 提示输入 Common Name,输入示例:
# Common Name: OpenVPN-CA

# ⚠️ 生产环境推荐使用带密码的 CA:
# ./easyrsa build-ca
# 会提示设置 CA 私钥密码

# 验证 CA 证书
openssl x509 -in pki/ca.crt -noout -text | grep -A 2 "Validity"

3.4 生成服务器证书(完整步骤)

# ===== 方法1:标准分步骤(推荐用于生产环境)=====

# 步骤1:生成服务器私钥和证书请求
./easyrsa gen-req server nopass
# 提示输入 Common Name,输入:server(或服务器FQDN)

# 步骤2:签发服务器证书
./easyrsa sign-req server server
# 输入 yes 确认
# 如果 CA 有密码,需要输入密码

# ===== 方法2:快捷命令(等同于上述两步)=====
# ./easyrsa build-server-full server nopass

# 验证服务器证书
openssl x509 -in pki/issued/server.crt -noout -text | head -20

# 验证证书链
openssl verify -CAfile pki/ca.crt pki/issued/server.crt
# 应显示:pki/issued/server.crt: OK

3.5 生成 DH 参数

# 生成 2048 位 DH 参数(推荐,约需 2-5 分钟)
./easyrsa gen-dh

# 如需更高安全性(4096 位,可能需要 20-30 分钟)
# 先修改 vars: set_var EASYRSA_KEY_SIZE 4096
# 然后执行: ./easyrsa gen-dh

# 验证生成
ls -lh pki/dh.pem
# 应显示约 424 字节的文件

3.6 生成 TLS 认证密钥

# 生成 tls-auth 密钥(防 DDoS 攻击)
openvpn --genkey secret pki/ta.key

# 验证生成
ls -lh pki/ta.key
cat pki/ta.key | head -5

3.7 生成 CRL(证书吊销列表)

# 生成初始 CRL
./easyrsa gen-crl

# 验证
ls -lh pki/crl.pem
openssl crl -in pki/crl.pem -noout -text

3.8 生成客户端证书(示例)

# 定义客户端名称
CLIENT_NAME="client1"

# ===== 方法1:完整步骤(推荐)=====
# 步骤1:生成证书请求
./easyrsa gen-req $CLIENT_NAME nopass
# Common Name: client1

# 步骤2:签发客户端证书(注意类型是 client)
./easyrsa sign-req client $CLIENT_NAME
# 输入 yes 确认

# ===== 方法2:快捷命令 =====
# ./easyrsa build-client-full $CLIENT_NAME nopass

# 验证客户端证书
openssl verify -CAfile pki/ca.crt pki/issued/$CLIENT_NAME.crt

3.9 复制证书到服务器配置目录

cd /etc/openvpn/server/easy-rsa

# 复制 CA 证书
cp pki/ca.crt /etc/openvpn/server/keys/

# 复制服务器证书和私钥
cp pki/issued/server.crt /etc/openvpn/server/keys/
cp pki/private/server.key /etc/openvpn/server/keys/

# 复制 DH 参数(重命名以便识别)
cp pki/dh.pem /etc/openvpn/server/keys/dh2048.pem

# 复制 TLS 认证密钥
cp pki/ta.key /etc/openvpn/server/keys/

# 复制 CRL(可选但推荐)
cp pki/crl.pem /etc/openvpn/server/keys/

# 设置严格权限(重要!)
#私钥600,公钥644
chmod 600 /etc/openvpn/server/keys/server.key
chmod 600 /etc/openvpn/server/keys/ta.key
chmod 644 /etc/openvpn/server/keys/*.crt
chmod 644 /etc/openvpn/server/keys/dh2048.pem
chmod 644 /etc/openvpn/server/keys/crl.pem

# 设置所有者
chown -R root:root /etc/openvpn/server/keys

# 验证文件完整性
ls -lh /etc/openvpn/server/keys/
root@anolis810:/etc/openvpn/server/easy-rsa# ls -lh /etc/openvpn/server/keys/
总用量 28K
-rw-r--r-- 1 root root 1.2K 12月 4 09:40 ca.crt
-rw-r--r-- 1 root root 646 12月 4 09:41 crl.pem
-rw-r--r-- 1 root root 424 12月 4 09:40 dh2048.pem
-rw-r--r-- 1 root root 4.5K 12月 4 09:40 server.crt
-rw------- 1 root root 1.7K 12月 4 09:40 server.key
-rw------- 1 root root 636 12月 4 09:40 ta.key

四、配置 OpenVPN 服务器

4.1 创建服务器配置文件

cat > /etc/openvpn/server/server.conf <<'EOF'
#################################################
# OpenVPN 2.6.17 服务器配置文件
# 系统: Anolis 8.10
# 创建时间: 2025-12-03
#################################################

# ===== 基本网络设置 =====
# 监听端口(默认 1194)
port 1194

# 协议类型(UDP 性能更好,TCP 更稳定)
proto udp
# 如需使用 TCP,取消下行注释并注释上一行
# proto tcp

# 虚拟网卡类型(TUN=路由模式,TAP=桥接模式)
dev tun

# 网络拓扑(subnet 是推荐模式)
topology subnet

# ===== 证书和密钥路径 =====
# CA 根证书
ca keys/ca.crt

# 服务器证书
cert keys/server.crt

# 服务器私钥(严格保密!)
key keys/server.key

# Diffie-Hellman 参数
dh keys/dh2048.pem

# TLS 认证密钥(0 = 服务器模式)
tls-auth keys/ta.key 0

# 证书吊销列表(推荐启用)
crl-verify keys/crl.pem

# ===== 加密和安全设置 =====
# 数据通道加密算法(OpenVPN 2.6+ 推荐)
cipher AES-256-GCM

# 支持的加密算法列表(协商用)
data-ciphers AES-256-GCM:AES-128-GCM:AES-256-CBC

# 认证算法
auth SHA256

# TLS 最低版本(增强安全)
tls-version-min 1.2

# TLS 加密套件(可选,更严格的安全策略)
# tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256

# ===== VPN 网络配置 =====
# VPN 子网(服务器自动获得 10.8.0.1)
server 10.8.0.0 255.255.255.0

# 维护客户端 IP 分配关系(重启后保持)
ifconfig-pool-persist /var/log/openvpn/ipp.txt

# ===== 路由设置 =====
# 推送路由到客户端(访问公司内网)
# 假设公司内网是 192.168.1.0/24
#push "route 192.168.1.0 255.255.255.0"
push "route 10.0.0.0 255.255.255.0"

# 推送所有流量走 VPN(全局代理模式,将客户端所有流量都路由到 VPN,可能影响速度)
# push "redirect-gateway def1 bypass-dhcp"

# 推送 DNS 服务器(客户端连接 VPN 后,会使用这些 DNS 服务器解析域名)
# 主 DNS:Windows Server(解析内网域名)
push "dhcp-option DNS 192.168.1.112"
# 备用 DNS:公网 DNS(解析外网域名,提高速度)
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 223.5.5.5"  # 阿里 DNS(国内推荐)

# 推送 AD 域后缀
push "dhcp-option DOMAIN example.local"


# 推送 NTP 服务器(统一时间同步)
# push "dhcp-option NTP 192.168.1.1"

# ===== 客户端配置 =====
# 允许客户端之间通信(按需启用)
client-to-client

# 最大客户端连接数(在当前 /24 网段内# 最多可设为 252)
max-clients 200

# 同一证书只允许一个客户端连接(推荐)
# duplicate-cn 默认禁用,生产环境不要启用

# 客户端特定配置目录(为不同客户端分配固定 IP 或特定路由规则),创建客户端证书时的Common name
#/etc/openvpn/server/ccd/client1 文件可配置 client1 的专属设置
client-config-dir ccd

# ===== 连接保持 =====
# 每 10 秒 ping 一次,120 秒无响应则断线
keepalive 10 120

# ===== 压缩设置 =====
# LZ4 压缩(LZ4 压缩算法,减少传输数据量,降低带宽消耗,LZ4 压缩/解压速度快,CPU 占用低)
#注意: 客户端也必须支持 LZ4
compress lz4-v2
push "compress lz4-v2"

# 或禁用压缩(更安全,防 VORACLE 攻击)
# comp-lzo no
# push "comp-lzo no"

# ===== 权限和安全 =====
# 降低运行权限(启动后切换到 nobody 用户,即使 OpenVPN 被攻破,攻击者也只有 nobody 用户权限)
user nobody
group nobody

# 重启后保持密钥和 TUN 设备
persist-key
persist-tun

# ===== 日志设置 =====
# 状态日志(显示连接的客户端)
status /var/log/openvpn/openvpn-status.log

# 运行日志(log-append:追加模式;log: 覆盖模式(每次启动清空旧日志))
log-append /var/log/openvpn/openvpn.log

# 日志详细级别(0=静默, 3=正常, 9=极详细)
verb 3

# 重复消息静默(避免日志刷屏)
mute 20

# ===== 性能优化 =====
# 发送/接收缓冲区大小(字节)
sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"

# 快速 I/O(减少 CPU 使用)
fast-io

# ===== 管理接口(可选)=====
# 启用管理接口(用于监控,仅本地访问)
management 127.0.0.1 7505

# ===== 其他选项 =====
# UDP 模式下显式退出通知(客户端断开时明确通知服务器)
explicit-exit-notify 1

# 脚本安全级别(允许运行外部脚本,0: 禁止脚本;1: 只允许内置脚本;2: 允许所有脚本(含 shell 命令))
# script-security 2

# 客户端连接/断开时执行自定义脚本
# client-connect /etc/openvpn/server/scripts/client-connect.sh
# client-disconnect /etc/openvpn/server/scripts/client-disconnect.sh
EOF

4.2 配置优化建议

# 根据实际需求调整配置

# 场景1:仅访问内网(推荐,不影响客户端上网)
# 保持当前配置:push "route 192.168.1.0 255.255.255.0"

# 场景2:全局代理(所有流量走 VPN)
# 启用:push "redirect-gateway def1 bypass-dhcp"

# 场景3:双栈支持(IPv4 + IPv6)
# 添加:
# server-ipv6 fd00:abcd::/64
# push "route-ipv6 2000::/3"

# 场景4:多个内网段
# 添加多条 push "route" 指令

4.3 创建客户端特定配置(可选)

# 为 client1 分配固定 IP
cat > /etc/openvpn/server/ccd/client1 <<EOF
# 固定 IP 分配(必须在 server 网段内)
ifconfig-push 192.168.1.1 255.255.255.0

# 推送特定路由
push "route 192.168.1.0 255.255.255.0"

# 限制带宽(单位:字节/秒)
# shaper 1024000
EOF

五、配置网络转发

5.1 启用 IP 转发

# 临时启用
sysctl -w net.ipv4.ip_forward=1

# 永久启用
cat >> /etc/sysctl.conf <<EOF
# OpenVPN IP 转发
net.ipv4.ip_forward = 1

# 可选:IPv6 转发
# net.ipv6.conf.all.forwarding = 1
EOF

# 应用配置
sysctl -p

# 验证
sysctl net.ipv4.ip_forward
# 应显示:net.ipv4.ip_forward = 1

5.2 配置防火墙(firewalld)

# 检查 firewalld 状态
systemctl status firewalld

# 如果未启动,启动 firewalld
systemctl enable --now firewalld

# 获取网卡名称(通常是 eth0 或 ens33)
INTERFACE=$(ip route | grep default | awk '{print $5}')
echo "外网网卡: $INTERFACE"

# 添加 OpenVPN 服务
firewall-cmd --permanent --add-service=openvpn

# 或直接开放端口(如果上述命令无效)
firewall-cmd --permanent --add-port=1194/udp

# 添加 NAT 伪装(关键!)
firewall-cmd --permanent --add-masquerade

# 添加直接规则(NAT 转发)
firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 \
-s 10.8.0.0/24 -o $INTERFACE -j MASQUERADE

# 允许 VPN 流量转发
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 \
-i tun0 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 \
-o tun0 -j ACCEPT

# 重载防火墙
firewall-cmd --reload

# 验证规则
firewall-cmd --list-all
firewall-cmd --direct --get-all-rules
[root@localhost easy-rsa]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens192
sources:
services: cockpit dhcpv6-client openvpn ssh
ports: 1194/udp
protocols:
forward: no
masquerade: yes
forward-ports:
source-ports:
icmp-blocks:
rich rules:
rule priority="1" family="ipv4" source address="192.168.20.222" port port="37017" protocol="tcp" accept
rule priority="10" family="ipv4" port port="37017" protocol="tcp" drop
[root@localhost easy-rsa]# firewall-cmd --direct --get-all-rules
ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 -o ens192 -j MASQUERADE
ipv4 filter FORWARD 0 -i tun0 -j ACCEPT
ipv4 filter FORWARD 0 -o tun0 -j ACCEPT

5.3 配置防火墙(iptables)

# 如果使用 iptables(替代 firewalld)

# 停止 firewalld
systemctl stop firewalld
systemctl disable firewalld

# 安装并启动 iptables
dnf install iptables-services -y
systemctl enable --now iptables

# 添加规则
INTERFACE=$(ip route | grep default | awk '{print $5}')

# NAT 转发规则
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o $INTERFACE -j MASQUERADE

# 允许转发
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -j ACCEPT

# 保存规则
service iptables save

# 验证规则
iptables -t nat -L -n -v | grep 10.8.0.0

5.4 创建防火墙规则持久化脚本(可选,自动执行上述配置)

cat > /etc/openvpn/server/firewall-rules.sh <<'EOF'
#!/bin/bash
# OpenVPN 防火墙规则脚本

# 获取外网网卡
INTERFACE=$(ip route | grep default | awk '{print $5}')

if command -v firewall-cmd &> /dev/null; then
   # 使用 firewalld
   echo "检测到 firewalld,应用规则..."
  firewall-cmd --permanent --add-masquerade
  firewall-cmd --permanent --add-service=openvpn
  firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 \
       -s 10.8.0.0/24 -o $INTERFACE -j MASQUERADE
  firewall-cmd --reload
else
   # 使用 iptables
   echo "使用 iptables,应用规则..."
  iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o $INTERFACE -j MASQUERADE
  iptables -A FORWARD -i tun0 -j ACCEPT
  iptables -A FORWARD -o tun0 -j ACCEPT
   service iptables save
fi

echo "防火墙规则已应用"
EOF

chmod +x /etc/openvpn/server/firewall-rules.sh

# 执行脚本
/etc/openvpn/server/firewall-rules.sh

5.5 验证网络配置

# 检查 IP 转发
cat /proc/sys/net/ipv4/ip_forward
# 应显示:1

# 检查 NAT 规则
iptables -t nat -L -n -v | grep 10.8.0.0
# 或
firewall-cmd --direct --get-rules ipv4 nat POSTROUTING

# 检查路由
ip route

# 测试 DNS 解析(可选)
nslookup www.baidu.com 8.8.8.8

六、启动和验证服务

6.1 测试配置文件

# 测试配置语法
openvpn --config /etc/openvpn/server/server.conf --test-crypto

# 前台运行测试(查看详细输出,按 Ctrl+C 停止)
openvpn --config /etc/openvpn/server/server.conf

# 观察输出,确保没有错误
# 正确的输出最后会显示:
# Initialization Sequence Completed

6.2 启动服务

# 启动服务
systemctl start openvpn-server@server

# 设置开机自启
systemctl enable openvpn-server@server

# 检查服务状态
systemctl status openvpn-server@server

# 应显示:
# Active: active (running)
# Status: "Initialization Sequence Completed"

6.3 验证服务运行

# 检查进程
ps aux | grep openvpn

# 检查监听端口
ss -tunlp | grep 1194
# 应显示:udp UNCONN 0 0 *:1194 *:*

# 或使用 netstat
netstat -tunlp | grep 1194

# 检查 TUN 设备
ip addr show tun0
# 应显示:inet 10.8.0.1/24

# 检查路由表
ip route | grep tun0
# 应显示:10.8.0.0/24 dev tun0

# 从服务器 ping VPN 网关
ping -c 3 10.8.0.1

6.4 查看日志

# 查看实时日志
tail -f /var/log/openvpn/openvpn.log

# 查看 systemd 日志
journalctl -u openvpn-server@server -f

# 查看最近 50 行日志
journalctl -u openvpn-server@server -n 50

# 查看状态文件(显示连接的客户端)
cat /var/log/openvpn/openvpn-status.log

七、生成客户端配置

7.1 创建客户端配置目录

mkdir -p /etc/openvpn/client-configs/{files,keys,base}
cd /etc/openvpn/client-configs

7.2 创建客户端配置模板

# 获取服务器公网 IP
SERVER_IP=$(curl -s ifconfig.me)
echo "服务器公网 IP: $SERVER_IP"

# 如果无法获取,手动设置
# SERVER_IP="YOUR_PUBLIC_IP"

cat > /etc/openvpn/client-configs/base.conf <<EOF
##############################################
# OpenVPN 客户端配置文件
# 服务器: $SERVER_IP
# 生成时间: $(date)
##############################################

# 客户端模式
client

# 使用 TUN 设备(与服务器一致)
dev tun

# 协议(与服务器一致)
proto udp
# 如服务器使用 TCP,改为:proto tcp

# 服务器地址和端口
remote $SERVER_IP 1194

# 如有多个服务器(高可用)
# remote server1.example.com 1194
# remote server2.example.com 1194
# remote-random

# 保持尝试连接
resolv-retry infinite

# 不绑定本地端口
nobind

# 加密设置(与服务器一致)
cipher AES-256-GCM
auth SHA256

# TLS 认证(方向为 1,与服务器的 0 对应)
key-direction 1

# 压缩设置(与服务器一致)
compress lz4-v2

# 重启后保持
persist-key
persist-tun

# 降低权限(Linux/macOS 客户端)
# user nobody
# group nobody

# 日志级别
verb 3

# 静默重复消息
mute 20

# 脚本安全级别(如需运行脚本)
# script-security 2

# 验证服务器证书(增强安全)
remote-cert-tls server

# 以下内容由生成脚本自动添加
# <ca>...</ca>
# <cert>...</cert>
# <key>...</key>
# <tls-auth>...</tls-auth>
EOF

7.3 创建客户端配置生成脚本(改进版)

cat > /etc/openvpn/client-configs/make_config.sh <<'EOF'
#!/bin/bash
#################################################
# OpenVPN 客户端配置生成脚本
# 用法: ./make_config.sh <client_name>
#################################################

# 配置变量
BASE_CONFIG="/etc/openvpn/client-configs/base.conf"
OUTPUT_DIR="/etc/openvpn/client-configs/files"
KEY_DIR="/etc/openvpn/server/easy-rsa/pki"
TA_KEY="/etc/openvpn/server/keys/ta.key"

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 检查参数
if [ $# -ne 1 ]; then
   echo -e "${RED}用法: $0 <客户端名称>${NC}"
   echo -e "${YELLOW}示例: $0 client1${NC}"
   exit 1
fi

CLIENT_NAME=$1

# 检查证书是否存在
if [ ! -f "$KEY_DIR/issued/${CLIENT_NAME}.crt" ]; then
   echo -e "${RED}错误:客户端证书不存在: ${CLIENT_NAME}.crt${NC}"
   echo -e "${YELLOW}请先生成客户端证书:${NC}"
   echo " cd /etc/openvpn/server/easy-rsa"
   echo " ./easyrsa gen-req $CLIENT_NAME nopass"
   echo " ./easyrsa sign-req client $CLIENT_NAME"
   exit 1
fi

# 检查私钥是否存在
if [ ! -f "$KEY_DIR/private/${CLIENT_NAME}.key" ]; then
   echo -e "${RED}错误:客户端私钥不存在: ${CLIENT_NAME}.key${NC}"
   exit 1
fi

# 创建输出目录
mkdir -p ${OUTPUT_DIR}

# 生成配置文件
OUTPUT_FILE="${OUTPUT_DIR}/${CLIENT_NAME}.ovpn"

# 复制基础配置
cat ${BASE_CONFIG} > ${OUTPUT_FILE}

# 添加证书和密钥(内嵌方式)
echo "" >> ${OUTPUT_FILE}
echo "<ca>" >> ${OUTPUT_FILE}
cat ${KEY_DIR}/ca.crt >> ${OUTPUT_FILE}
echo "</ca>" >> ${OUTPUT_FILE}

echo "" >> ${OUTPUT_FILE}
echo "<cert>" >> ${OUTPUT_FILE}
# 提取证书部分(去掉额外内容)
sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' ${KEY_DIR}/issued/${CLIENT_NAME}.crt >> ${OUTPUT_FILE}
echo "</cert>" >> ${OUTPUT_FILE}

echo "" >> ${OUTPUT_FILE}
echo "<key>" >> ${OUTPUT_FILE}
cat ${KEY_DIR}/private/${CLIENT_NAME}.key >> ${OUTPUT_FILE}
echo "</key>" >> ${OUTPUT_FILE}

echo "" >> ${OUTPUT_FILE}
echo "<tls-auth>" >> ${OUTPUT_FILE}
cat ${TA_KEY} >> ${OUTPUT_FILE}
echo "</tls-auth>" >> ${OUTPUT_FILE}

# 设置权限
chmod 600 ${OUTPUT_FILE}

# 成功提示
echo -e "${GREEN}===== 客户端配置生成成功 =====${NC}"
echo -e "${GREEN}文件位置: ${OUTPUT_FILE}${NC}"
echo ""
echo -e "${YELLOW}传输方式:${NC}"
echo " 1. SCP 传输:"
echo "     scp ${OUTPUT_FILE} user@client:/path/"
echo ""
echo " 2. 查看内容(复制粘贴):"
echo "     cat ${OUTPUT_FILE}"
echo ""
echo " 3. 生成二维码(移动设备导入):"
echo "     qrencode -t ansiutf8 < ${OUTPUT_FILE}"
echo ""
echo -e "${YELLOW}Windows 客户端:${NC}"
echo " 将 .ovpn 文件复制到 C:\\Program Files\\OpenVPN\\config\\"
echo ""
echo -e "${YELLOW}Linux 客户端:${NC}"
echo " sudo openvpn --config ${CLIENT_NAME}.ovpn"
echo ""
echo -e "${YELLOW}移动设备(Android/iOS):${NC}"
echo " 使用 OpenVPN Connect 应用导入 .ovpn 文件"
echo ""
EOF

chmod +x /etc/openvpn/client-configs/make_config.sh

7.4 生成客户端配置文件

# 进入配置目录
cd /etc/openvpn/client-configs

# 为 client1 生成配置
./make_config.sh client1

# 为多个客户端批量生成
for client in alice bob charlie manager; do
# 先生成证书(如果还没生成)
cd /etc/openvpn/server/easy-rsa
./easyrsa gen-req $client nopass
./easyrsa sign-req client $client

# 生成配置文件
cd /etc/openvpn/client-configs
./make_config.sh $client
done

# 查看生成的文件
ls -lh /etc/openvpn/client-configs/files/

7.5 创建配置下载服务(可选)

# 安装 Python3(如果未安装)
dnf install python3 -y

# 创建简单的 HTTP 服务器脚本
cat > /etc/openvpn/client-configs/start-http-server.sh <<'EOF'
#!/bin/bash
# 临时 HTTP 服务器,用于下载客户端配置

cd /etc/openvpn/client-configs/files
python3 -m http.server 8000 --bind 0.0.0.0
EOF

chmod +x /etc/openvpn/client-configs/start-http-server.sh

# 使用方法(临时):
# ./start-http-server.sh
# 然后在浏览器访问:http://服务器IP:8000/client1.ovpn

# ⚠️ 注意:这只是临时方案,下载后立即停止服务!
# 生产环境应使用 HTTPS 或 SFTP

八、客户端连接测试

8.1 Linux 客户端

# 安装 OpenVPN 客户端
# Debian/Ubuntu
apt update && apt install openvpn -y

# RHEL/CentOS/Anolis
dnf install epel-release -y
dnf install openvpn -y

# 传输配置文件(在服务器执行)
scp /etc/openvpn/client-configs/files/client1.ovpn user@client_ip:/tmp/

# 在客户端连接(前台测试)
sudo openvpn --config /tmp/client1.ovpn

# 后台运行
sudo openvpn --config /tmp/client1.ovpn --daemon

# 使用 systemd 管理(推荐)
sudo cp /tmp/client1.ovpn /etc/openvpn/client/client1.conf
sudo systemctl start openvpn-client@client1
sudo systemctl enable openvpn-client@client1

# 查看状态
sudo systemctl status openvpn-client@client1

8.2 Windows 客户端

1. 下载 OpenVPN GUI
  https://openvpn.net/community-downloads/
 
2. 安装 OpenVPN GUI(管理员权限)

3. 将 client1.ovpn 复制到配置目录:
  C:\Program Files\OpenVPN\config\
 
4. 右键任务栏 OpenVPN 图标,选择 "连接"

5. 查看连接日志:
  右键 → "查看日志"

8.3 macOS 客户端

1. 下载 Tunnelblick
  https://tunnelblick.net/downloads.html
 
2. 安装 Tunnelblick

3. 双击 client1.ovpn 文件,自动导入配置

4. 点击 Tunnelblick 图标,选择 "连接"

8.4 Android 客户端

1. 在 Google Play 安装 "OpenVPN Connect"

2. 传输 .ovpn 文件到手机
- 方法1:通过邮件发送
- 方法2:通过 USB 传输
- 方法3:扫描二维码(需安装 qrencode)

3. 打开 OpenVPN Connect → 导入 → 选择 .ovpn 文件

4. 点击连接

8.5 iOS 客户端

1. 在 App Store 安装 "OpenVPN Connect"

2. 传输 .ovpn 文件
- 通过 AirDrop
- 通过邮件附件
- 通过 iCloud Drive

3. 打开文件,选择 "导入到 OpenVPN"

4. 点击连接

8.6 验证客户端连接

# ===== 在客户端执行 =====

# 检查 VPN 接口
ip addr show tun0
# 或 Windows: ipconfig /all

# 应显示分配的 IP(如 10.8.0.6)

# 检查路由
ip route
# 应显示:10.8.0.0/24 dev tun0

# Ping VPN 服务器
ping 10.8.0.1

# Ping 内网服务器(如 192.168.1.100)
ping 192.168.1.100

# 检查公网 IP(验证是否走 VPN)
curl ifconfig.me
# 应显示为 OpenVPN 服务器的公网 IP

# 测试 DNS 解析
nslookup www.baidu.com

# Trace 路由
traceroute -n 8.8.8.8
# 第一跳应该是 10.8.0.1

8.7 在服务器查看已连接客户端

# 查看状态文件
cat /var/log/openvpn/openvpn-status.log

# 示例输出:
# CLIENT_LIST,client1,10.8.0.6,192.168.1.100:53241,11223344,22334455,Sun Dec 3 18:30:00 2025

# 实时监控连接
watch -n 2 'cat /var/log/openvpn/openvpn-status.log | grep CLIENT_LIST'

# 查看实时日志
tail -f /var/log/openvpn/openvpn.log

# 使用管理接口查询(如果启用)
echo "status" | nc 127.0.0.1 7505

九、证书管理

9.1 查看证书信息

cd /etc/openvpn/server/easy-rsa

# 查看 CA 证书
openssl x509 -in pki/ca.crt -noout -text

# 查看证书有效期
openssl x509 -in pki/issued/client1.crt -noout -dates

# 查看所有已签发证书
cat pki/index.txt

# 查看证书列表
ls -lh pki/issued/

# 查看私钥
ls -lh pki/private/

9.2 吊销客户端证书

cd /etc/openvpn/server/easy-rsa

# 吊销证书(假设吊销 client1)
./easyrsa revoke client1

# 提示确认,输入:yes

# 重新生成 CRL
./easyrsa gen-crl

# 更新服务器的 CRL
cp pki/crl.pem /etc/openvpn/server/keys/

# 重启 OpenVPN 服务
systemctl restart openvpn-server@server

# 验证 CRL
openssl crl -in /etc/openvpn/server/keys/crl.pem -noout -text

9.3 续期证书

# OpenVPN 证书续期需要重新签发

# 方法1:重新生成(推荐)
cd /etc/openvpn/server/easy-rsa

# 先吊销旧证书(可选)
# ./easyrsa revoke client1

# 删除旧证书文件
rm -f pki/issued/client1.crt
rm -f pki/private/client1.key
rm -f pki/reqs/client1.req

# 重新生成
./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1

# 重新生成客户端配置
cd /etc/openvpn/client-configs
./make_config.sh client1

# 方法2:延长有效期(修改 vars 后重新签发)
# 编辑 vars,增加 EASYRSA_CERT_EXPIRE
# 然后重新执行上述步骤

9.4 备份 PKI

# 创建备份脚本
cat > /root/backup-openvpn-pki.sh <<'EOF'
#!/bin/bash
# OpenVPN PKI 备份脚本

BACKUP_DIR="/backup/openvpn"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/openvpn-pki-$DATE.tar.gz"

# 创建备份目录
mkdir -p $BACKUP_DIR

# 备份 PKI
tar -czf $BACKUP_FILE \
  /etc/openvpn/server/easy-rsa/pki \
  /etc/openvpn/server/server.conf \
  /etc/openvpn/server/keys

# 保留最近 7 天的备份
find $BACKUP_DIR -name "openvpn-pki-*.tar.gz" -mtime +7 -delete

echo "备份完成: $BACKUP_FILE"
ls -lh $BACKUP_FILE
EOF

chmod +x /root/backup-openvpn-pki.sh

# 手动执行
/root/backup-openvpn-pki.sh

# 添加到 crontab(每天凌晨 2 点备份)
crontab -e
# 添加:0 2 * * * /root/backup-openvpn-pki.sh >> /var/log/openvpn-backup.log 2>&1

9.5 恢复 PKI

# 从备份恢复
cd /
tar -xzf /backup/openvpn/openvpn-pki-20251203_020000.tar.gz

# 重启服务
systemctl restart openvpn-server@server

十、安全加固

10.1 启用 TLS-Crypt(推荐,替代 TLS-Auth)

# TLS-Crypt 比 TLS-Auth 更安全,加密控制通道

# 生成 TLS-Crypt 密钥
cd /etc/openvpn/server/keys
openvpn --genkey secret tc.key

# 修改服务器配置
# 将 tls-auth 改为 tls-crypt
sed -i 's/tls-auth keys\/ta.key 0/tls-crypt keys\/tc.key/' /etc/openvpn/server/server.conf

# 修改客户端配置模板
sed -i 's/key-direction 1//' /etc/openvpn/client-configs/base.conf
sed -i 's/<tls-auth>/<tls-crypt>/' /etc/openvpn/client-configs/base.conf
sed -i 's/<\/tls-auth>/<\/tls-crypt>/' /etc/openvpn/client-configs/base.conf

# 重新生成客户端配置
# 并重启服务器
systemctl restart openvpn-server@server

10.2 限制 TLS 加密套件

# 编辑服务器配置
cat >> /etc/openvpn/server/server.conf <<'EOF'

# 限制 TLS 加密套件(仅允许强加密)
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384
EOF

# 重启服务
systemctl restart openvpn-server@server

10.3 启用客户端连接日志审计

# 创建脚本目录
mkdir -p /etc/openvpn/server/scripts

# 创建连接日志脚本
cat > /etc/openvpn/server/scripts/client-connect.sh <<'EOF'
#!/bin/bash
# 客户端连接日志

LOG_FILE="/var/log/openvpn/connections.log"
DATE=$(date "+%Y-%m-%d %H:%M:%S")

echo "$DATE | CONNECT | Client: $common_name | IP: $trusted_ip:$trusted_port | VPN_IP: $ifconfig_pool_remote_ip" >> $LOG_FILE
EOF

cat > /etc/openvpn/server/scripts/client-disconnect.sh <<'EOF'
#!/bin/bash
# 客户端断开日志

LOG_FILE="/var/log/openvpn/connections.log"
DATE=$(date "+%Y-%m-%d %H:%M:%S")

echo "$DATE | DISCONNECT | Client: $common_name | Duration: ${time_duration}s | RX: ${bytes_received} bytes | TX: ${bytes_sent} bytes" >> $LOG_FILE
EOF

chmod +x /etc/openvpn/server/scripts/*.sh

# 在服务器配置中启用脚本
cat >> /etc/openvpn/server/server.conf <<'EOF'

# 客户端连接/断开脚本
script-security 2
client-connect /etc/openvpn/server/scripts/client-connect.sh
client-disconnect /etc/openvpn/server/scripts/client-disconnect.sh
EOF

# 创建日志文件
touch /var/log/openvpn/connections.log
chmod 644 /var/log/openvpn/connections.log

# 重启服务
systemctl restart openvpn-server@server

# 查看连接日志
tail -f /var/log/openvpn/connections.log

10.4 限制客户端访问范围

# 方法1:使用客户端配置目录(CCD)

# 为 client1 创建限制配置
cat > /etc/openvpn/server/ccd/client1 <<EOF
# 仅允许访问特定网段
iroute 192.168.100.0 255.255.255.0

# 禁止访问其他网段(通过不推送路由实现)
EOF

# 方法2:使用 iptables 规则

# 允许 client1(10.8.0.10)访问 192.168.1.0/24
iptables -A FORWARD -s 10.8.0.10 -d 192.168.1.0/24 -j ACCEPT

# 禁止访问其他内网
iptables -A FORWARD -s 10.8.0.10 -d 192.168.0.0/16 -j REJECT

# 保存规则
service iptables save

10.5 启用双因素认证(可选)

# 安装 Google Authenticator PAM 模块
dnf install google-authenticator qrencode -y

# 配置 PAM
cat >> /etc/pam.d/openvpn <<'EOF'
auth required pam_google_authenticator.so
EOF

# 在服务器配置中启用
cat >> /etc/openvpn/server/server.conf <<'EOF'

# 启用 PAM 认证
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn
EOF

# 为每个用户生成密钥
# su - openvpn_user
# google-authenticator

# 重启服务
systemctl restart openvpn-server@server

十一、监控和维护

11.1 创建监控脚本

cat > /usr/local/bin/openvpn-monitor.sh <<'EOF'
#!/bin/bash
# OpenVPN 监控脚本

echo "========== OpenVPN 服务监控 =========="
echo "时间: $(date)"
echo ""

# 1. 服务状态
echo "【服务状态】"
systemctl is-active openvpn-server@server && echo "✓ 服务运行正常" || echo "✗ 服务未运行"
echo ""

# 2. 监听端口
echo "【监听端口】"
ss -tunlp | grep 1194 || echo "✗ 端口未监听"
echo ""

# 3. TUN 设备
echo "【TUN 设备】"
ip addr show tun0 2>/dev/null | grep inet || echo "✗ TUN 设备未创建"
echo ""

# 4. 已连接客户端
echo "【已连接客户端】"
CLIENT_COUNT=$(grep "^CLIENT_LIST" /var/log/openvpn/openvpn-status.log 2>/dev/null | wc -l)
echo "当前连接数: $CLIENT_COUNT"
grep "^CLIENT_LIST" /var/log/openvpn/openvpn-status.log 2>/dev/null | \
   awk -F',' '{print " - "$2" ("$3")"}' || echo " 无客户端连接"
echo ""

# 5. 流量统计
echo "【流量统计】"
if [ -f /sys/class/net/tun0/statistics/rx_bytes ]; then
   RX=$(cat /sys/class/net/tun0/statistics/rx_bytes)
   TX=$(cat /sys/class/net/tun0/statistics/tx_bytes)
   echo " 接收: $(numfmt --to=iec-i --suffix=B $RX)"
   echo " 发送: $(numfmt --to=iec-i --suffix=B $TX)"
else
   echo " 无法获取流量统计"
fi
echo ""

# 6. 最近错误日志
echo "【最近错误】"
tail -10 /var/log/openvpn/openvpn.log | grep -i error || echo " 无错误"
echo ""

# 7. 系统资源
echo "【系统资源】"
echo " CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}')%"
echo " 内存: $(free -h | grep Mem | awk '{print $3"/"$2}')"
echo ""

echo "========================================="
EOF

chmod +x /usr/local/bin/openvpn-monitor.sh

# 执行监控
/usr/local/bin/openvpn-monitor.sh

# 添加到 crontab(每小时执行一次)
crontab -e
# 添加:0 * * * * /usr/local/bin/openvpn-monitor.sh >> /var/log/openvpn-monitor.log

11.2 日志轮转配置

# 创建 logrotate 配置
cat > /etc/logrotate.d/openvpn <<'EOF'
/var/log/openvpn/*.log {
  daily
  rotate 30
  missingok
  notifempty
  compress
  delaycompress
  sharedscripts
  postrotate
      /bin/systemctl reload openvpn-server@server > /dev/null 2>&1 || true
  endscript
}
EOF

# 测试 logrotate
logrotate -d /etc/logrotate.d/openvpn

11.3 性能优化

# 调整系统参数
cat >> /etc/sysctl.conf <<'EOF'
# OpenVPN 性能优化
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.core.rmem_default = 67108864
net.core.wmem_default = 67108864
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
net.ipv4.tcp_congestion_control = bbr
EOF

sysctl -p

11.4 告警通知(可选)

# 安装邮件工具
dnf install mailx -y

# 创建告警脚本
cat > /usr/local/bin/openvpn-alert.sh <<'EOF'
#!/bin/bash
# OpenVPN 告警脚本

ADMIN_EMAIL="admin@example.com"

# 检查服务状态
if ! systemctl is-active --quiet openvpn-server@server; then
   echo "OpenVPN 服务已停止!" | mail -s "OpenVPN 告警" $ADMIN_EMAIL
  systemctl start openvpn-server@server
fi

# 检查 TUN 设备
if ! ip addr show tun0 &>/dev/null; then
   echo "TUN 设备异常!" | mail -s "OpenVPN 告警" $ADMIN_EMAIL
fi
EOF

chmod +x /usr/local/bin/openvpn-alert.sh

# 添加到 crontab(每 5 分钟检查一次)
crontab -e
# */5 * * * * /usr/local/bin/openvpn-alert.sh

十二、常见问题排查

12.1 服务无法启动

# 问题:systemctl start 失败

# 排查步骤:
# 1. 查看详细日志
journalctl -xeu openvpn-server@server

# 2. 检查配置文件语法
openvpn --config /etc/openvpn/server/server.conf --test-crypto

# 3. 前台运行查看详细错误
openvpn --config /etc/openvpn/server/server.conf

# 常见错误:
# 错误1:证书文件不存在
# 解决:检查 keys 目录下文件是否齐全

# 错误2:权限问题
# 解决:chmod 600 /etc/openvpn/server/keys/server.key

# 错误3:端口被占用
# 解决:ss -tunlp | grep 1194 # 查找占用进程

12.2 客户端无法连接

# 问题:客户端连接超时

# 服务器端排查:
# 1. 检查防火墙
firewall-cmd --list-all | grep 1194
iptables -L -n | grep 1194

# 2. 检查端口监听
ss -tunlp | grep 1194

# 3. 检查服务状态
systemctl status openvpn-server@server

# 4. 检查日志
tail -f /var/log/openvpn/openvpn.log

# 客户端排查:
# 1. Ping 服务器 IP
ping 服务器IP

# 2. Telnet 测试端口
telnet 服务器IP 1194

# 3. 检查客户端日志
# Windows: C:\Program Files\OpenVPN\log\
# Linux: journalctl -u openvpn-client@client1

12.3 连接成功但无法访问内网

# 问题:VPN 连接成功,但 ping 不通内网

# 排查步骤:
# 1. 检查服务器 IP 转发
cat /proc/sys/net/ipv4/ip_forward
# 应该是 1

# 2. 检查 NAT 规则
iptables -t nat -L -n -v | grep 10.8.0.0

# 3. 检查路由
# 在客户端执行:
ip route | grep tun0

# 4. 检查防火墙
iptables -L FORWARD -n -v

# 5. 在服务器抓包
tcpdump -i tun0 -n icmp

# 解决方案:
# 重新应用 NAT 规则
INTERFACE=$(ip route | grep default | awk '{print $5}')
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o $INTERFACE -j MASQUERADE
service iptables save

12.4 客户端频繁断线

# 问题:VPN 连接不稳定

# 排查:
# 1. 检查 keepalive 设置
grep keepalive /etc/openvpn/server/server.conf

# 2. 调整参数(在服务器配置中)
keepalive 5 60  # 降低超时时间

# 3. 检查网络质量
# 在客户端执行:
ping -i 0.5 10.8.0.1  # 测试延迟和丢包

# 4. 调整 MTU(如果有分片问题)
# 在服务器配置中添加:
mssfix 1400
tun-mtu 1500

# 重启服务
systemctl restart openvpn-server@server

12.5 性能问题(速度慢)

# 排查:
# 1. 检查加密算法
# 使用 AES-128-GCM 替代 AES-256-GCM(速度更快)

# 2. 禁用压缩
# 在某些情况下压缩会降低性能

# 3. 调整缓冲区
sndbuf 393216
rcvbuf 393216

# 4. 使用 UDP 而不是 TCP

# 5. 测试带宽
# 在客户端执行:
iperf3 -c 10.8.0.1

12.6 证书过期

# 问题:证书过期导致无法连接

# 检查证书有效期
openssl x509 -in /etc/openvpn/server/keys/server.crt -noout -dates

# 解决方案:续期证书(参见 9.3 节)
cd /etc/openvpn/server/easy-rsa
./easyrsa renew server nopass
cp pki/issued/server.crt /etc/openvpn/server/keys/
systemctl restart openvpn-server@server

12.7 DNS 解析问题

# 问题:连接 VPN 后无法解析域名

# 在客户端检查 DNS
cat /etc/resolv.conf  # Linux
ipconfig /all         # Windows

# 解决方案:
# 1. 在服务器配置中推送正确的 DNS
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 114.114.114.114"

# 2. 检查客户端是否应用了 DNS
# Linux 客户端可能需要:
sudo resolvconf -u

十三、工作原理详解

13.1 连接建立流程

┌─────────────┐                    ┌──────────────┐                ┌─────────────┐
│   客户端   │                   │ OpenVPN 服务器│               │   内网服务器 │
│ (家里电脑) │                   │ (公司 VPS)   │               │ (192.168.1.x)│
└──────┬──────┘                   └──────┬───────┘               └──────┬──────┘
      │                                 │                               │
      │ 1. TCP/UDP 连接到 1194 端口     │                               │
      │─────────────────────────────────>│                               │
      │                                 │                               │
      │ 2. TLS 握手(交换证书)         │                               │
      │<────────────────────────────────>│                               │
      │   - 验证服务器证书               │                               │
      │   - 验证客户端证书               │                               │
      │   - 验证 tls-auth HMAC           │                               │
      │                                 │                               │
      │ 3. 协商加密参数                 │                               │
      │<────────────────────────────────>│                               │
      │   - 加密算法: AES-256-GCM       │                               │
      │   - 认证算法: SHA256             │                               │
      │   - DH 密钥交换                 │                               │
      │                                 │                               │
      │ 4. 建立加密隧道                 │                               │
      │══════════════════════════════════│                               │
      │   创建 tun0 (10.8.0.6)           │   创建 tun0 (10.8.0.1)       │
      │                                 │                               │
      │ 5. 接收路由推送                 │                               │
      │<─────────────────────────────────│                               │
      │   route add 192.168.1.0/24       │                               │
      │   via 10.8.0.1                   │                               │
      │                                 │                               │
      │ 6. 访问内网 (192.168.1.100)     │                               │
      │══════════════════════════════════>│ 7. NAT 转换并转发             │
      │   加密数据包                     │──────────────────────────────>│
      │   外层: UDP 到公网IP:1194         │   源IP: 192.168.1.1         │
      │   内层: 10.8.0.6 -> 192.168.1.100 │   目标IP: 192.168.1.100     │
      │                                 │                               │
      │                                 │ 8. 返回数据                   │
      │                                 │<──────────────────────────────│
      │ 9. 加密后返回                   │                               │
      │<══════════════════════════════════│                               │
      │                                 │                               │

13.2 数据包封装过程

原始数据包:
┌──────────────────────────────────────────────────┐
│ IP Header: 10.8.0.6 → 192.168.1.100             │
│ TCP/UDP Header                                   │
│ Application Data (HTTP/SSH/etc.)                 │
└──────────────────────────────────────────────────┘
                  ↓ OpenVPN 加密
┌──────────────────────────────────────────────────┐
│ AES-256-GCM 加密                                 │
│ HMAC-SHA256 认证                                 │
│ [加密后的原始数据包]                             │
└──────────────────────────────────────────────────┘
                  ↓ UDP/TCP 封装
┌──────────────────────────────────────────────────┐
│ 外层 IP: 客户端公网IP → 服务器公网IP             │
│ UDP Header: 源端口随机 → 目标端口 1194           │
│ OpenVPN Header                                   │
│ [加密数据]                                       │
└──────────────────────────────────────────────────┘
                  ↓ 互联网传输
                  ↓ 服务器解密
┌──────────────────────────────────────────────────┐
│ IP Header: 10.8.0.6 → 192.168.1.100             │
│ TCP/UDP Header                                   │
│ Application Data                                 │
└──────────────────────────────────────────────────┘
                  ↓ NAT 转换
┌──────────────────────────────────────────────────┐
│ IP Header: 192.168.1.1 → 192.168.1.100         │ ← 源IP改为服务器内网IP
│ TCP/UDP Header                                   │
│ Application Data                                 │
└──────────────────────────────────────────────────┘
                  ↓ 转发到内网服务器

13.3 关键组件作用

组件作用安全级别
ca.crtCA 根证书,验证服务器和客户端证书公开
server.crt服务器证书,证明服务器身份公开
server.key服务器私钥,绝对保密🔒 私密
dh.pemDiffie-Hellman 参数,密钥交换公开
ta.keyTLS 认证密钥,防 DDoS 和端口扫描🔒 私密
client.crt客户端证书,证明客户端身份半公开
client.key客户端私钥,绝对保密🔒 私密

13.4 安全机制

多层安全防护:
├── 第1层: TLS 证书双向认证
│   ├── 服务器验证客户端证书
│   └── 客户端验证服务器证书

├── 第2层: tls-auth HMAC 验证
│   ├── 防止端口扫描
│   ├── 防止 DDoS 攻击
│   └── 丢弃非法数据包(在 TLS 握手前)

├── 第3层: 数据加密
│   ├── AES-256-GCM(对称加密)
│   └── 每个会话独立密钥

├── 第4层: 数据完整性
│   ├── HMAC-SHA256 认证
│   └── 防止数据篡改

└── 第5层: 前向保密
  └── Diffie-Hellman 密钥交换
      即使私钥泄露,历史会话仍然安全

13.5 NAT 转换详解

# 客户端访问内网服务器的 NAT 过程

# 第1步:客户端发送数据包
源IP: 10.8.0.6 (VPN 客户端)
目标IP: 192.168.1.100 (内网服务器)

# 第2步:OpenVPN 服务器接收并解密
数据包到达 tun0 接口

# 第3步:Linux 内核路由决策
ip route 查询:192.168.1.100 在内网,通过 eth0 转发

# 第4步:iptables POSTROUTING(NAT 转换)
规则:iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
效果:
源IP: 10.8.0.6 → 192.168.1.1 (服务器内网IP)
目标IP: 192.168.1.100 (不变)

# 第5步:数据包从 eth0 发出到内网
源IP: 192.168.1.1
目标IP: 192.168.1.100

# 第6步:内网服务器响应
源IP: 192.168.1.100
目标IP: 192.168.1.1

# 第7步:服务器接收响应,iptables 反向 NAT
源IP: 192.168.1.100 (不变)
目标IP: 192.168.1.1 → 10.8.0.6

# 第8步:OpenVPN 加密并通过隧道返回客户端

13.6 性能指标

项目典型值说明
延迟增加10-30ms取决于加密算法和服务器性能
吞吐量50-500 Mbps取决于 CPU、加密算法、网络带宽
CPU 使用5-20%AES-NI 硬件加速可大幅降低
内存占用10-50MB每个客户端约 1-2MB
连接建立时间1-3 秒包括 TLS 握手和密钥交换

十四、快速检查清单

# 创建一键检查脚本
cat > /usr/local/bin/openvpn-check.sh <<'EOF'
#!/bin/bash
echo "===== OpenVPN 完整检查 ====="

echo -e "\n[1] 服务状态:"
systemctl is-active openvpn-server@server && echo "✓ 运行中" || echo "✗ 未运行"

echo -e "\n[2] 监听端口:"
ss -tunlp | grep 1194 && echo "✓ 正常监听" || echo "✗ 未监听"

echo -e "\n[3] TUN 设备:"
ip addr show tun0 2>/dev/null && echo "✓ 已创建" || echo "✗ 未创建"

echo -e "\n[4] IP 转发:"
[ $(cat /proc/sys/net/ipv4/ip_forward) -eq 1 ] && echo "✓ 已启用" || echo "✗ 未启用"

echo -e "\n[5] NAT 规则:"
iptables -t nat -L -n | grep -q 10.8.0.0 && echo "✓ 已配置" || echo "✗ 未配置"

echo -e "\n[6] 证书文件:"
for file in ca.crt server.crt server.key dh2048.pem ta.key; do
  [ -f /etc/openvpn/server/keys/$file ] && echo "✓ $file" || echo "✗ $file 缺失"
done

echo -e "\n[7] 已连接客户端:"
grep "^CLIENT_LIST" /var/log/openvpn/openvpn-status.log 2>/dev/null | wc -l

echo -e "\n[8] 最近错误:"
tail -10 /var/log/openvpn/openvpn.log | grep -i error || echo "✓ 无错误"

echo -e "\n===== 检查完成 ====="
EOF

chmod +x /usr/local/bin/openvpn-check.sh
/usr/local/bin/openvpn-check.sh

十五、总结

✅ 部署流程完整性检查

步骤状态说明
环境准备系统检查、依赖安装
OpenVPN 编译源码编译、systemd 配置
PKI 证书体系CA、服务器、客户端证书
服务器配置完整的 server.conf 配置
网络转发IP 转发、NAT、防火墙
客户端配置配置生成脚本、多平台支持
连接测试各平台客户端连接指南
证书管理吊销、续期、备份
安全加固TLS-Crypt、审计日志、访问控制
监控维护监控脚本、日志轮转、性能优化
故障排查常见问题和解决方案
工作原理详细的技术原理说明

📝 关键改进点

  1. 完整的证书生成流程:补充了 gen-req + sign-req 的完整步骤
  2. 客户端配置生成:提供了改进的自动化脚本
  3. 安全加固:增加了 TLS-Crypt、审计日志、访问控制等内容
  4. 监控和维护:提供了完整的监控脚本和日志管理
  5. 故障排查:列举了常见问题和详细的解决方案
  6. 工作原理:增加了详细的技术原理图解

🚀 快速开始(精简版)

# 1. 安装依赖
dnf install -y epel-release easy-rsa openssl-devel lz4-devel

# 2. 编译安装 OpenVPN
wget https://github.com/OpenVPN/openvpn/releases/download/v2.6.17/openvpn-2.6.17.tar.gz
tar -zxf openvpn-2.6.17.tar.gz && cd openvpn-2.6.17
./configure --prefix=/usr/local --sysconfdir=/etc/openvpn --enable-systemd
make -j$(nproc) && make install

# 3. 配置 PKI
cd /etc/openvpn/server && mkdir easy-rsa && cd easy-rsa
cp -r /usr/share/easy-rsa/3/* .
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa build-server-full server nopass
./easyrsa gen-dh
openvpn --genkey secret pki/ta.key

# 4. 复制证书
mkdir -p /etc/openvpn/server/keys
cp pki/{ca.crt,issued/server.crt,private/server.key,dh.pem,ta.key} /etc/openvpn/server/keys/
chmod 600 /etc/openvpn/server/keys/server.key

# 5. 创建配置文件(使用本文档第四节的完整配置)

# 6. 启用网络转发
sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

# 7. 配置防火墙
firewall-cmd --permanent --add-masquerade
firewall-cmd --permanent --add-service=openvpn
firewall-cmd --reload

# 8. 启动服务
systemctl enable --now openvpn-server@server

# 9. 生成客户端证书和配置
cd /etc/openvpn/server/easy-rsa
./easyrsa build-client-full client1 nopass
/etc/openvpn/client-configs/make_config.sh client1

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部