# OpenVPN Manager > 一个开箱即用的 OpenVPN Web 管理控制台 —— 多实例托管、客户端证书一键签发、流量审计、证书到期提醒、自动备份与恢复。 > 基于 **Go (Gin) + Vue 3 + Element Plus + ECharts**,单二进制部署。 ![dashboard](https://img.shields.io/badge/Go-1.21+-00ADD8?logo=go) ![Vue](https://img.shields.io/badge/Vue-3-4FC08D?logo=vue.js) ![License](https://img.shields.io/badge/license-MIT-green) --- ## 目录 - [功能特性](#功能特性) - [架构概览](#架构概览) - [一、服务端部署](#一服务端部署) - [系统要求](#系统要求) - [一键安装](#一键安装) - [安装参数](#安装参数) - [手动安装](#手动安装) - [目录结构](#目录结构) - [systemd 管理](#systemd-管理) - [升级](#升级) - [卸载](#卸载) - [二、首次配置](#二首次配置) - [登录 Web 控制台](#登录-web-控制台) - [修改默认密码](#修改默认密码) - [创建第一个实例](#创建第一个实例) - [创建客户端用户并下载配置](#创建客户端用户并下载配置) - [防火墙与公网暴露](#防火墙与公网暴露) - [三、访问控制(白名单模式)](#三访问控制白名单模式) - [四、客户端使用](#四客户端使用) - [配置文件说明](#配置文件说明) - [Windows](#windows) - [macOS](#macos) - [Linux](#linux) - [Android](#android) - [iOS](#ios) - [验证连接](#验证连接) - [五、API 参考](#五api-参考) - [六、常见问题](#六常见问题) - [七、开发](#七开发) - [许可证](#许可证) --- ## 功能特性 | 模块 | 说明 | | ---- | ---- | | 多实例管理 | 同一台机器上跑多个 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 │ │ │ │ --cd │ ▼ │ │ → status.log │ ┌──────────────────────────┐ │ └────────────────────────┘ │ │ │ │ pki/ │ │ │ instances//... │ │ │ clients/// │ │ │ 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.5 - `openssl` ≥ 1.1 - `nodejs` ≥ 18 - `npm` - `golang` ≥ 1.21 ## 一键安装 ```bash 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 ``` 脚本会做这些事: 1. 识别发行版,自动选 apt/dnf/yum 2. 安装系统依赖 3. `npm install` + `npm run build` 构建前端 4. `go build` 编译后端二进制 5. 拷贝到 `/opt/openvpn-manager` 6. 注册 systemd 单元并启动 7. 健康检查 `/api/health` 8. 打印访问地址和默认账号 成功后会看到: ``` ================================================================ OpenVPN Manager 安装完成 ================================================================ 访问地址 : http://<服务器IP>:8089 用户名 : admin 密码 : admin123 安装目录 : /opt/openvpn-manager 数据目录 : /opt/openvpn-manager/data 配置单元 : /etc/systemd/system/openvpn-manager.service ================================================================ ``` ## 安装参数 ```bash 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): ```bash # 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 && 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/ │ │ └── / │ │ ├── server.conf # OpenVPN 服务端配置 │ │ ├── status.log # OpenVPN 状态文件(10s 周期) │ │ ├── ipp.txt # IP 池持久化 │ │ ├── ccd/ # 客户端配置目录(固定 IP) │ │ ├── logs/openvpn.log │ │ └── pki/ │ │ ├── issued/.crt │ │ └── private/.key │ ├── clients/ │ │ └── /.ovpn │ └── backups/ # 自动备份目录 └── .env # 环境变量(权限 0600) ``` ## systemd 管理 ```bash 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 行 ``` 修改配置后需要: ```bash systemctl edit openvpn-manager # 改环境变量(创建 override.conf) systemctl daemon-reload systemctl restart openvpn-manager ``` 或者直接编辑主单元: ```bash systemctl edit --full openvpn-manager ``` ## 升级 ```bash cd /path/to/openvpn-manager git pull sudo ./scripts/install.sh ``` `install.sh` 会: - 重新编译并覆盖二进制 - 保留 `data/`、`backups/`、`dist/`(原压缩产物) - 重启服务 **重要**:升级前请先在 Web 界面"备份与恢复"页面手动做一次备份,以防万一。 ## 卸载 ```bash 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 都禁用/删除了,或者忘了所有密码,可以临时用环境变量密码 覆盖(只用于"首次登录然后改密",不持久): ```bash 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.1`
`dhcp-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 → "用户管理": 1. 顶部下拉框选择实例 2. "新建用户": - 用户名(CN):`alice`(字母数字下划线,作为证书 CN) - 备注:`Alice 张三` - 邮箱:`alice@example.com` - 固定 IP:留空为动态;若填 `10.8.0.10`,Alice 每次连上都是这个 VPN IP 3. 保存后表格出现 alice,点"下载 .ovpn" 下载的文件约 4-5 KB,里面已经内嵌了: - CA 证书(`...`) - 客户端证书(`...`) - 客户端私钥(`...`) - TLS-Auth 密钥(`...`,`key-direction 1`) 直接发给用户即可,无需额外的 `ca.crt` 等文件。 ## 防火墙与公网暴露 1. Web 管理端口(默认 8089)**不建议直接暴露公网**,建议: - 用防火墙只允许公司/家庭 IP 访问 - 或反代 + HTTPS + Basic Auth - 或 SSH 端口转发 `ssh -L 8089:127.0.0.1:8089 user@server` 2. OpenVPN 实例端口**必须**开放给需要连入的客户端。UDP 优先(性能好): ```bash # ufw ufw allow 1194/udp ufw allow 1194/tcp # 如果实例用 TCP # firewalld firewall-cmd --permanent --add-port=1194/udp firewall-cmd --reload ``` 3. 若服务器在 NAT 后(如家用宽带),需要在路由器做端口映射 UDP 1194 → 服务器内网 IP。 --- # 三、访问控制(白名单模式) **核心需求**:VPN 用户登录后,只能访问你明确允许的内网网段,默认与所有内网隔离。 ## 工作原理 每个实例有一个 `access_mode` 字段: - `open`(默认):不限制,客户端可访问所有可达网段 - `whitelist`:仅允许访问白名单中列出的内网网段 当 `access_mode=whitelist` 时: 1. **实例配置 `allow_networks`**:该实例下所有用户共享的允许网段 2. **用户配置 `allow_networks`**:单个用户的额外允许网段(在实例基础上叠加) 3. **实际生效** = 实例白名单 ∪ 用户白名单(去重) 4. **服务端强制**: - OpenVPN 自动生成 `client-connect.sh` / `client-disconnect.sh` 脚本 - 每个用户连接时,服务端的 FORWARD 链插入 iptables ACCEPT 规则,只放行到白名单网段的流量 - 其他内网流量在服务端被 REJECT(客户端看到的是"无法连接",而非"超时") 5. **客户端推送**: - 自动 `push "redirect-gateway def1 bypass-dhcp"` 让客户端把所有流量都走 VPN(否则白名单没意义) - 自动按白名单 `push route ...` 让客户端知道这些网段在 VPN 后 > 双重防护:即使客户端操作系统被绕过,iptables 仍会拒绝非法流量。 ## 使用方法 ### Web 端 1. **实例管理 → 新建/编辑实例** - "访问控制"下拉选 **"白名单(whitelist)"** - "允许网段"标签输入:每行一个 CIDR,如 `192.168.1.0/24`、`10.0.0.0/8` - 保存 2. **用户管理 → 编辑用户**(可选) - "额外允许网段":这个用户特有的、实例未列出的网段 - 保存 3. **启动实例** —— 实例启动时,会执行一次 `iptables -A FORWARD -i tunX -j REJECT`(仅白名单模式)作为兜底 ### 命令行(API) ```bash # 创建白名单实例 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"]}' ``` ## 验证白名单生效 实例启动后,登录客户端: ```bash # 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 规则: ```bash iptables -L FORWARD -n --line-numbers # 应看到 -i tun0 -j REJECT 在底部,前面若干 -s -d -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 -----BEGIN CERTIFICATE----- ... CA 证书内容 ... -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- ... 客户端证书 ... -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- ... 客户端私钥(请勿泄露)... -----END PRIVATE KEY----- -----BEGIN OpenVPN Static key V1----- ... TLS-Auth 共享密钥 ... -----END OpenVPN Static key V1----- key-direction 1 ``` 注意 `remote` 行是客户端实际连接的服务器地址,**默认是 `vpn.example.com`,需要改成你自己的服务器公网域名/IP**。 修改方法: - 在 Web 界面"用户管理"页面,顶部"客户端连接的远端域名/IP"输入框填入你的服务器地址(如 `vpn.your-domain.com` 或 `1.2.3.4`),再点"下载 .ovpn" - 或下载后用文本编辑器手动改 `remote` 行 ## Windows **推荐**:OpenVPN 官方 GUI 客户端 1. 下载:https://openvpn.net/community-downloads/ → 选择 "Windows 64-bit MSI installer" 2. 安装(一路下一步,会安装一个虚拟网卡驱动,需要管理员权限) 3. 把 `alice.ovpn` 放到 `C:\Users\<你>\OpenVPN\config\` 4. 启动 "OpenVPN GUI"(开始菜单里),右下角会出现托盘图标 5. 右键托盘图标 → Connect 6. 第一次会弹窗请求管理员权限(用于配置路由) 7. 连接成功后托盘变绿,会分配一个 `10.8.0.x` 的 VPN IP **验证**: ```cmd ipconfig /all # 看到 "10.8.0.x" 的 Tap adapter IPv4 地址即成功 ping 10.8.0.1 # 应该通(10.8.0.1 是 OpenVPN 服务端在子网里的网关) ``` ## macOS **选项 1:Tunnelblick**(免费开源,推荐) 1. 下载:https://tunnelblick.net/ 2. 安装,会自动安装 `tun` 驱动 3. 双击 `alice.ovpn`,Tunnelblick 会问你"是否为所有用户安装",选"仅我"即可 4. 菜单栏点 Tunnelblick 图标 → Connect alice 5. 状态变绿即成功 **选项 2:OpenVPN Connect**(官方) 从 Mac App Store 搜索 "OpenVPN" 安装。 ## Linux ### 命令行 (systemd 服务) ```bash # 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 图形客户端 ```bash 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 1. 安装"OpenVPN Connect"(Google Play / F-Droid 都有) 2. 把 `alice.ovpn` 通过 USB / 邮件 / 网盘传到手机 3. 用文件管理器打开 `.ovpn`,系统会询问"用 OpenVPN 打开" 4. 点右上角"连接" 5. 首次会提示接受 VPN 配置,点确定 6. 通知栏出现钥匙图标即连接成功 ## iOS 1. App Store 搜索"OpenVPN"安装 2. 用"文件"App 把 `alice.ovpn` 传到手机(隔空投送也行) 3. 在"文件"App 里点击 `.ovpn`,选择"用 OpenVPN 打开" 4. 点"ADD"导入 → 点右上角开关连接 5. 系统会弹窗请求添加 VPN 配置,允许 6. 设置 → 通用 → VPN 里可以看到状态 ## 验证连接 无论哪个平台,连接成功后都可以这样验证: 1. **VPN IP**:看分配的 IP 是否在配置的子网里(如 `10.8.0.x`) 2. **Ping 服务端**:从客户端 `ping 10.8.0.1` 应该通 3. **公网出口**:从客户端 `curl ifconfig.me` 应显示服务器公网 IP 4. **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 `。 完整列表见 [`docs/API.md`](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` | 审计日志 | 示例: ```bash # 登录 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 提示"无法连接"?** 排查顺序: ```bash 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 运行,启动会失败。检查: ```bash ps aux | grep openvpn-manager # 确认主进程是 root cat /etc/systemd/system/openvpn-manager.service | grep User # 应该 User=root ``` **Q: 下载的 .ovpn 客户端连不上?** 1. 确认服务器防火墙/路由器开放了对应端口(UDP 1194 等) 2. 客户端能 ping 通服务器公网 IP 吗? 3. 服务端 status.log 有没有客户端连接尝试? **Q: 怎么从备份恢复?** Web → "备份与恢复" → 选中备份 → "恢复"。会**覆盖**现有 `pki/`、`instances/`、`clients/`,操作前**先做一次新的备份**以防万一。 **Q: 能用 Nginx 反代 + HTTPS 吗?** 可以,示例 Nginx 配置: ```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`(用"自定义"字段)。 --- # 七、开发 ```bash # 后端 cd backend go run ./cmd/server --data ../data --dist ../dist # 前端(开发热重载,会自动代理 /api 到 :8089) cd frontend npm install npm run dev # 浏览器打开 http://localhost:3000 ``` 调试模式日志: ```bash OVPNMGR_LOG_LEVEL=debug ./bin/openvpn-manager --data ./data --dist ./dist ``` 跑测试: ```bash cd backend && go test ./... cd frontend && npm run build # 顺便当 type/lint 校验 ``` 构建发布版: ```bash # 前端 cd frontend && npm run build && cd .. # 后端(静态链接、剥离调试符号) cd backend CGO_ENABLED=0 go build -ldflags "-s -w" -trimpath -o ../bin/openvpn-manager ./cmd/server ``` --- ## 许可证 [MIT](LICENSE) --- ## 致谢 本项目使用了以下开源软件: - [OpenVPN](https://openvpn.net/) - [Gin Web Framework](https://github.com/gin-gonic/gin) - [Vue.js](https://vuejs.org/) - [Element Plus](https://element-plus.org/) - [ECharts](https://echarts.apache.org/) - [golang-jwt](https://github.com/golang-jwt/jwt)