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.crt CA 根证书,验证服务器和客户端证书 公开 server.crt 服务器证书,证明服务器身份 公开 server.key 服务器私钥,绝对保密 🔒 私密 dh.pem Diffie-Hellman 参数,密钥交换 公开 ta.key TLS 认证密钥,防 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、审计日志、访问控制 监控维护 ✅ 监控脚本、日志轮转、性能优化 故障排查 ✅ 常见问题和解决方案 工作原理 ✅ 详细的技术原理说明
📝 关键改进点
完整的证书生成流程 :补充了 gen-req + sign-req 的完整步骤
客户端配置生成 :提供了改进的自动化脚本
安全加固 :增加了 TLS-Crypt、审计日志、访问控制等内容
监控和维护 :提供了完整的监控脚本和日志管理
故障排查 :列举了常见问题和详细的解决方案
工作原理 :增加了详细的技术原理图解
🚀 快速开始(精简版)
# 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