API now returns:
{
"logs": [...], // ConnectionLog array (same fields as before)
"_diag": [...] // status.log paths/existence/parse status per instance
}
Frontend updated to handle both array (legacy) and object format.
This makes it easy to diagnose:
- Which status.log paths the backend looked at
- Whether files exist and their sizes
- How many entries were parsed
- Any parse errors
User just needs to: git pull && rebuild && restart on production.
OpenVPN Manager
一个开箱即用的 OpenVPN Web 管理控制台 —— 多实例托管、客户端证书一键签发、流量审计、证书到期提醒、自动备份与恢复。 基于 Go (Gin) + Vue 3 + Element Plus + ECharts,单二进制部署。
目录
功能特性
| 模块 | 说明 |
|---|---|
| 多实例管理 | 同一台机器上跑多个 OpenVPN 实例,每个独立端口/协议/子网/PKI |
| 客户端证书 | 一键签发,自动生成 .ovpn(内嵌 CA/Cert/Key/TLS-Auth),无需额外文件 |
| 固定 IP | 通过 CCD (client-config-dir) 为指定用户分配固定 VPN IP |
| 访问控制(白名单) | 实例/用户两层 allow_networks,合并生效;服务端 iptables 强制隔离 |
| 多账号管理 | db.json 中存 bcrypt 哈希,可创建多个 admin/operator 账号,首登强制改密 |
| 启停控制 | Web 一键启动/停止实例,显示 PID 与状态 |
| 流量审计 | 解析 status-version 3 输出,记录上下行字节/连接时长 |
| 证书到期提醒 | 仪表盘统计 30 天内到期的证书,单独证书管理页查看完整清单 |
| 自动备份 | 一键打包 PKI + 实例配置 + 客户端配置为 tar.gz |
| 一键恢复 | 上传/选择已有备份,直接覆盖还原 |
| 操作审计 | 所有写操作(创建/修改/删除/吊销/备份)持久化,记录操作者/IP/结果 |
| JWT 鉴权 | 登录后 12 小时有效 token,无状态可水平扩展 |
架构概览
┌──────────────────────────┐
│ 浏览器 (Vue 3 SPA) │
│ Element Plus + ECharts │
└──────────────┬───────────┘
│ HTTPS/HTTP (8089)
▼
┌──────────────────────────┐ ┌────────────────────────┐
│ Go HTTP 服务 (Gin) │ ◄──┐ │ systemd: │
│ - JWT 鉴权 │ │ │ openvpn-manager.service│
│ - REST API │ │ └────────────────────────┘
│ - OpenVPN 进程管理 │ │
│ - OpenSSL 证书签发/吊销 │ │ ┌────────────────────────┐
└──────────────┬───────────┘ │ │ /usr/sbin/openvpn │
│ ├───►│ --config <conf> │
│ │ │ --cd <dir> │
▼ │ │ → status.log │
┌──────────────────────────┐ │ └────────────────────────┘
│ <DataDir> │ │
│ pki/ │ │
│ instances/<name>/... │ │
│ clients/<inst>/<user>/ │ │
│ backups/ │ │
│ db.json │ │
└──────────────────────────┘ │
│
┌────────────────┘
│
▼
(所有写操作) → audit_logs[]
一、服务端部署
系统要求
- 操作系统:Ubuntu 20.04+ / Debian 11+ / CentOS Stream 9+ / Rocky 9+
- CPU:1 核即可
- 内存:最低 512 MB
- 磁盘:1 GB(证书 + 用户越多占用越大)
- 网络:开放
8089端口(管理界面) + 每个 OpenVPN 实例一个 UDP/TCP 端口(默认 1194) - 权限:必须以
root启动(OpenVPN 需要TUN/TAP设备权限) - 依赖工具(脚本自动安装):
openvpn≥ 2.5openssl≥ 1.1nodejs≥ 18npmgolang≥ 1.21
一键安装
git clone ssh://git@git.cnbugs.com:10022/AI-Agent/openvpn-manager.git
cd openvpn-manager
chmod +x scripts/install.sh
sudo ./scripts/install.sh
脚本会做这些事:
- 识别发行版,自动选 apt/dnf/yum
- 安装系统依赖
npm install+npm run build构建前端go build编译后端二进制- 拷贝到
/opt/openvpn-manager - 注册 systemd 单元并启动
- 健康检查
/api/health - 打印访问地址和默认账号
成功后会看到:
================================================================
OpenVPN Manager 安装完成
================================================================
访问地址 : http://<服务器IP>:8089
用户名 : admin
密码 : admin123
安装目录 : /opt/openvpn-manager
数据目录 : /opt/openvpn-manager/data
配置单元 : /etc/systemd/system/openvpn-manager.service
================================================================
安装参数
sudo ./scripts/install.sh \
--port 9090 \
--user admin \
--pass 'StrongPass!2026' \
--dir /opt/openvpn-manager
| 参数 | 默认值 | 说明 |
|---|---|---|
--port |
8089 |
Web 管理端口 |
--user |
admin |
初始管理员用户名 |
--pass |
admin123 |
初始管理员密码,生产环境必须改 |
--dir |
/opt/openvpn-manager |
安装目录 |
-u, --uninstall |
- | 卸载(停服务、删除安装目录、清理 systemd) |
JWT 签名密钥会在安装时自动生成 64 位随机十六进制串写入
/etc/systemd/system/openvpn-manager.service的OVPNMGR_JWT_SECRET环境变量,不要复制生产环境的这个文件。
手动安装
适合不想用 systemd 的场景(如 Docker):
# 1. 装依赖
apt-get install -y openvpn openssl nodejs npm golang-go git # Debian/Ubuntu
# 或
dnf install -y openvpn openssl nodejs npm golang git # RHEL/Fedora
# 2. 编译
git clone <this-repo> && cd openvpn-manager
cd frontend && npm install --include=dev && npm run build && cd ..
cd backend && go build -o ../bin/openvpn-manager ./cmd/server && cd ..
# 3. 运行
mkdir -p data
OVPNMGR_PORT=8089 \
OVPNMGR_ADMIN_USER=admin \
OVPNMGR_ADMIN_PASS='your-password' \
OVPNMGR_JWT_SECRET=$(openssl rand -hex 32) \
./bin/openvpn-manager --data ./data --dist ./dist
目录结构
/opt/openvpn-manager/
├── bin/openvpn-manager # Go 编译后的二进制 (~21MB)
├── dist/ # Vue 构建产物 (index.html + assets/)
├── data/ # 数据目录,定期备份
│ ├── db.json # 元数据(JSON):实例/用户/审计
│ ├── pki/
│ │ ├── ca.crt # CA 证书(全局共享)
│ │ ├── ca.key # CA 私钥(权限 0600)
│ │ ├── dh.pem # DH 参数
│ │ └── ta.key # TLS-Auth 共享密钥
│ ├── instances/
│ │ └── <instance-name>/
│ │ ├── server.conf # OpenVPN 服务端配置
│ │ ├── status.log # OpenVPN 状态文件(10s 周期)
│ │ ├── ipp.txt # IP 池持久化
│ │ ├── ccd/ # 客户端配置目录(固定 IP)
│ │ ├── logs/openvpn.log
│ │ └── pki/
│ │ ├── issued/<cn>.crt
│ │ └── private/<cn>.key
│ ├── clients/
│ │ └── <instance>/<user>.ovpn
│ └── backups/ # 自动备份目录
└── .env # 环境变量(权限 0600)
systemd 管理
systemctl status openvpn-manager # 状态
systemctl restart openvpn-manager # 重启
systemctl stop openvpn-manager # 停止
journalctl -u openvpn-manager -f # 跟踪日志(ctrl+c 退出)
journalctl -u openvpn-manager -n 200 # 最近 200 行
修改配置后需要:
systemctl edit openvpn-manager # 改环境变量(创建 override.conf)
systemctl daemon-reload
systemctl restart openvpn-manager
或者直接编辑主单元:
systemctl edit --full openvpn-manager
升级
cd /path/to/openvpn-manager
git pull
sudo ./scripts/install.sh
install.sh 会:
- 重新编译并覆盖二进制
- 保留
data/、backups/、dist/(原压缩产物) - 重启服务
重要:升级前请先在 Web 界面"备份与恢复"页面手动做一次备份,以防万一。
卸载
sudo ./scripts/install.sh -u
此命令会:停服务、禁用自启、删除 /etc/systemd/system/openvpn-manager.service、删除 /opt/openvpn-manager。
源码目录不会被删除,如需彻底清理请手动 rm -rf。
二、首次配置
登录 Web 控制台
浏览器访问 http://<服务器IP>:8089/。
默认账号:
- 用户名:
admin - 密码:
admin123
修改默认密码
⚠️ 生产环境第一步。
首次登录强制改密
首次访问用默认账号 admin/admin123 登录后,系统强制弹出"修改初始密码"对话框,
必须改成 ≥6 位的强密码才能继续使用,无法跳过。这一步密码修改后会写入 data/db.json,
之后不再需要重启服务,密码以 bcrypt 哈希持久化。
通过 Web 修改自己的密码
右上角 admin 下拉 → "修改密码" → 填写当前密码 + 新密码 → 保存,立即生效。
创建/管理其他账号
Web → 左侧"管理员"菜单(admin role 才可见):
| 操作 | 说明 |
|---|---|
| 新建账号 | 设置用户名、密码、角色(admin / operator) |
| 重置密码 | 不知道旧密码也能强制改密,新密码立即生效 |
| 启用/禁用 | 禁用后该账号无法登录(已登录的 token 仍可短期使用) |
| 删除 | 不能删除自己、不能删除最后一个 admin |
所有账号操作都进入审计日志。
通过 systemd 环境变量重置(忘记密码时)
如果你把所有 admin 都禁用/删除了,或者忘了所有密码,可以临时用环境变量密码 覆盖(只用于"首次登录然后改密",不持久):
systemctl edit --full openvpn-manager
# 找到 OVPNMGR_ADMIN_PASS 一行,改成你临时用的密码
systemctl daemon-reload
systemctl restart openvpn-manager
# 用新密码登录,系统会触发 SeedDefaultAdminIfEmpty
# 注:此路径只在 db.json 中无任何 admin 时生效;否则会校验 db.json 中的账号
更可靠的做法:直接编辑 data/db.json,把 password_hash 替换为 bcrypt 哈希
(用 htpasswd -bnBC 10 "" yourpass | tr -d ':\n' 生成)后重启服务。
环境变量里的
OVPNMGR_ADMIN_USER/OVPNMGR_ADMIN_PASS仅在数据库为空时作为初始 seed 使用。
创建第一个实例
Web → "实例管理" → "新建实例":
| 字段 | 推荐值 | 说明 |
|---|---|---|
| 名称 | prod |
字母数字下划线,作为目录名,不可重复 |
| 端口 | 1194 |
OpenVPN 监听端口,不能与已有服务冲突 |
| 协议 | udp |
udp 性能好,tcp 穿透性强 |
| 设备 | tun |
tun 路由模式(常用),tap 桥接模式 |
| 子网 | 10.8.0.0/24 |
给客户端分配的 VPN 内网网段 |
| 加密 | AES-256-GCM |
AES-128-GCM 更快,CHACHA20-POLY1305 适合 ARM |
| 摘要 | SHA256 |
|
| 推送 DNS | dhcp-option DNS 1.1.1.1dhcp-option DNS 8.8.8.8 |
一行一条 |
| 推送路由 | 192.168.1.0 255.255.255.0 |
让客户端能访问内网,每行一条 CIDR |
点"保存"会自动:
- 创建实例目录
- 用全局 CA 签发服务端证书
- 生成
server.conf
然后点列表里的"启动"按钮即可。如果失败,看 journalctl -u openvpn-manager -n 50。
创建客户端用户并下载配置
Web → "用户管理":
- 顶部下拉框选择实例
- "新建用户":
- 用户名(CN):
alice(字母数字下划线,作为证书 CN) - 备注:
Alice 张三 - 邮箱:
alice@example.com - 固定 IP:留空为动态;若填
10.8.0.10,Alice 每次连上都是这个 VPN IP
- 用户名(CN):
- 保存后表格出现 alice,点"下载 .ovpn"
下载的文件约 4-5 KB,里面已经内嵌了:
- CA 证书(
<ca>...</ca>) - 客户端证书(
<cert>...</cert>) - 客户端私钥(
<key>...</key>) - TLS-Auth 密钥(
<tls-auth>...</tls-auth>,key-direction 1)
直接发给用户即可,无需额外的 ca.crt 等文件。
防火墙与公网暴露
-
Web 管理端口(默认 8089)不建议直接暴露公网,建议:
- 用防火墙只允许公司/家庭 IP 访问
- 或反代 + HTTPS + Basic Auth
- 或 SSH 端口转发
ssh -L 8089:127.0.0.1:8089 user@server
-
OpenVPN 实例端口必须开放给需要连入的客户端。UDP 优先(性能好):
# ufw
ufw allow 1194/udp
ufw allow 1194/tcp # 如果实例用 TCP
# firewalld
firewall-cmd --permanent --add-port=1194/udp
firewall-cmd --reload
- 若服务器在 NAT 后(如家用宽带),需要在路由器做端口映射 UDP 1194 → 服务器内网 IP。
三、访问控制(白名单模式)
核心需求:VPN 用户登录后,只能访问你明确允许的内网网段,默认与所有内网隔离。
工作原理
每个实例有一个 access_mode 字段:
open(默认):不限制,客户端可访问所有可达网段whitelist:仅允许访问白名单中列出的内网网段
当 access_mode=whitelist 时:
- 实例配置
allow_networks:该实例下所有用户共享的允许网段 - 用户配置
allow_networks:单个用户的额外允许网段(在实例基础上叠加) - 实际生效 = 实例白名单 ∪ 用户白名单(去重)
- 服务端强制:
- OpenVPN 自动生成
client-connect.sh/client-disconnect.sh脚本 - 每个用户连接时,服务端的 FORWARD 链插入 iptables ACCEPT 规则,只放行到白名单网段的流量
- 其他内网流量在服务端被 REJECT(客户端看到的是"无法连接",而非"超时")
- OpenVPN 自动生成
- 客户端推送:
- 自动
push "redirect-gateway def1 bypass-dhcp"让客户端把所有流量都走 VPN(否则白名单没意义) - 自动按白名单
push route ...让客户端知道这些网段在 VPN 后
- 自动
双重防护:即使客户端操作系统被绕过,iptables 仍会拒绝非法流量。
使用方法
Web 端
-
实例管理 → 新建/编辑实例
- "访问控制"下拉选 "白名单(whitelist)"
- "允许网段"标签输入:每行一个 CIDR,如
192.168.1.0/24、10.0.0.0/8 - 保存
-
用户管理 → 编辑用户(可选)
- "额外允许网段":这个用户特有的、实例未列出的网段
- 保存
-
启动实例 —— 实例启动时,会执行一次
iptables -A FORWARD -i tunX -j REJECT(仅白名单模式)作为兜底
命令行(API)
# 创建白名单实例
curl -X POST http://localhost:8089/api/instances \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{
"name": "internal",
"port": 1194,
"subnet": "10.8.0.0/24",
"access_mode": "whitelist",
"allow_networks": ["192.168.1.0/24", "10.0.0.0/8"]
}'
# 创建用户,额外允许一个网段
curl -X POST http://localhost:8089/api/instances/$IID/users \
-H "Authorization: Bearer $TOKEN" \
-d '{"username":"alice","allow_networks":["172.16.0.0/16"]}'
验证白名单生效
实例启动后,登录客户端:
# 1. 客户端连上 VPN,确认 VPN IP 拿到
ip addr show | grep 10.8.0
# 2. 测允许的网段 - 应通
ping 192.168.1.1
# 3. 测未允许的网段 - 应 REJECT(ICMP net unreachable)
ping 192.168.50.1 # 不在白名单,应该不通
服务端验证 iptables 规则:
iptables -L FORWARD -n --line-numbers
# 应看到 -i tun0 -j REJECT 在底部,前面若干 -s <vpn-ip> -d <allowed-net> -j ACCEPT
限制与注意
| 项 | 说明 |
|---|---|
| 仅 IPv4 | IPv6 白名单需要扩展 client-connect.sh 使用 route-ipv6,目前未实现 |
| 需要 root + iptables | 若运行在容器内/无 root,白名单模式会以"open"模式退化运行 |
| 端口转发必须由客户端发起 | 客户端连入后,服务端只允许它主动访问白名单中的目标;不能用 VPN 当跳板从外部进入内网 |
| 修改 allow_networks 后 | 已有用户需重新连接一次才能拿到新的 push route;新用户即时生效 |
| 删除/吊销用户 | 会清掉 iptables 中对应的 ACCEPT 规则,不影响其他用户 |
常见误用
| 错误 | 后果 |
|---|---|
| 客户端关掉 VPN 网关 | 服务端 iptables 仍会拒绝非白名单流量,客户端访问不到 |
| 客户端把 allowed 网段路由改成另一条 | 服务端 iptables 在 FORWARD 链过滤,客户端改路由无效 |
| 忘记添加 DNS 服务器 | 客户端没法解析域名 —— 在"允许网段"加上 DNS 服务器的 IP(如 8.8.8.8/32) |
三、客户端使用
配置文件说明
下载的 alice.ovpn 是单一文件,内容大致为:
client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
cipher AES-256-GCM
auth SHA256
remote-cert-tls server
verb 3
<ca>
-----BEGIN CERTIFICATE-----
... CA 证书内容 ...
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
... 客户端证书 ...
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
... 客户端私钥(请勿泄露)...
-----END PRIVATE KEY-----
</key>
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
... TLS-Auth 共享密钥 ...
-----END OpenVPN Static key V1-----
</tls-auth>
key-direction 1
注意 remote 行是客户端实际连接的服务器地址,默认是 vpn.example.com,需要改成你自己的服务器公网域名/IP。
修改方法:
- 在 Web 界面"用户管理"页面,顶部"客户端连接的远端域名/IP"输入框填入你的服务器地址(如
vpn.your-domain.com或1.2.3.4),再点"下载 .ovpn" - 或下载后用文本编辑器手动改
remote行
Windows
推荐:OpenVPN 官方 GUI 客户端
- 下载:https://openvpn.net/community-downloads/ → 选择 "Windows 64-bit MSI installer"
- 安装(一路下一步,会安装一个虚拟网卡驱动,需要管理员权限)
- 把
alice.ovpn放到C:\Users\<你>\OpenVPN\config\ - 启动 "OpenVPN GUI"(开始菜单里),右下角会出现托盘图标
- 右键托盘图标 → Connect
- 第一次会弹窗请求管理员权限(用于配置路由)
- 连接成功后托盘变绿,会分配一个
10.8.0.x的 VPN IP
验证:
ipconfig /all
# 看到 "10.8.0.x" 的 Tap adapter IPv4 地址即成功
ping 10.8.0.1
# 应该通(10.8.0.1 是 OpenVPN 服务端在子网里的网关)
macOS
选项 1:Tunnelblick(免费开源,推荐)
- 下载:https://tunnelblick.net/
- 安装,会自动安装
tun驱动 - 双击
alice.ovpn,Tunnelblick 会问你"是否为所有用户安装",选"仅我"即可 - 菜单栏点 Tunnelblick 图标 → Connect alice
- 状态变绿即成功
选项 2:OpenVPN Connect(官方)
从 Mac App Store 搜索 "OpenVPN" 安装。
Linux
命令行 (systemd 服务)
# Debian/Ubuntu
sudo apt-get install -y openvpn
# RHEL/Fedora
sudo dnf install -y openvpn
# 连接
sudo openvpn --config alice.ovpn --daemon
# 或前台运行(能看到日志)
sudo openvpn --config alice.ovpn
NetworkManager 图形客户端
sudo apt-get install -y network-manager-openvpn network-manager-openvpn-gnome # Debian/Ubuntu
sudo dnf install -y NetworkManager-openvpn NetworkManager-openvpn-gnome # Fedora
设置 → 网络 → + VPN → "从文件导入 VPN" → 选 alice.ovpn → 保存 → 连接。
Android
- 安装"OpenVPN Connect"(Google Play / F-Droid 都有)
- 把
alice.ovpn通过 USB / 邮件 / 网盘传到手机 - 用文件管理器打开
.ovpn,系统会询问"用 OpenVPN 打开" - 点右上角"连接"
- 首次会提示接受 VPN 配置,点确定
- 通知栏出现钥匙图标即连接成功
iOS
- App Store 搜索"OpenVPN"安装
- 用"文件"App 把
alice.ovpn传到手机(隔空投送也行) - 在"文件"App 里点击
.ovpn,选择"用 OpenVPN 打开" - 点"ADD"导入 → 点右上角开关连接
- 系统会弹窗请求添加 VPN 配置,允许
- 设置 → 通用 → VPN 里可以看到状态
验证连接
无论哪个平台,连接成功后都可以这样验证:
- VPN IP:看分配的 IP 是否在配置的子网里(如
10.8.0.x) - Ping 服务端:从客户端
ping 10.8.0.1应该通 - 公网出口:从客户端
curl ifconfig.me应显示服务器公网 IP - DNS 解析:如果推送了 DNS,客户端
/etc/resolv.conf(Linux)应看到推送的 DNS
在 Web 控制台:
- "仪表盘"会实时显示当前在线客户端数(10 秒刷新)
- "实例管理" → 点实例 → 不会直接显示在线,但可以看 status.log
- "连接日志"显示历史连接记录
排障
| 症状 | 可能原因 |
|---|---|
| 连接后立刻断开 | 客户端证书与 CA 不匹配;服务端证书过期 |
| 拿到 IP 但 ping 不通服务端 | 防火墙没允许 UDP 1194;服务端没启用 IP 转发 |
| 拿到 IP 但访问不了互联网 | 没推送 DNS,或客户端没把 VPN 设为默认网关 |
| Android 连不上 | 服务器在 NAT 后,检查运营商是否屏蔽 UDP |
| iOS 连不上 | 看 OpenVPN 日志(应用内 OpenVPN → Settings → Log) |
五、API 参考
所有 /api 路径(除 /login、/health)都需要 Authorization: Bearer <token>。
完整列表见 docs/API.md 或启动后查看 internal/api/router.go。
简单列几个常用的:
| 方法 | 路径 | 用途 |
|---|---|---|
| POST | /api/login |
登录,返回 {token, username} |
| GET | /api/dashboard |
仪表盘汇总 |
| GET/POST | /api/instances |
列出/创建实例 |
| GET/PUT/DELETE | /api/instances/:id |
单实例 CRUD |
| POST | /api/instances/:id/start / /stop |
启停 |
| GET/POST | /api/instances/:id/users |
用户列表/新建 |
| POST | /api/instances/:id/users/:uid/revoke |
吊销 |
| DELETE | /api/instances/:id/users/:uid |
删除 |
| GET | /api/instances/:id/users/:uid/ovpn?host=X |
下载 .ovpn |
| GET | /api/certs |
证书到期清单 |
| GET | /api/connlogs?instance=X |
连接日志 |
| GET/POST/DELETE | /api/backups / /api/backups/:id |
备份管理 |
| POST | /api/backups/:id/restore |
恢复 |
| GET | /api/audits |
审计日志 |
示例:
# 登录
TOKEN=$(curl -s -X POST http://localhost:8089/api/login \
-H 'content-type: application/json' \
-d '{"username":"admin","password":"admin123"}' | jq -r .token)
# 创建实例
curl -X POST http://localhost:8089/api/instances \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"name":"prod","port":1194,"subnet":"10.8.0.0/24"}'
六、常见问题
Q: 服务启动后访问 8089 提示"无法连接"?
排查顺序:
systemctl status openvpn-manager # 进程在不在?
journalctl -u openvpn-manager -n 50 # 启动报错?
ss -tlnp | grep 8089 # 端口在听吗?
curl http://127.0.0.1:8089/api/health # 本机能访问吗?
常见原因:go/nodejs/openvpn 没装或版本太低。
Q: 在实例列表点"启动"提示成功,但状态一直 stopped?
OpenVPN 需要 root 启动。如果你的 systemd 单元不是 root 运行,启动会失败。检查:
ps aux | grep openvpn-manager # 确认主进程是 root
cat /etc/systemd/system/openvpn-manager.service | grep User
# 应该 User=root
Q: 下载的 .ovpn 客户端连不上?
- 确认服务器防火墙/路由器开放了对应端口(UDP 1194 等)
- 客户端能 ping 通服务器公网 IP 吗?
- 服务端 status.log 有没有客户端连接尝试?
Q: 怎么从备份恢复?
Web → "备份与恢复" → 选中备份 → "恢复"。会覆盖现有 pki/、instances/、clients/,操作前先做一次新的备份以防万一。
Q: 能用 Nginx 反代 + HTTPS 吗?
可以,示例 Nginx 配置:
server {
listen 443 ssl http2;
server_name vpn-admin.example.com;
ssl_certificate /etc/letsencrypt/live/vpn-admin.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vpn-admin.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8089;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
注意 OpenVPN 自身的 UDP/TCP 端口(1194 等)不能走 Nginx,要单独放行。
Q: 支持 IPv6 吗?
服务端支持(把 proto 改成 udp6 或 tcp6,子网用 IPv6 CIDR),但本项目目前 UI 主要按 IPv4 写,IPv6 子网需要手动编辑 server.conf(用"自定义"字段)。
七、开发
# 后端
cd backend
go run ./cmd/server --data ../data --dist ../dist
# 前端(开发热重载,会自动代理 /api 到 :8089)
cd frontend
npm install
npm run dev
# 浏览器打开 http://localhost:3000
调试模式日志:
OVPNMGR_LOG_LEVEL=debug ./bin/openvpn-manager --data ./data --dist ./dist
跑测试:
cd backend && go test ./...
cd frontend && npm run build # 顺便当 type/lint 校验
构建发布版:
# 前端
cd frontend && npm run build && cd ..
# 后端(静态链接、剥离调试符号)
cd backend
CGO_ENABLED=0 go build -ldflags "-s -w" -trimpath -o ../bin/openvpn-manager ./cmd/server
许可证
致谢
本项目使用了以下开源软件: