别再手动管OpenVPN了,一行命令部署管理后台
系统基于Docker Compose部署,包含三个容器:OpenVPN服务端(kylemanna/openvpn镜像)、Flask+Bootstrap管理后台、MySQL 8.0数据库,认证热路径直连MySQL避免单点故障。项目已开源至GitHub,并支持多认证Provider插件化,可接入企业自有账号体系。
为什么要自建 OpenVPN 管理面板
账号到期没人提醒、新人入职配置混乱、离职员工忘记回收证书……
市面上的几款开源方案我基本都试用过,没有找到满意的。
于是我决定自己撸一个:足够轻量(一台 2C4G 跑得动)、MySQL 存储、支持多认证 Provider(这是关键——我们的合规要求是密码 + MFA 双因子)。今天把它整理开源到 GitHub,记录下我趟过的几个关键坑。
几个核心设计决策:
- server 容器用
kylemanna/openvpn:社区成熟的 OpenVPN Docker 镜像,支持自定义 auth_verify 钩子和 management 接口 - admin 用 Flask + Bootstrap(没用 React/Vue):单文件 admin 服务,部署简单、排查问题直接看日志就行
- MySQL 作为唯一数据源:用户、连接历史、活跃会话都进库,方便后续接 BI 做合规审计
- 认证热路径直连 MySQL(OpenVPN 的
auth_verify钩子不通过 admin):避免 admin 挂掉导致整个 VPN 瘫掉
部署:一行命令跑起来
git clone https://github.com/OpsZhu/openvpn-admin-panel.git
cd openvpn-admin-panel
cp .env.example .env
vim .env # 改 MYSQL_PASSWORD 等关键变量
bash setup.sh
setup.sh 做了 4 件事:
- 生成 OpenVPN 服务端证书(PKI)
- 初始化 MySQL(创建库表 + 默认 admin 账号)
- 启动 docker-compose
- 轮询
mysqladmin ping等 MySQL 真正就绪(我栽过坑:固定 sleep 30 秒不够——见下)
坑 1:MySQL 初始化超时
setup.sh 第一版写的是 sleep 30 等 MySQL 起来。但 MySQL 第一次启动做 initdb 经常超过 30 秒,30 秒后 admin 启动直接报 ERROR 2003 (HY000): Can't connect to MySQL server on 'db:3306' (111)。
修复用轮询外加让 admin 失败时直接退出 + 依赖 docker restart 重试,比"admin 起来了但 db 没就绪然后报一堆错"清爽得多。
坑 2:管理界面里的"踢下线"按钮
服务器状态页有个"踢下线"按钮,调用 OpenVPN management 接口 kill <client>。写完一测就报 common name not found。
排查过程:
- 抓 management 接口的
status 2输出,发现CLIENT_LIST返回的是空的 - 但
active_connections表里有数据(client-connect钩子写入的) - 两个数据源对不上——management 看不到客户端
根因:OpenVPN 2.4.9 的 kill 命令只接受两种参数:
<common_name>(证书里 CN 字段)<real_ip:port>(客户端真实 IP:端口,如192.168.16.1:42301)
不接受纯数字 client_id,也不接受 virtual_ip(192.168.255.6 是 VPN 内网 IP,不是真实 IP)。
修复方案:
前端按钮传 client_addr(real_ip:port),不再传 virtual_ip。实测 100% 成功率。
多认证 Provider 插件化
这套面板最强的设计我觉得是多认证 Provider。完全可以接入企业自有的账号体系中做认证。