OpenVPN 实战上手:原理、部署、解决什么问题¶
写在前面¶
很多运维同学的第一次 OpenVPN,都是在这种场景下被推上去的:
老板:「研发要在家里访问公司内网的测试环境,你给配个 VPN。」
你:「好的。」(心里:什么是 VPN?)
或者面试的时候:
面试官:「你们生产环境运维通道用的什么方案?」
你:「FRP。」
面试官:「OpenVPN 用过吗?讲讲它的原理。」
你:「……」
这篇文章的目标,就是让一个没碰过 OpenVPN 的运维,用一两个小时建立起一套能在面试讲清楚、能在生产部署起来的认知。
不会展开密码学和 TLS 握手的所有细节,重点放在:
- OpenVPN 到底是个什么东西、解决什么问题
- 它和 FRP、WireGuard、IPSec 是什么关系
- 工作原理(一张图就能讲清楚)
- 一套最小可用的部署流程
- 客户端账号怎么签发、怎么吊销
- 生产里的常见坑和面试常被问的点
一句话理解 OpenVPN¶
OpenVPN = 把一根"加密的虚拟网线"插进你的电脑,让你的电脑像物理接进了公司机房的内网一样。
拆开看:
- "虚拟网线"——通过软件创建一张虚拟网卡(
tun0),系统觉得你接了一根新网线 - "加密的"——所有走这根线的流量都被 TLS 加密
- "插进公司内网"——VPN 服务端帮你转发流量到内网的真实服务
跟 FRP 的核心区别一句话:
FRP 是"把内网的某个服务搬到公网",OpenVPN 是"把你这个人塞进内网"。
这个区别在面试里几乎必问,下面会再展开。
它解决什么问题¶
典型场景:
flowchart LR
User[研发同学<br/>在家/出差] -.X.- Office[公司内网<br/>10.0.0.0/8]
Office --> DB[(MySQL 测试库)]
Office --> K8s[K8s 集群]
Office --> Wiki[Confluence] 研发要访问内网的 MySQL、K8s Dashboard、Wiki,没 VPN 就得:
- 把每个服务都开公网端口 → 安全灾难
- 一个个用 FRP 暴露 → 服务多了管不过来,且每个都要开口子
- 上跳板机 SSH 转发 → 体验差,K8s Dashboard / IDE 直连这些场景搞不定
OpenVPN 的解法:连上 VPN 后,研发的电脑获得一个 VPN 隧道 IP(比如 10.8.0.5),服务端再把去公司内网的流量转发过去。从使用体验上看,他像是接进了公司机房局域网;但最终能访问哪些网段,取决于服务端下发的路由、内核转发、NAT 或内网回程路由。
flowchart LR
User[研发<br/>本地获得 10.8.0.5] -->|加密隧道| VPN[OpenVPN 服务端<br/>公网 IP]
VPN -->|转发| Office[公司内网]
Office --> DB[(MySQL)]
Office --> K8s[K8s]
Office --> Wiki[Wiki] OpenVPN 在 VPN 家族里的位置¶
VPN 不是一个东西,而是一类技术。常见的有:
| 方案 | 协议层 | 典型场景 | 特点 |
|---|---|---|---|
| OpenVPN | 应用层(TLS over UDP/TCP) | 远程办公接入 | 跨平台、防火墙穿透好、配置灵活 |
| WireGuard | 内核态(UDP) | 站点互联、性能敏感 | 极简、超快、新世代 |
| IPSec / L2TP | 网络层 | 企业级站点对站点 | 老牌、复杂、防火墙容易拦 |
| SSL VPN(Pulse/SonicWall) | 应用层 | 商业堡垒接入产品 | 一般要付费、带 Web 控制台 |
OpenVPN 的定位:老牌、稳定、跨平台、社区生态最成熟。新项目今天会推荐 WireGuard,但企业里存量 OpenVPN 集群很多,仍然是必备技能。
面试时如果对方问"为什么不用 WireGuard",标准回答:
WireGuard 性能更好、配置更简单,新建项目我会优先选 WireGuard。但 OpenVPN 在「客户端兼容性、用户认证体系(PAM/LDAP)、证书撤销列表(CRL)、灵活路由」上更成熟,存量企业场景仍然是主力。
工作原理:一张图讲完¶
sequenceDiagram
participant App as 客户端 App<br/>(浏览器/MySQL Workbench)
participant Tun as 本地 tun 虚拟网卡
participant Client as OpenVPN 客户端进程
participant Server as OpenVPN 服务端
participant Intra as 公司内网
Note over Client,Server: 1. TLS 握手期间交换并验证证书
Client->>Server: ClientHello(发起握手、协商参数)
Server->>Client: ServerHello + Certificate(返回服务端证书)
Client->>Server: Certificate(提交客户端证书)
Note over Client,Server: 2. 协商会话密钥<br/>分配虚拟 IP(10.8.0.5)
App->>Tun: 我要访问 10.0.0.20:3306
Tun->>Client: 内核把包交给 OpenVPN 进程
Client->>Server: 加密封装后从公网发出(UDP 1194)
Server->>Server: 解密 → 拿到原始 IP 包
Server->>Intra: 按路由或 NAT 转发到 10.0.0.20:3306
Intra->>Server: MySQL 响应
Server->>Client: 加密回包
Client->>Tun: 解密
Tun->>App: App 拿到响应 关键概念:
- tun 设备:内核里的"虚拟网卡",OpenVPN 进程从它那里收发 IP 包
- 加密:用 TLS(OpenSSL 库),既加密内容也校验身份
- 证书互认:服务端验客户端证书、客户端验服务端证书 —— 它比"只靠账号密码"更适合作为强身份基础,但前提是私钥独立保管、离职及时吊销
- 路由下发:服务端在握手成功后会推送一组路由(
push "route 10.0.0.0 255.0.0.0")给客户端,客户端的10.0.0.0/8流量就自动走 VPN
tun 和 tap 的区别(高频面试题)¶
- tun 模式(推荐):工作在 IP 层(L3),虚拟网卡进出的是 IP 包。跨网段路由用这个。
- tap 模式:工作在以太网层(L2),出入的是完整以太网帧。桥接用这个(让 VPN 客户端获得跟服务端同一个广播域,能跑 ARP、DHCP、组播)。
99% 的远程办公场景用 tun。tap 主要用在「让远程用户像物理插了网线一样在内网做 PXE 启动、Wake-on-LAN」这类奇葩需求。
一套最小可用部署(CentOS/Ubuntu 通用)¶
下面用「Easy-RSA + 原生 OpenVPN」最经典的方式过一遍。生产里可以用自动化脚本、受维护的镜像或平台化方案来降低操作成本,但理解原生流程是基础。
1. 装 OpenVPN 和 Easy-RSA¶
# Ubuntu/Debian
apt install -y openvpn easy-rsa
# CentOS/RHEL
yum install -y epel-release
yum install -y openvpn easy-rsa
2. 搭建自己的 CA(这是 OpenVPN 的精髓)¶
make-cadir /etc/openvpn/easy-rsa
cd /etc/openvpn/easy-rsa
# 初始化 PKI 体系
./easyrsa init-pki
# 生成根 CA(会让你设密码,记住,签发客户端证书时要用)
./easyrsa build-ca
# 生成服务端证书 + 私钥
./easyrsa build-server-full server nopass
# 生成 Diffie-Hellman 参数(用来做前向安全密钥交换,会很慢,几分钟)
./easyrsa gen-dh
# 生成初始 CRL,后面 crl-verify 会用到
./easyrsa gen-crl
# 准备 OpenVPN 服务端运行目录
mkdir -p /etc/openvpn/server
install -m 644 pki/crl.pem /etc/openvpn/server/crl.pem
# 生成 tls-crypt 密钥,保护控制信道并减少无效握手消耗
openvpn --genkey tls-crypt /etc/openvpn/server/ta.key
# 如果发行版里的 OpenVPN 还不支持上面写法,可以退回:
# openvpn --genkey --secret /etc/openvpn/server/ta.key
到这一步你拥有了一个自己的小 CA,可以为每个员工签发独立证书。
3. 服务端配置¶
/etc/openvpn/server/server.conf:
port 1194
proto udp
dev tun
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
dh /etc/openvpn/easy-rsa/pki/dh.pem
tls-crypt /etc/openvpn/server/ta.key
# 给客户端分配 10.8.0.0/24 网段
topology subnet
server 10.8.0.0 255.255.255.0
# 把公司内网路由推给客户端
push "route 10.0.0.0 255.0.0.0"
# 把 DNS 也推给客户端(让 wiki.intra 能解析)
push "dhcp-option DNS 10.0.0.2"
# 数据通道加密套件(OpenVPN 2.5+ 推荐写法)
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
auth SHA256
# 客户端断线后保留 IP 分配,方便重连
ifconfig-pool-persist ipp.txt
# 限制最大连接数
max-clients 100
# 日志
status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 3
# 让多个客户端可以互相通信(按需开)
# client-to-client
# 撤销列表(吊销用户证书后必填)
crl-verify /etc/openvpn/server/crl.pem
# 可选:用于踢掉在线会话
management /run/openvpn/server.sock unix
management-client-user root
management-client-group root
这里有一个很重要的取舍:如果服务端做 NAT,内网服务看到的源地址通常是 VPN 服务端的内网地址,配置最简单;如果不做 NAT,而是让内网路由器知道 10.8.0.0/24 怎么回到 OpenVPN 服务端,内网服务就能看到真实 VPN 客户端 IP,更利于审计。
启动:
# 开启内核转发(关键,否则 VPN 进得来出不去)
sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
# 配置 NAT,让 VPN 客户端能访问内网(假设 eth0 是去内网的网卡)
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
# 放行 OpenVPN 端口,实际命令按你的防火墙工具调整
# ufw allow 1194/udp
# firewall-cmd --permanent --add-port=1194/udp && firewall-cmd --reload
systemctl enable --now openvpn-server@server
上面的 iptables 只是即时生效。生产里要用 iptables-save、firewalld、nftables 或云厂商安全组把规则持久化,否则机器重启后规则会丢。
4. 给员工签发证书¶
每个员工一套独立证书。这是 OpenVPN 的核心安全模型。
cd /etc/openvpn/easy-rsa
# 给"zhangsan"签发
# 演示环境为了导入方便用了 nopass;生产更建议给私钥加密码,或叠加 LDAP/TOTP
./easyrsa build-client-full zhangsan nopass
# 生成的文件
ls pki/issued/zhangsan.crt
ls pki/private/zhangsan.key
把以下 5 个文件打包给员工:
ca.crt(根证书)zhangsan.crt(员工证书)zhangsan.key(员工私钥)ta.key(防 DoS 预共享密钥)client.ovpn(连接配置)
注意:zhangsan.key 是员工私钥,泄露后基本等于这个 VPN 身份泄露。不要用聊天工具随手传,生产里最好结合私钥密码、LDAP/TOTP 和离职吊销流程。
client.ovpn 模板:
client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
auth SHA256
ca ca.crt
cert zhangsan.crt
key zhangsan.key
tls-crypt ta.key
verb 3
更专业的做法:把 5 个文件内联进单个 .ovpn 文件(用 <ca>...</ca>、<cert>...</cert> 标签包起来),员工只需要导入一个文件。脚本可以自动生成。
5. 吊销员工证书(员工离职必做)¶
cd /etc/openvpn/easy-rsa
./easyrsa revoke zhangsan
./easyrsa gen-crl
install -m 644 pki/crl.pem /etc/openvpn/server/crl.pem
# CRL 对新连接/重连生效;已经在线的会话建议主动踢掉
# 下面命令依赖 server.conf 里的 management 配置
printf "kill zhangsan\n" | socat - UNIX-CONNECT:/run/openvpn/server.sock
面试要点:证书吊销能让离职人员的客户端证书失效,但它不替代账号禁用、私钥回收和在线会话清理。生产里通常会把 CRL、LDAP 禁用和踢会话一起做。
生产里的部署捷径¶
手搓 Easy-RSA 适合学习。生产里可以用脚本或镜像减少重复劳动,但要先确认项目是否仍在维护、默认配置是否符合你们公司的安全基线。
方案 A:openvpn-install 一键脚本¶
curl -O https://raw.githubusercontent.com/Nyr/openvpn-install/master/openvpn-install.sh
bash openvpn-install.sh
这是社区里常见的一键安装脚本,菜单式选择端口、加密套件、DNS,自动签 CA、生成 client.ovpn。它很适合快速搭环境,但生产执行前一定要审脚本内容、固定版本,并记录生成的 CA、证书和配置。
方案 B:kylemanna/openvpn Docker 镜像¶
docker volume create openvpn-data
# 初始化配置
docker run -v openvpn-data:/etc/openvpn --rm \
kylemanna/openvpn ovpn_genconfig -u udp://vpn.example.com
# 初始化 CA(会让你设密码)
docker run -v openvpn-data:/etc/openvpn --rm -it \
kylemanna/openvpn ovpn_initpki
# 启动
docker run -v openvpn-data:/etc/openvpn -d \
-p 1194:1194/udp --cap-add=NET_ADMIN \
--name openvpn kylemanna/openvpn
# 签客户端
docker run -v openvpn-data:/etc/openvpn --rm -it \
kylemanna/openvpn easyrsa build-client-full zhangsan nopass
docker run -v openvpn-data:/etc/openvpn --rm \
kylemanna/openvpn ovpn_getclient zhangsan > zhangsan.ovpn
优点:所有状态在一个 docker volume 里,迁移、备份比较方便。需要注意的是,镜像方案要看维护状态;如果镜像多年不更新,就更适合作为学习或小规模内网工具,生产最好选择仍在维护的镜像,或者自己构建基础镜像。
客户端账号管理的几种姿势¶
| 方式 | 易用性 | 安全性 | 适合 |
|---|---|---|---|
| 仅证书 | 一般 | 高 | 内部团队、人数固定 |
| 证书 + 用户名密码(PAM/LDAP) | 较好 | 很高 | 推荐:能复用公司 AD/LDAP |
| 证书 + TOTP(Google Authenticator) | 好 | 极高 | 安全敏感场景,开 2FA |
| 仅用户名密码(不带证书) | 好 | 低 | 不推荐 |
最常见的生产姿势是 证书 + LDAP,用 openvpn-auth-ldap 插件接公司 AD:
这样员工的 OpenVPN 账号自动跟着 AD 走。离职禁用 AD 账号后,后续认证会失败;同时仍建议吊销证书并踢掉已经在线的会话。
路由模式:split tunnel vs full tunnel¶
# split tunnel(默认推荐):只把内网流量走 VPN,刷抖音不走
push "route 10.0.0.0 255.0.0.0"
# full tunnel:所有流量走 VPN(适合在不可信 WiFi 防嗅探)
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 10.0.0.2"
full tunnel 不是只加一行路由就完事。服务端还要能把客户端的公网流量 NAT 出去,并且 DNS 要走可信解析器,否则用户会出现“连上 VPN 后不能上网”或者 DNS 泄露的问题。
面试 Tip:能讲清这两种模式的差别和适用场景,会显得你确实做过远程接入方案设计。
常见故障排查¶
| 现象 | 多半原因 |
|---|---|
| 客户端连上了,但 ping 不通内网 IP | 服务端 ip_forward=0 或者 NAT/路由没配 |
| 客户端连上了,能 ping IP 但解析不了内部域名 | 没 push DNS,或客户端没接受 push 的 DNS |
| 连接频繁断开 | 客户端在弱网(4G/酒店 WiFi),优先看丢包和 MTU;UDP 被限速/丢弃时再临时试 proto tcp |
| 突然所有人连不上 | 服务端证书过期、ta.key 不一致、CRL 文件损坏、防火墙或安全组变更 |
| 某个用户连不上其他人能 | 证书过期/被吊销,客户端文件没下发对,或 LDAP/TOTP 认证失败 |
排查命令:
# 服务端日志
tail -f /var/log/openvpn.log
# 当前连接状态
cat /var/log/openvpn-status.log
# 抓握手包
tcpdump -i eth0 udp port 1194 -nn
# 客户端调试模式(加详细日志)
openvpn --config zhangsan.ovpn --verb 6
面试可能被问到的点(重点)¶
Q1:OpenVPN 和 FRP 有什么区别?¶
- FRP:把内网某个端口暴露到公网,面向"服务"。一个内网 MySQL 暴露成公网 IP:3306。访问者拿到的是公网入口。
- OpenVPN:把人接进一个受控的 VPN 隧道,面向"用户"。用户连上后获得隧道 IP,再通过路由或 NAT 访问内网资源。
- 选型:少量服务对外、临时调试 → FRP;多人远程办公、要访问大量内网资源 → OpenVPN/WireGuard。
Q2:OpenVPN 怎么保证安全?¶
- TLS 控制信道加密 + 数据通道加密(例如 AES-256-GCM / CHACHA20-POLY1305)
- 双向证书认证(服务端验客户端、客户端验服务端)
- 私有 CA + 每人独立证书
- 离职可吊销证书(CRL),并踢掉在线会话
- 可叠加 LDAP 账号密码、TOTP 二次认证
Q3:tun 和 tap 的区别?¶
- tun = L3,IP 包,跨网段路由场景,99% 用这个
- tap = L2,以太网帧,桥接场景(PXE、组播)
Q4:UDP 还是 TCP?¶
默认 UDP:低延迟、不会"TCP over TCP"(嵌套 TCP 重传性能灾难)。 TCP 兜底:在严格防火墙、酒店 WiFi 这类只放行 80/443 的环境,可以把 OpenVPN 改成 tcp/443 试试。注意这只是跑在 443 端口,不等于真正的 HTTPS 流量,深度检测仍然可能识别。
Q5:你怎么管理 OpenVPN 用户?离职了怎么办?¶
- 入职:管理员用 Easy-RSA 签发独立证书 + 生成 .ovpn 文件下发
- 日常:账号接 LDAP,跟着公司 AD 一起管
- 离职:执行
easyrsa revoke+gen-crl更新 CRL,禁掉 LDAP 账号,并通过 management 接口踢掉已在线会话
Q6:OpenVPN 高可用怎么做?¶
- 多节点 + DNS 轮询 / 支持 UDP 的公网 LB,可以解决入口故障
- 状态(IP 池、CRL、CA/证书材料)放共享存储或定时同步
- 客户端 .ovpn 里写多个
remote vpn1.example.com 1194、remote vpn2.example.com 1194,可以重连 failover,但不是无缝会话迁移
Q7:你为什么不上 WireGuard?¶
WireGuard 性能更好、内核态、配置简单。新项目我会优先选 WireGuard。OpenVPN 留给以下场景: - 已有的存量集群 - 需要 LDAP / AD 集成 - 客户端环境很杂(老 Windows、出差时只能用第三方 OpenVPN 客户端) - 需要严格的证书撤销列表(CRL)和审计
一句话总结¶
OpenVPN = 让你这个"人"通过加密隧道虚拟接入到公司内网,靠的是「自建 CA + 双向证书 + tun 虚拟网卡」三件套。
把「证书签发吊销、tun/tap 区别、split/full tunnel、UDP/TCP 选型、与 FRP 的差异」这五件事讲清楚,面试基本不会被卡。