Files
opsx-vpn/README.md
T

205 lines
12 KiB
Markdown
Raw 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
## 快速开始
### 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) 创建企业自建应用,启用网页登录授权,在应用安全设置中登记回调、发布应用并限定可用人员。先核实飞书租户是否提供标准 OIDC discovery (`/.well-known/openid-configuration`) 与 ID Token;若没有,用 Keycloak / Authentik 等身份代理对接飞书,再把代理的 OIDC issuer 及其客户端凭据填入向导。此时飞书应用登记的是**代理给飞书的上游回调**,不是 VPN 回调;OAuth 授权地址不能代替 issuer。
2. 在 Linux VPN 主机安装 OpenVPN **2.6.2 或更新版本**及 `openvpn-auth-oauth2` 可执行文件(置于 PATH 或 `data/bin/openvpn-auth-oauth2`)。创建时填 HTTPS issuer、Client ID/Secret、独立公网 HTTPS 入口(例如 `https://vpn-login.example.com`)以及本机服务端口(默认 `19090`)。每条 OIDC 隧道使用不同的公网入口和本机端口。
3. 在最终的 OIDC 身份提供方注册引导页显示的 `https://vpn-login.example.com/oauth2/callback`(直连飞书时登记在飞书应用;经代理时登记在代理的 OIDC 客户端)。为该公网入口配置 TLS 和反向代理,将**所有路径**转发到本机 `127.0.0.1:19090`(按实际端口调整);仅开放公网 HTTPS 与 OpenVPN 的 UDP/TCP VPN 端口,不暴露本机认证端口或管理 socket。回调由 `openvpn-auth-oauth2` 接收,**不需要**在平台的 `:18080` 增加 `/oauth2/callback`。
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 # 停止服务
```
### Linux 服务器部署
```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