feat: 完整 Squid Web Manager 平台 - P0-P3 全功能
完整 Web 管理平台,涵盖: P0 生产加固: - 会话超时(空闲+绝对) + CSRF 防护 + 登录失败限流 - HTTPS/TLS 证书管理(自签生成/上传/删除/过期提醒) - SSL Bump (HTTPS 透明代理) 可视化配置 - 配置文件 diff 预览 + 二次确认才写入 - 服务控制二次确认 + 操作期间按钮锁定 P1 运维能力: - 日志轮转管理(logrotate) + 日志状态监控 - 告警规则(5xx/命中率/磁盘/客户端流量) - 多 Squid 实例管理 + 一键切换 - squidclient mgr 实时性能指标 - 流量异常检测(突增/大文件/高频小包/新客户端) P2 日志分析增强: - 日志持久化到 SQLite + 历史时间范围查询 - 导出 CSV/JSON(日志/KPI/异常/审计) - GeoIP 地图(Leaflet + ip-api.com 离线可选 GeoLite2) - 每客户端 24h 趋势图 - 自定义 Squid logformat 解析器 P3 体验锦上添花: - 暗/亮主题切换(cookie 持久化) - WebSSH 终端(xterm.js + paramiko) - 完整审计日志 + 用户管理 技术栈: Flask 3.0 + SQLAlchemy 2.0 + SQLite + Chart.js + Leaflet 总代码量: ~16500 行 (15 Python 模块 + 34 模板 + CSS) 路由数: 73
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
# Squid Web Manager
|
||||
|
||||
一个基于 Flask 的 Squid 代理服务器 Web 管理平台。
|
||||
|
||||
## 功能
|
||||
|
||||
### 1. 全 Web 化配置管理
|
||||
- **主配置**: HTTP/HTTPS/ICP/SNMP 端口、缓存内存、对象大小、超时、DNS、日志路径、管理员邮箱等
|
||||
- **ACL 规则表**: 完整 ACL CRUD,支持 28+ 类型 (src, dst, dstdomain, port, method, time, url_regex, proxy_auth, ...)
|
||||
- **访问控制**: http_access / https_access / icp_access / snmp_access 等所有访问指令的可视化管理
|
||||
- **缓存目录**: cache_dir 多目录管理 (ufs / aufs / diskd / rock)
|
||||
- **刷新规则**: refresh_pattern 正则/百分比/最大时间
|
||||
- **认证配置**: basic / digest / ntlm / negotiate 全套 auth_param 管理
|
||||
- **缓存对等**: cache_peer 父代理/兄弟节点配置
|
||||
- **原始编辑**: 直接编辑 squid.conf,支持语法校验
|
||||
|
||||
每次保存自动备份当前配置,可选启用 `squid -k parse` 语法校验。
|
||||
|
||||
### 2. 日志分析
|
||||
解析 Squid 原生 access.log,提供:
|
||||
|
||||
- **KPI 卡片**: 总请求数、缓存命中率、总流量、平均响应、拒绝率、中断率、4xx/5xx 错误率
|
||||
- **每小时流量图**: 请求数 + 流量双 Y 轴折线图
|
||||
- **结果码分布**: TCP_HIT / TCP_MISS / TCP_TUNNEL / TCP_DENIED 等 (含中文释义)
|
||||
- **HTTP 状态码分布**: 2xx/3xx/4xx/5xx 分类
|
||||
- **方法分布**: GET / POST / CONNECT / ...
|
||||
- **请求分类**: Hit / Miss / Tunnel / Denied / Aborted / Error
|
||||
- **Top 客户端**: 按 IP 排序,显示请求数和流量
|
||||
- **Top 目标主机**: 按域名排序
|
||||
- **Top URL**: 访问最多的资源
|
||||
- **层级代码**: HIER_DIRECT / HIER_PARENT_HIT / ...
|
||||
- **Content-Type 分布**
|
||||
- **日志查询**: 多维度过滤 (IP / 方法 / 结果码 / 主机 / URL / 大小范围 / 时间范围)
|
||||
- **实时日志**: 自动刷新的 Live Tail 视图
|
||||
- **日志导入**: 离线分析一次性粘贴的日志
|
||||
|
||||
### 3. 服务控制
|
||||
- 启动 / 停止 / 重启 / 平滑重载 (reload,失败回退 restart)
|
||||
- 服务状态查看 (PID, 版本, 启动时间, unit 文件)
|
||||
- 关键路径一览
|
||||
|
||||
### 4. 运维功能
|
||||
- **配置备份**: 自动备份历史,可下载/恢复
|
||||
- **审计日志**: 所有配置变更、服务操作、登录登出全程留痕
|
||||
- **修改密码**: admin/admin 默认账号,强制可改
|
||||
|
||||
## 技术栈
|
||||
|
||||
| 组件 | 选型 |
|
||||
|------|------|
|
||||
| 后端 | Python 3 + Flask + SQLAlchemy |
|
||||
| 数据库 | SQLite (instance/squid_mgr.db) |
|
||||
| 前端 | 原生 HTML + CSS + 原生 JS |
|
||||
| 图表 | Chart.js 4.4 (CDN) |
|
||||
| WSGI | gunicorn |
|
||||
| 进程管理 | systemd (可选) |
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 安装依赖
|
||||
```bash
|
||||
cd /root/squid-manager
|
||||
pip install -r requirements.txt --break-system-packages
|
||||
```
|
||||
|
||||
### 直接运行 (开发)
|
||||
```bash
|
||||
python3 app.py
|
||||
# 默认监听 0.0.0.0:5200,调试模式
|
||||
```
|
||||
|
||||
### 生产部署 (gunicorn + systemd)
|
||||
```bash
|
||||
# 初始化数据库
|
||||
python3 -c "from app import app, db, seed_admin; \
|
||||
app.app_context().push(); \
|
||||
db.create_all(); seed_admin()"
|
||||
|
||||
# 启动 gunicorn
|
||||
gunicorn --workers 2 --bind 0.0.0.0:5200 wsgi:app
|
||||
```
|
||||
|
||||
### systemd 单元 (推荐)
|
||||
`/etc/systemd/system/squid-manager.service`:
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Squid Web Manager
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=exec
|
||||
User=root
|
||||
WorkingDirectory=/root/squid-manager
|
||||
ExecStart=/usr/bin/gunicorn --workers 2 --bind 0.0.0.0:5200 wsgi:app
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now squid-manager
|
||||
```
|
||||
|
||||
## 默认账号
|
||||
|
||||
- 用户名: `admin`
|
||||
- 密码: `admin`
|
||||
|
||||
**首次登录后请立即修改密码** (左侧导航 → 修改密码)。
|
||||
|
||||
## 配置路径
|
||||
|
||||
默认假设 Squid 安装在本机:
|
||||
- 配置文件: `/etc/squid/squid.conf`
|
||||
- 访问日志: `/var/log/squid/access.log`
|
||||
- 缓存日志: `/var/log/squid/cache.log`
|
||||
- 二进制: `squid`
|
||||
- 服务名: `squid`
|
||||
|
||||
如需管理远程 Squid 或路径不同,在
|
||||
**路径设置** 页面修改 (路径需在本平台可访问的位置)。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
squid-manager/
|
||||
├── app.py # Flask 应用 (模型、路由、业务逻辑)
|
||||
├── squid_config.py # squid.conf 解析 / 生成 / 校验
|
||||
├── log_parser.py # access.log 解析与统计
|
||||
├── wsgi.py # gunicorn 入口
|
||||
├── requirements.txt
|
||||
├── README.md
|
||||
├── instance/ # SQLite 数据库 (自动创建)
|
||||
│ └── squid_mgr.db
|
||||
├── backups/ # squid.conf 自动备份
|
||||
├── templates/ # Jinja2 模板
|
||||
│ ├── base.html
|
||||
│ ├── login.html
|
||||
│ ├── dashboard.html
|
||||
│ ├── logs.html
|
||||
│ ├── logs_import.html
|
||||
│ ├── logs_live.html
|
||||
│ ├── service.html
|
||||
│ ├── config_main.html
|
||||
│ ├── config_acls.html
|
||||
│ ├── config_rules.html
|
||||
│ ├── config_cache.html
|
||||
│ ├── config_refresh.html
|
||||
│ ├── config_auth.html
|
||||
│ ├── config_peers.html
|
||||
│ ├── config_raw.html
|
||||
│ ├── config_paths.html
|
||||
│ ├── audit.html
|
||||
│ ├── backups.html
|
||||
│ ├── change_password.html
|
||||
│ └── error.html
|
||||
└── static/
|
||||
└── style.css
|
||||
```
|
||||
|
||||
## 日志格式支持
|
||||
|
||||
标准 Squid access.log 格式 (默认):
|
||||
```
|
||||
time elapsed client action/code size method URL ident hierarchy content-type
|
||||
```
|
||||
|
||||
示例:
|
||||
```
|
||||
1783841223.438 2488 172.16.12.232 TCP_MISS_ABORTED/000 0 GET http://169.254.169.254/metadata/instance/compute - HIER_DIRECT/169.254.169.254 -
|
||||
1783841225.683 4564 172.16.237.9 TCP_TUNNEL/200 10197 CONNECT default.exp-tas.com:443 - HIER_DIRECT/13.107.5.93 -
|
||||
```
|
||||
|
||||
支持的结果码:
|
||||
- TCP_HIT, TCP_MEM_HIT, TCP_NEGATIVE_HIT, TCP_IMS_HIT, TCP_REFRESH_HIT (命中)
|
||||
- TCP_MISS, TCP_REFRESH_MISS, TCP_CLIENT_REFRESH_MISS (未命中)
|
||||
- TCP_TUNNEL (CONNECT 隧道)
|
||||
- TCP_DENIED, TCP_DENIED_REPLY (拒绝)
|
||||
- TCP_MISS_ABORTED (中断)
|
||||
- TCP_REDIRECT (重定向)
|
||||
- UDP_* (ICP 协议)
|
||||
- NONE (错误)
|
||||
|
||||
## 安全建议
|
||||
|
||||
1. **修改默认密码** - admin/admin 仅为示例
|
||||
2. **绑定内网 IP** - 不要暴露到公网,或前置 nginx + Basic Auth
|
||||
3. **限制文件权限** - 配置文件含敏感信息,确保 600
|
||||
4. **审计日志** - 定期查看 `/audit` 页面
|
||||
5. **TLS** - 生产环境建议 nginx 反代 + HTTPS
|
||||
|
||||
## 已知限制
|
||||
|
||||
- 服务控制 (start/stop/reload) 仅在 Squid 与本平台同机时有效
|
||||
- `squid -k parse` 校验需要本机有 squid 二进制
|
||||
- 多 gunicorn worker 下 SQLite 写入有竞态,已用 try/except 兜底
|
||||
- access.log 解析按需读取 (默认末尾 10000 行),不持久化
|
||||
|
||||
## TLS / HTTPS 部署指南
|
||||
|
||||
本 Web 平台本身默认监听 HTTP。在公网或需要 HTTPS 的内网场景下,**强烈不要把本平台直接暴露**
|
||||
请用 `nginx` 做反向代理 + TLS 终结。
|
||||
|
||||
Web UI 提供 **🔐 TLS 证书管理** 页面 (`/config/tls`):
|
||||
|
||||
### 1. 自签名证书 (仅用于测试 / 内网)
|
||||
|
||||
> 进入 **配置管理 → TLS 证书**,填入 Common Name (如 `proxy.example.local`),点击"生成自签名证书"。
|
||||
> 生成的文件保存在 `ssl_certs/` 目录下,名为 `CN_YYYYMMDD_xxxxxxxx.pem`,
|
||||
> 内含 cert + key,可直接用于 nginx 自测。
|
||||
>
|
||||
> 浏览器会提示"不受信任",仅用于内网 / 自测 / `curl -k`。
|
||||
|
||||
### 2. 生产部署: nginx 反代 + Let's Encrypt + 强制 HTTPS
|
||||
|
||||
最小化的 `nginx` 配置示例 (假设本平台监听 `127.0.0.1:5200`):
|
||||
|
||||
```nginx
|
||||
# HTTP -> HTTPS 强制重定向
|
||||
server {
|
||||
listen 80;
|
||||
server_name proxy.example.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# HTTPS 终结
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name proxy.example.com;
|
||||
|
||||
# Let's Encrypt 签发的证书
|
||||
ssl_certificate /etc/letsencrypt/live/proxy.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/proxy.example.com/privkey.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 1d;
|
||||
|
||||
# 转发到本平台
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:5200;
|
||||
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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
申请 Let's Encrypt 证书:
|
||||
|
||||
```bash
|
||||
# 一次性安装 certbot (Debian/Ubuntu)
|
||||
apt install -y certbot
|
||||
# 仅申请证书,不需要 nginx 插件 (webroot 模式)
|
||||
certbot certonly --webroot -w /var/www/html \
|
||||
-d proxy.example.com \
|
||||
--email admin@example.com --agree-tos -n
|
||||
# 证书自动存放在 /etc/letsencrypt/live/proxy.example.com/
|
||||
# 推荐加上 cron 自动续期
|
||||
echo "0 3 * * * /usr/bin/certbot renew --quiet --post-hook 'systemctl reload nginx'" \
|
||||
| sudo crontab -
|
||||
```
|
||||
|
||||
也可以从本平台 **上传** 页面手动上传 `.pem` / `.crt` / `.key` (上限 1 MB):
|
||||
|
||||
| 字段 | 用法 |
|
||||
|------|------|
|
||||
| 主题 (CN) | 证书绑定的域名,需与 nginx `server_name` 一致 |
|
||||
| 状态 | 绿色=有效 ≥30 天 / 黄色=<30 天 / 红色=已过期 |
|
||||
| SHA-256 指纹 | 审计追踪用,只记录指纹,**绝不写私钥内容** |
|
||||
|
||||
### 3. 常见误区
|
||||
|
||||
- 不要把 `ssl_certs/*.pem` 加入 git 或公网备份,文件含**私钥**
|
||||
- 不要把 80 / 443 直接绑到 `app.py` 运行端口,务必过 nginx (WAF / 限速 / 防护)
|
||||
- Let's Encrypt 单证书有效期 90 天,务必配置自动续期
|
||||
- 反代场景下,`app.py` 的 `SECRET_KEY` 必须固定 (环境变量),否则每次重启会话失效
|
||||
|
||||
Reference in New Issue
Block a user