Files

211 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VPN 专线管理平台
Gin + Vue3 + SQLite 的多协议 VPN 专线 Web 管理平台:**单二进制交付、配置简单、管理便捷、可扩展自定义协议**。
## 支持协议
| 协议 | 实现方式 | 场景 |
|---|---|---|
| WireGuard | 系统 `wg` / `wg-quick`,多 Peer、NAT/MTU、流量累计 | 内部接入、移动办公(首选) |
| IPSec | StrongSwan `swanctl`,厂商模板一键套用 | **第三方对接**、站点互联 |
| IKEv2 远程接入 | StrongSwan Road Warrior,PSK + EAP-MSCHAPv2 | 员工手机/笔记本原生拨号 |
| L2TP/IPSec | StrongSwan + xl2tpd,支持多拨号用户 | 手机/老设备兼容 |
| FRP | 直接管理 `frps` / `frpc`(TOML),含 STCP/XTCP | 内网穿透、端口映射 |
| GRE | Linux `ip tunnel` 管理标准 GRE 隧道 | 点对点网站互联 |
| OpenVPN | 进程管理 + PKI;UDP/TCP 可切换;证书/密码 + TOTP MFA | 老项目兼容 |
| 自定义协议 | 插件命令钩子(Create/Start/Stop/Status/Config) | 任意协议扩展 |
## 核心功能
- **专线列表**:名称/协议/状态/流量/到期时间,一键启停、编辑、删除、下载配置、WireGuard 二维码
- **创建向导**:选协议 → 依赖检测门控(未就绪不可选,引导下载/安装)→ 填参数(高级折叠)→ 必填校验
- **在线会话**:跨协议统一展示在线用户、公网 IP、VPN IP、连接时长、流量;支持踢下线
- **流量审计**:连接审计日志(connect/disconnect/auth_fail)、异常突发流量告警、管理员手动踢下线
- **流量配额**:隧道级配额(GB)、超额动作(告警/停止/限速)、周期重置(日/月)
- **协议引擎管理**:FRP/OpenVPN 支持平台一键下载部署;WireGuard/StrongSwan 显示系统包安装命令
- **WireGuard Peer 管理**:详情内增删 Peer、按设备下载配置/二维码
- **拨号用户**:OpenVPN / L2TP / IKEv2 共用用户表;支持从平台用户导入、批量创建、LDAP 浏览导入
- **IPSec 第三方对接专页**:设备模板预置 Phase1/Phase2 参数、双方参数一致性检查、一键连通性测试
- **节点管理**:多中继节点,远程节点支持 SSH 凭证验证(密码/私钥、即时测试连接)
- **专线日志**:操作栏「更多 → 查看日志」SSE 实时输出实例进程日志
- **安全**:PSK/私钥 AES-GCM 加密存储、配置文件 0600 权限、操作审计
- **访问控制**:admin / operator / viewer;首登强制改密;登录防爆破;TOTP MFA + 备用码;LDAP
## 快速开始
桌面客户端位于 [client/](client/README.md):Rust + Tauri v2 管理拨号用户登录、线路与设备登记,打包的 Go WireGuard 网络栈提供出口诊断和仅供主动配置的应用使用的本地 SOCKS5 代理。macOS/Linux 的**整机 VPN**目前仍依赖本机 `wg`/`wg-quick`;Windows 整机隧道未实现。客户端功能和操作见 [客户端说明](client/README.md),免安装系统隧道的设计与待验收项目见 [SDD-003](docs/specs/SDD-003-bundled-wireguard-client.md)。
### OpenVPN 飞书 / OIDC 浏览器认证
在「创建专线 → OpenVPN → 认证方式」选择「第三方 OAuth2 / OIDC(飞书登录)」。引导页会展示飞书应用准备、OIDC 信息、公网回调与客户端试连四步。该模式由 [openvpn-auth-oauth2](https://github.com/jkroepke/openvpn-auth-oauth2) 接管 OpenVPN 的 WebAuth 认证;**不会将飞书登录转交给已有的 LDAP 密码校验,也不会将现有 LDAP 用户自动关联为飞书用户**。应用的可用范围应在飞书或身份代理侧明确限定。
1. 在 [飞书开放平台](https://open.feishu.cn/app) 创建并发布企业自建应用,启用网页登录,限定可用人员。**内置方案**:通过可信 HTTPS 管理入口打开「设置 → 飞书身份」,只在此处保存飞书 App ID、轮换后的 App Secret 与允许的 `tenant_key`,把页面所示 `https://<公网域名>/id/feishu/callback` 登记到飞书应用。启用后系统通过 `https://<公网域名>/id` 提供标准 OIDC 发现文档、JWKS 和令牌签发。在专线新建或编辑页选择「内置飞书身份」,发行者与 VPN Client ID 自动引用,VPN Client Secret 由服务端自动配置,不会回显。也可以继续使用外部标准 OIDC issuer:此时飞书 App 凭据留在外部代理,专线填写代理生成的 VPN Client ID/Secret。
2. 在 Linux VPN 主机安装 OpenVPN **2.6.2 或更新版本**及 `openvpn-auth-oauth2` 可执行文件(置于 PATH 或 `data/bin/openvpn-auth-oauth2`)。内置方案在向导中选择内置 issuer,公网认证入口可复用管理域名(已有证书);独立服务端口默认 `19090`。外部 OIDC 方案仍需手动填写发行者、VPN 客户端凭据与独立 HTTPS 入口。每条专线的认证入口和本机端口必须唯一。
3. 内置方案在设置页同步身份公网路由,Nginx 只转发固定 `/id/` 端点;启动**唯一一条使用该管理域名**的测试 OpenVPN OIDC 专线后再次同步,Nginx 才将 `/oauth2/` 转给本机认证组件。该 `https://<公网域名>/oauth2/callback` 属于 OpenVPN 组件,**不是飞书应用的回调**。外部发行者方案仍需在外部 OIDC 客户端登记此 VPN 回调。公网只开放 HTTPS 与 VPN 协议端口,认证端口 `127.0.0.1:19090+` 和 OpenVPN 管理 socket 不对公网开放。
4. 启动专线时平台会运行独立的 OpenVPN 和认证服务进程;OIDC 凭据在数据库加密保存,认证服务的 `openvpn-auth-oauth2.yaml` 与管理密码文件在 `data/instances/<ID>-openvpn/` 内以 `0600` 保存。未安装二进制、OpenVPN 版本不足或认证服务启动失败都会报错并停止该专线。浏览器登录失败时不回退到 LDAP 或本地密码。
5. 下载 `.ovpn` 并在支持 WebAuth 的客户端试连。上游[客户端兼容性说明](https://github.com/jkroepke/openvpn-auth-oauth2/wiki/OpenVPN)列出 Windows OpenVPN Community Client 2.6+、macOS Tunnelblick 4.0 beta 10+ 和 Viscosity;OpenVPN Connect v3 仅部分兼容,应先实测。客户端需要在 VPN 建立**之前**访问公网 HTTPS 入口及身份源。用授权用户与未授权用户分别测试登录和拒绝,验证断线重连。
首次上线先创建独立测试隧道;不要直接切换现有密码隧道。OIDC 登录身份的授权由飞书应用范围或身份代理规则控制,管理端的 VPN 拨号用户列表目前仍是独立的数据模型。需要将飞书身份与 LDAP 用户逐一绑定时,应增加按稳定 `sub` 映射的授权设计,不能只按相同邮箱/用户名匹配。服务日志位于实例目录的 `oidc.log`,可能包含认证诊断信息,按敏感日志管理。
### 本地构建与运行
```bash
./run.sh run # 构建并运行(默认 admin / admin123)
./run.sh dev # 开发模式(前后端分离)
./run.sh restart # 重新构建并重启
./run.sh stop # 停止服务
```
管理后台的视觉和交互规范见 [管理端 UI 实施说明](docs/specs/SDD-008-web-ui-guide-alignment.md)。前端沿用 Vue 3 + Element Plus:路由元数据统一生成侧栏与页标题,颜色和间距集中在 `frontend/src/styles/tokens.css`,列表与图表明确展示加载、空数据和失败重试。单独预览前端可在 `frontend/` 运行 `npm run dev`;默认代理 `/api` 到本机 `8080`,需要启动后端才能测试登录及真实数据。
### Linux 服务器部署
现有服务器的构建、升级、备份与 OIDC 入口配置参见 [部署手册](docs/deploy.md)。
```bash
# 1. 交叉编译 Linux 二进制(在 macOS 上)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o opsx-vpn ./backend
# 2. 上传到服务器
scp opsx-vpn user@server:/opt/opsx-vpn/
cd /opt/opsx-vpn && chmod +x opsx-vpn
# 3. 安装系统依赖(按需)
apt install -y wireguard-tools openvpn easy-rsa strongswan strongswan-swanctl iproute2 iptables xl2tpd
# FRP 无需系统包 —— 平台 UI 内点「下载部署」自动从 GitHub 下载到 data/bin/
# 4. 启动(生产建议用 systemd 管理)
VPN_LISTEN_ADDR=:18080 ./opsx-vpn # 生产管理端口 :18080,数据目录 ./data
```
### systemd 服务(生产推荐)
```ini
# /etc/systemd/system/opsx-vpn.service
[Unit]
Description=VPN Management Platform
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/opsx-vpn
ExecStart=/opt/opsx-vpn/opsx-vpn
Restart=always
RestartSec=5
# 环境变量按需调整
Environment=VPN_LISTEN_ADDR=:18080
Environment=VPN_DATA_DIR=/opt/opsx-vpn/data
# WireGuard/OpenVPN 需要 root 权限(创建 TUN 设备 + iptables)
# 如需降权,需配置 NET_ADMIN capability
[Install]
WantedBy=multi-user.target
```
```bash
systemctl daemon-reload
systemctl enable --now opsx-vpn
journalctl -u opsx-vpn -f # 查看日志
```
## 防火墙 / 安全组端口
部署到云服务器时,需开放以下端口:
### VPN 数据通道(对公网开放)
| 端口 | 协议 | 类型 | 用途 |
|---|---|---|---|
| UDP 51820 | WireGuard | UDP | WG 默认监听端口(可在创建时改) |
| UDP 1194 | OpenVPN | UDP | OpenVPN 默认端口(可改 TCP) |
| TCP 1194 | OpenVPN | TCP | OpenVPN TCP 模式(如选 TCP) |
| UDP 500 | IPSec / IKEv2 / L2TP | UDP | IKE 密钥交换 |
| UDP 4500 | IPSec / IKEv2 / L2TP | UDP | NAT-T 穿透 |
| UDP 1701 | L2TP | UDP | L2TP 隧道 |
| TCP 7000 | FRP | TCP | frps 绑定端口(客户端连接用) |
| IP 协议 47 | GRE | GRE | GRE 封装(无 TCP/UDP 端口) |
### 管理(仅限你的 IP 或内网)
| 端口 | 协议 | 类型 | 用途 |
|---|---|---|---|
| TCP 18080 | 管理平台 | TCP | Web UI + API(**勿对公网开放**,建议 Nginx HTTPS 后改 443) |
| TCP 22 | SSH | TCP | 远程管理 |
### 安全组配置示例
```
# VPN 数据通道(对公网开放)
UDP 500/4500 0.0.0.0/0 # IPSec/IKEv2/L2TP 密钥交换 + NAT-T
UDP 51820 0.0.0.0/0 # WireGuard
UDP 1194 0.0.0.0/0 # OpenVPN UDP
TCP 1194 0.0.0.0/0 # OpenVPN TCP(如启用)
UDP 1701 0.0.0.0/0 # L2TP
TCP 7000 0.0.0.0/0 # FRP server
# GRE 不是 TCP/UDP 端口,需在安全组中放行 GRE / IP 协议 47
GRE 协议 47 对端公网 IP/32 # 建议只允许对端地址
# 管理(仅限你的 IP)
TCP 18080 你的IP/32 # 管理 UI
TCP 22 你的IP/32 # SSH
```
> **注意**:IPSec 必须同时开放 UDP 500 + 4500(缺一个连不上)。GRE 需要**本端、对端及中间云安全组**双向允许 **IP 协议 47**,不是端口号;Linux 端依赖 `iproute2` 的 `ip tunnel`。管理端口 18080 切勿对公网开放。仅用 WireGuard 最简部署只需 3 个端口:UDP 51820 + TCP 18080 + TCP 22。
## 协议依赖安装
| 协议 | 安装方式 | 平台下载 |
|---|---|---|
| WireGuard | `apt install -y wireguard-tools` | ❌ 系统包 |
| OpenVPN | `apt install -y openvpn easy-rsa`(easy-rsa 用于生成 PKI,缺了无法下发客户端配置) | ✅ GitHub Release / 系统包 |
| StrongSwan (IPSec/IKEv2/L2TP) | `apt install -y strongswan strongswan-swanctl` | ❌ 系统包 |
| GRE | `apt install -y iproute2`(多数系统默认已安装) | ❌ 系统包 |
| FRP | 无需系统包 | ✅ 平台 UI「下载部署」自动从 GitHub 下载 |
在「总览 → 协议引擎状态」表中,未就绪的协议会显示「下载部署」或「安装命令」按钮。
## 环境变量
| 变量 | 默认 | 说明 |
|---|---|---|
| `VPN_LISTEN_ADDR` | `:18080` | 监听地址 |
| `VPN_DATA_DIR` | `./data` | 数据目录(SQLite、密钥、实例配置、下载的二进制) |
## 常用命令
| 命令 | 说明 |
|---|---|
| `./run.sh run` | 构建并后台运行单二进制(默认) |
| `./run.sh build` | 全量构建(前端 + 后端二进制) |
| `./run.sh dev` | 开发模式(前后端分离) |
| `./run.sh stop` | 停止所有服务 |
| `./run.sh restart` | 重新构建并重启 |
| `./run.sh status` | 查看服务状态 |
## 项目结构
```
frontend/ # Vue3 + Element Plus 前端
backend/
main.go # Gin 入口(内嵌前端 embed.FS)
internal/
api/ # REST 路由与鉴权
core/ # Protocol 统一接口 + 注册中心
model/ # GORM 数据模型
store/ # SQLite + AES-GCM 密钥存储
service/ # 协议实现
wireguard/ ipsec/ ikev2/ l2tp/ frp/ openvpn/
custom/ # 自定义协议插件
monitor/ # 状态/流量/会话/配额采集引擎
sessionmgr/ # 在线会话同步 + 连接审计
trafficmgr/ # 流量配额 + 异常检测 + 限速
binmgr/ # 协议二进制下载部署 + 安装引导
sshutil/ # SSH 连接测试(节点验证)
```
## 交付形态
- **单二进制**:前端构建后通过 `go:embed` 内嵌进 Go 二进制,`./opsx-vpn` 单文件即可运行(含 SPA + REST API + SQLite)
- 不依赖 Docker、不依赖外部数据库
- 纯静态编译:`CGO_ENABLED=0` 可交叉编译到任意 Linux/Windows