Files
openvpn-manager/README.md
T
cnbugs 77f8b59290 Initial commit: OpenVPN Manager v1.0
OpenVPN Web management console with multi-instance support, client cert
issuance, traffic/connection auditing, certificate expiry reminders,
auto backup/restore.

Stack:
- Backend: Go 1.21+ (Gin + JWT)
- Frontend: Vue 3 + Element Plus + ECharts + Vite
- Storage: JSON file (db.json) + filesystem (pki/, instances/, clients/, backups/)

Features:
- Multi-instance OpenVPN management (independent port/proto/subnet/PKI)
- One-click client certificate issuance with .ovpn (embedded certs)
- Certificate expiry reminders (30-day threshold)
- Connection log parsing (status-version 3)
- Auto backup/restore (tar.gz)
- Audit log for all write operations
- JWT auth (12h TTL)
- One-line install.sh for Ubuntu/Debian/RHEL/Fedora
2026-08-09 20:32:37 +08:00

21 KiB

OpenVPN Manager

一个开箱即用的 OpenVPN Web 管理控制台 —— 多实例托管、客户端证书一键签发、流量审计、证书到期提醒、自动备份与恢复。 基于 Go (Gin) + Vue 3 + Element Plus + ECharts,单二进制部署。

dashboard Vue License


目录


功能特性

模块 说明
多实例管理 同一台机器上跑多个 OpenVPN 实例,每个独立端口/协议/子网/PKI
客户端证书 一键签发,自动生成 .ovpn(内嵌 CA/Cert/Key/TLS-Auth),无需额外文件
固定 IP 通过 CCD (client-config-dir) 为指定用户分配固定 VPN IP
启停控制 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.5
    • openssl ≥ 1.1
    • nodejs ≥ 18
    • npm
    • golang ≥ 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

脚本会做这些事:

  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
================================================================

安装参数

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.serviceOVPNMGR_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

修改默认密码

⚠️ 生产环境第一步

当前版本通过 systemd 环境变量修改密码:

systemctl edit --full openvpn-manager
# 找到 OVPNMGR_ADMIN_PASS 一行,改成你的强密码
# 也建议修改 OVPNMGR_JWT_SECRET 为随机串
systemctl daemon-reload
systemctl restart openvpn-manager

或重新跑 install.sh --pass 新密码

创建第一个实例

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 证书(<ca>...</ca>)
  • 客户端证书(<cert>...</cert>)
  • 客户端私钥(<key>...</key>)
  • TLS-Auth 密钥(<tls-auth>...</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 优先(性能好):

# ufw
ufw allow 1194/udp
ufw allow 1194/tcp   # 如果实例用 TCP

# firewalld
firewall-cmd --permanent --add-port=1194/udp
firewall-cmd --reload
  1. 若服务器在 NAT 后(如家用宽带),需要在路由器做端口映射 UDP 1194 → 服务器内网 IP。

三、客户端使用

配置文件说明

下载的 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.com1.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

验证:

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 服务)

# 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

  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 <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 客户端连不上?

  1. 确认服务器防火墙/路由器开放了对应端口(UDP 1194 等)
  2. 客户端能 ping 通服务器公网 IP 吗?
  3. 服务端 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 改成 udp6tcp6,子网用 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

许可证

MIT


致谢

本项目使用了以下开源软件: