Files
Your Name 70b6da45c2 docs: 添加详细的生产部署文档(Gunicorn + Systemd + Nginx)
- WSGI 生产服务器配置说明
- 完整的 Systemd service 配置
- Nginx 反向代理 + SSL 配置示例
- 生产环境检查清单
- 优雅关闭特性说明
2026-07-17 00:10:25 +08:00

312 lines
12 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.
# SOCKS Manager — SOCKS5 代理管理平台
内建 asyncio SOCKS5 服务器(RFC 1928/1929)的完整代理管理平台,一个 Python 进程即可运行。支持多实例管理、流量控制、用户管理、审计日志、实时监控。
## 架构
```
┌──────────────────────────────────────────────┐
│ Web 管理面板 (Flask + Bootstrap 5 暗色主题) │
├──────────────────────────────────────────────┤
│ RESTful API (/api/*) │
├────────────┬──────────────┬──────────────────┤
│ engine/ │ services/ │ │
│ └server.py │ └user_service│ 数据: SQLite │
│ asyncio │ 流量/认证 │ socks_manager.db│
│ SOCKS5 │ └stats_ │ │
│ 服务器 │ 监控/趋势 │ │
│ └instances │ └backup_ │ │
│ 多实例 │ 备份恢复 │ │
└────────────┴──────────────┴──────────────────┘
```
## 功能覆盖
| 需求 | 实现 |
|------|------|
| 多实例管理 | 每个实例独立事件循环,支持创建/启动/停止/重启 |
| 基础参数 | 监听地址(IPv4/IPv6)、端口、超时可视化配置 |
| 底层引擎 | 内建 asyncio SOCKS5 服务器(RFC 1928/1929 |
| 配置热重载 | 修改参数后重启实例生效,不中断 Web 面板 |
| 多身份认证 | 无认证 / 账号密码认证 |
| 流量控制 | 总流量上限、月流量上限、超额自动停机 |
| 速度与并发 | 上下行带宽限制(Mbps)、最大并发连接数 |
| IP 白名单/黑名单 | 用户级逗号分隔配置 |
| 账号生命周期 | 生效时间、过期时间、一键封禁/解封 |
| 大盘控制台 | CPU/内存/网络吞吐量/活跃连接实时图表 |
| 实时连接追踪 | 源IP/目标域名/协议/持续时间,手动断开 |
| 流量统计报表 | 30 天折线/柱状图(Chart.js |
| 详细审计日志 | 按事件/用户/IP 筛选,分页查询 |
| 级联代理 | 连接建立时自动代理至目标(可扩展 upstream) |
| 负载均衡 | 多实例配置后按端口轮询 |
| 管理员认证 | 环境变量 `SM_ADMIN_PASSWORD` 保护 |
| 防爆破 | 自动阻断频繁登录尝试(Fail2Ban 机制) |
| 密码安全 | bcrypt 哈希存储 SOCKS5 用户密码(兼容旧明文自动迁移) |
| 会话管理 | 自定义 Cookie 域名/安全/名称,支持 HTTPS 部署 |
| 自动备份 | 一键备份 SQLite,按份数清理 |
| 每日流量快照 | 后台线程每小时记录一次,用于月度趋势图表 |
| RESTful API | 全部管理功能通过 `/api/` 暴露 |
## 快速开始
```bash
cd /root/socks-manager
# 安装依赖
pip install -r requirements.txt --break-system-packages
# 设置管理员密码(首次启动如未设置,自动使用默认密码 admin123 并写入 .env
export SM_ADMIN_PASSWORD=你的密码
# 启动
python3 run.py
```
访问 `http://你的IP:5000`,用户名 `admin`,密码为环境变量值。
> ⚠️ 首次启动时如果 `SM_ADMIN_PASSWORD` 未设置,会自动写入默认密码 `admin123` 到 `.env` 文件。**生产环境请务必修改此密码。**
## 环境变量
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `SM_ADMIN_USER` | `admin` | 管理员用户名 |
| `SM_ADMIN_PASSWORD` | `""` | 管理员密码(必须设置) |
| `SM_SECRET_KEY` | `sm-dev-key-change-in-prod` | Flask 会话密钥(生产环境务必修改,建议随机 64 位字符串) |
| `SM_SESSION_DOMAIN` | `None` | 会话 Cookie 域名(跨域访问时设为你的域名或 IP) |
| `SM_COOKIE_SECURE` | `false` | 是否启用 Cookie Secure 标志(HTTPS 时设为 `true` |
| `SM_SESSION_NAME` | `sm_session` | 会话 Cookie 名称(多实例同域名时避免冲突) |
| `SM_DB_URI` | `sqlite:///socks_manager.db` | 数据库连接串 |
| `SM_PORT` | `5000` | Web 面板监听端口 |
| `SM_HOST` | `0.0.0.0` | Web 面板监听地址 |
| `SM_BACKUP_DIR` | `./backups/` | 备份文件存储目录 |
| `SM_LOG_LEVEL` | `INFO` | 日志级别:`DEBUG`/`INFO`/`WARN`/`ERROR` |
## 常见问题
### 1. 在其他服务器上无法登录
问题:浏览器访问面板,输入密码后提示错误或跳转回登录页。
**可能原因 & 解决方案:**
| 原因 | 解决 |
|------|------|
| 密码不一致 | 确认所有服务器 `.env` 文件中的 `SM_ADMIN_PASSWORD` 一致 |
| Cookie 被浏览器拒绝(HTTP + 非标准域名) | 通过 `curl -c /tmp/cookies.txt -X POST -d "username=admin&password=xxx" http://你的IP:5000/login` 测试 |
| 通过 SOCKS5 代理访问面板 | 直连(非代理模式)访问面板 |
| Session Cookie 域名不匹配 | 设置 `SM_SESSION_DOMAIN=你的IP` 并重启 |
| HTTPS 下未设置 Secure | 设置 `SM_COOKIE_SECURE=true` |
验证登录是否成功:
```bash
curl -c /tmp/sm_cookies.txt -b /tmp/sm_cookies.txt \
-X POST -d "username=admin&password=你的密码" \
http://你的IP:5000/login -w "%{http_code} %{redirect_url}"
```
返回 `302 /dashboard` 表示成功。
### 2. 仪表盘流量趋势图无数据
首次部署后需等待 1 小时,后台线程每小时记录一次流量快照。也可以手动记录一次:
```bash
python3 -c "from services.stats_service import record_traffic_snapshot; record_traffic_snapshot()"
```
### 3. SOCKS5 用户密码安全性
SOCKS5 协议(RFC 1929)本身采用明文传输密码。本项目服务端使用 **bcrypt** 哈希存储,兼容旧版明文存储的数据库(首次验证时自动迁移到哈希)。Web 面板中展示用户时不会泄露密码。
## 核心代码结构
```
├── app.py # Flask 应用工厂
├── config.py # 配置
├── auth.py # 登录认证 + 防爆破
├── models.py # SQLAlchemy 数据模型(含 bcrypt 密码方法)
├── database.py # 数据库初始化
├── run.py # 启动入口
├── engine/
│ ├── server.py # asyncio SOCKS5 服务器(核心引擎)
│ └── instances.py # 多实例管理器(线程安全)
├── services/
│ ├── user_service.py # 用户管理/认证/流量/防爆破
│ ├── stats_service.py# 监控/统计/趋势/流量快照
│ └── backup_service.py# 备份与恢复
├── api/
│ └── v1.py # RESTful API(实例/用户/日志/备份)
├── web/
│ └── routes.py # Web 管理面板路由
└── templates/ # Jinja2 模板(暗色 Bootstrap 5
├── base.html # 布局(侧边栏+导航+全局样式)
├── dashboard.html # 仪表盘(实时图表 + 最近审计日志)
├── instances.html # 代理实例管理
├── users.html # 用户管理
├── stats.html # 流量统计
├── connections.html# 活跃连接
├── logs.html # 审计日志
└── system.html # 系统管理
```
## API 参考
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/dashboard` | 仪表盘汇总 |
| GET | `/api/stats/system` | 实时系统指标(含最近 10 分钟历史) |
| GET | `/api/stats/connections` | 活跃连接列表 |
| GET | `/api/stats/traffic-trend?days=30` | 流量趋势 |
| GET | `/api/stats/users` | 用户流量排名 |
| GET | `/api/stats/instances` | 实例流量统计 |
| GET/POST | `/api/instances` | 实例列表/创建 |
| PUT/DELETE | `/api/instances/<id>` | 更新/删除实例 |
| POST | `/api/instances/<id>/start\|stop\|restart` | 实例启停 |
| POST | `/api/instances/sync` | 同步所有实例状态 |
| GET/POST | `/api/users` | 用户列表/创建 |
| PUT/DELETE | `/api/users/<id>` | 更新/删除用户 |
| POST | `/api/users/<id>/toggle\|ban` | 用户启停/封禁 |
| GET | `/api/logs?page=1&event=&user=&src_ip=` | 审计日志查询 |
| GET/POST | `/api/backups` | 备份列表/创建 |
| POST | `/api/backups/<id>/restore` | 恢复备份 |
| POST | `/api/backups/cleanup` | 清理旧备份 |
所有 API 需要登录认证(Session Cookie),未登录返回 401。
## 生产部署
### 1. WSGI 生产服务器(Gunicorn
Flask 内置开发服务器不适合生产环境。使用 **Gunicorn**(生产级 WSGI 服务器):
```bash
# 安装 gunicorn
pip install gunicorn --break-system-packages
# 启动(4 worker 进程,适合 4 核服务器)
gunicorn -w 4 -b 0.0.0.0:5000 --timeout 120 run:app
# 推荐参数(更长超时 + 优雅关闭)
gunicorn -w 2 -b 0.0.0.0:5000 \
--timeout 300 \
--graceful-timeout 30 \
--max-requests 10000 \
--max-requests-jitter 1000 \
run:app
```
> **注意**:SOCKS5 代理实例运行在独立的 asyncio 线程中,不受 Gunicorn worker 数量影响。
---
### 2. Systemd 服务配置(推荐)
创建 `/etc/systemd/system/socks-manager.service`
```ini
[Unit]
Description=SOCKS5 Proxy Manager
After=network.target
[Service]
Type=notify
User=root
WorkingDirectory=/opt/socks-manager
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
# 生产环境变量(按需修改)
Environment="SM_ADMIN_PASSWORD=你的强密码"
Environment="SM_SECRET_KEY=生产环境用openssl rand -hex 32生成"
Environment="SM_LOG_LEVEL=WARN"
# Environment="SM_COOKIE_SECURE=true" # HTTPS 时开启
# Environment="SM_SESSION_DOMAIN=你的域名或IP" # 跨域时设置
ExecStart=/usr/local/bin/gunicorn -w 2 -b 0.0.0.0:5000 \
--timeout 300 \
--graceful-timeout 30 \
run:app
# 优雅关闭:先给 SOCKS5 实例时间关闭活跃连接
ExecStop=/bin/kill -s TERM $MAINPID
TimeoutStopSec=60
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
启动服务:
```bash
systemctl daemon-reload
systemctl enable --now socks-manager
systemctl status socks-manager
journalctl -u socks-manager -f # 查看实时日志
```
---
### 3. Nginx 反向代理 + SSL
```nginx
server {
listen 80;
server_name 你的域名;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name 你的域名;
ssl_certificate /etc/letsencrypt/live/你的域名/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/你的域名/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
proxy_http_version 1.1;
}
}
```
---
### 4. 生产环境检查清单
**强制修改默认密码**
```bash
# 生成强密钥
export SM_SECRET_KEY=$(openssl rand -hex 32)
```
**数据库备份**
- 配置 crontab 每日备份 `socks_manager.db`
- 定期测试恢复流程
**日志级别**
- 生产环境设置 `SM_LOG_LEVEL=WARN` 减少日志量
**HTTPS**
- 启用 Let's Encrypt SSL 证书
- 设置 `SM_COOKIE_SECURE=true`
**防火墙**
- 只开放需要的端口:Web 面板(5000) + SOCKS5 代理端口
- SOCKS5 端口建议限制源 IP
**优雅关闭**
- v1.1+ 版本已修复 SOCKS5 实例的优雅关闭逻辑
- 停止服务时最多等待 5 秒让活跃连接正常关闭
- 避免 `GeneratorExit``Task was destroyed` 警告