OpenVPN 服务端搭建与家用网络远程接入
给家里的服务器搭 OpenVPN,目标是:外地设备连回来能直接访问家里内网,客户端管理要能批量签发。这篇把最终方案和几个关键决策记录下来。
为什么是 OpenVPN
备选都看了:WireGuard 更轻量但内核模块依赖和兼容性在Debian 上有小坑,IPsec 配置繁琐,Tailscale 方便但流量要过中转。OpenVPN 的优势是纯用户态、配置文件全内联、客户端一个 .ovpn 文件走天下,对”自用 + 偶尔给朋友开个账号”的场景最省心。
整条链路是这样:客户端拿到 tun 地址 → 流量封进 UDP 1194 隧道 → 服务端 tun 拆包按 route 转发 → 出 eth0 时被 MASQUERADE 改写。反向的 iroute 打通见后面的 ccd 小节。
服务端核心配置
单文件 server.conf,关键决策是所有证书密钥全部内联(<ca></ca>、<cert></cert>、<key></key> 块),不引用外部路径:
1 | port 1194 |
几个点说明:
dev tun路由模式:客户端拿到的是三层网络,能直接访问对端内网,比tap桥接模式干净;route+push route分工:route让服务端认识对端网段,客户端访问该网段的流量才会被送进来;- 证书内联:升级服务端时不用同步一堆文件,
scp一个 conf 就完事。
NAT:用 systemd drop-in,不碰 iptables-persistent
VPN 客户端访问家里内网需要 MASQUERADE,最可靠的做法是挂在服务的生命周期上,而不是手动 iptables-save:
1 | # /etc/systemd/system/openvpn-server@server.service.d/nat.conf |
服务起来自动加规则,停服务自动撤规则。为什么不装 iptables-persistent:多一层持久化机制就多一个故障点,规则跟着服务走,行为完全可预期,重启服务器也不丢(systemd 会重新拉起)。
客户端签发脚本
自用场景,easy-rsa 的手工流程太啰嗦,封一个脚本:/root/ovpn-addclient.sh <名字>:
1 |
|
客户端拿到 .ovpn 文件,任何平台(Windows/macOS/Android/iOS)的 OpenVPN 客户端导入即用,零额外配置。吊销就用 ./easyrsa revoke <名字> + 更新 CRL,脚本记得把这个也包进去。
ccd:给固定客户端绑内网路由
有一台客户端是”家里的路由器”,需要让 VPN 另一端的设备也能主动访问家里网段——这时单向 route 不够,要双向打通。用客户端配置目录(ccd):
1 | # /etc/openvpn/ccd/home-router |
iroute 告诉服务端”这个客户端后面挂着 192.168.110.0/24 这个网段”,配合固定的 ifconfig-push 虚拟 IP,双向流量都能正确寻址。前提是对端路由器自己也配了回程路由(把 10.8.0.0/24 的流量指到 OpenVPN 客户端机器),只改一边永远是单向通。
运维备忘
1 | systemctl status openvpn-server@server # 看状态 |
日志里 Peer Connection Initiated / MULTI: Learn: ... 是客户端上线/学习路由的标志,排查”通了又断”的问题先看这两行。
小结
这套方案的三个关键决策:配置全内联(迁移无脑)、NAT 用 systemd drop-in(行为可预期)、ccd + iroute 打通双向内网(家用场景刚需)。客户端一个 .ovpn 文件走天下,签发吊销全脚本化,自用完全够。