4a1d949e41
完整 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
207 lines
11 KiB
HTML
207 lines
11 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}SSL Bump - Squid Manager{% endblock %}
|
||
{% block content %}
|
||
<div class="page-header">
|
||
<h1>🔐 SSL Bump (HTTPS 透明代理)</h1>
|
||
<div class="page-actions">
|
||
<button onclick="document.getElementById('add-form').style.display='block'" class="btn btn-primary btn-small">➕ 添加规则</button>
|
||
<button onclick="document.getElementById('cert-form').style.display='block'" class="btn btn-secondary btn-small">🪪 生成自签 CA</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card" style="border-left: 4px solid #d33; background: #fff8f8;">
|
||
<h3 class="card-title" style="color:#c0392b;">⚠️ 风险与合规提示</h3>
|
||
<ul>
|
||
<li><b>中间人攻击:</b> 启用 <code>bump</code> 后代理会解密所有 HTTPS 流量,浏览器看到的是代理签名的证书而非真实证书。</li>
|
||
<li><b>私钥泄露风险:</b> 必须在受信环境运行;一旦 CA 私钥泄露,所有用它签名的中间证书都可以伪造。</li>
|
||
<li><b>用户信任:</b> 客户端必须安装并信任你生成的 CA;否则会看到证书错误。</li>
|
||
<li><b>审计/合规:</b> 许多司法管辖区要求告知用户并获取同意;请提前与法务/合规团队沟通。</li>
|
||
<li><b>替代方案:</b> 如果只是需要域名过滤,优先用 <code>splice</code> (不解密) + SNI 嗅探;只有需要看 payload 时再用 <code>bump</code>。</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3 class="card-title">📋 默认规则示例</h3>
|
||
<pre class="code-block"><code>{{ default_example|e }}</code></pre>
|
||
<p class="meta-text">规则按顺序匹配,首条命中即停止。建议先用 <code>splice</code> 放通全部,排查没问题后再加 <code>peek</code>/<code>bump</code>。</p>
|
||
</div>
|
||
|
||
<div class="card" id="add-form" style="display:none;">
|
||
<h3 class="card-title">添加新 SSL Bump 规则</h3>
|
||
<form method="post" class="inline-form">
|
||
<input type="hidden" name="_csrf" value="{{ csrf_token() }}">
|
||
<input type="hidden" name="action" value="add">
|
||
<div class="filter-grid">
|
||
<div class="form-group">
|
||
<label>动作 (action)</label>
|
||
<select name="action_type" class="form-input">
|
||
{% for a in actions %}
|
||
<option value="{{ a }}" {% if a == 'peek' %}selected{% endif %}>{{ a }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<div class="form-group" style="grid-column: span 2;">
|
||
<label>ACL 列表 <span class="hint">(空格分隔,支持 <code>!aclname</code> 取反,如 <code>!localhost trusted_net</code>)</span></label>
|
||
<input type="text" name="acls" class="form-input" placeholder="step1 all">
|
||
</div>
|
||
<div class="form-group" style="grid-column: span 3;">
|
||
<label>备注</label>
|
||
<input type="text" name="comment" class="form-input" placeholder="示例: 缺省放行">
|
||
</div>
|
||
</div>
|
||
<details class="hint" style="margin-top: 0.5em;">
|
||
<summary>📚 动作含义</summary>
|
||
<ul style="margin-top: 0.5em;">
|
||
<li><code>peek</code> - 在 SslBump1 解密 client hello,只读 SNI/ALPN,不解后续</li>
|
||
<li><code>splice</code> - TCP 直通隧道,不解密 (性能最好,几乎无开销)</li>
|
||
<li><code>bump</code> - 完整解密,代理签发证书,可看明文 (最慢/最重)</li>
|
||
<li><code>terminate</code> - 主动关闭连接 (用于阻断)</li>
|
||
<li><code>client-first</code> / <code>server-first</code> - 控制 TLS 握手方向</li>
|
||
<li><code>none</code> - 显式禁用 (用于在内层 step 关闭默认行为)</li>
|
||
</ul>
|
||
</details>
|
||
<div class="form-actions">
|
||
<button type="submit" class="btn btn-primary">添加</button>
|
||
<button type="button" onclick="document.getElementById('add-form').style.display='none'" class="btn btn-secondary">取消</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<p class="card-desc">当前共 <b>{{ rules | length }}</b> 条 SSL Bump 规则。按表从上到下顺序匹配,首条命中即终止。</p>
|
||
<p class="meta-text">可用 ACL:
|
||
{% for name in acls_by_name.keys() %}
|
||
<code>{{ name }}</code>{% if not loop.last %} · {% endif %}
|
||
{% else %}
|
||
<em>暂无 ACL,请先在「ACL 规则表」页面创建。</em>
|
||
{% endfor %}
|
||
</p>
|
||
<form method="post">
|
||
<input type="hidden" name="_csrf" value="{{ csrf_token() }}">
|
||
<input type="hidden" name="action" value="save">
|
||
<div class="table-scroll">
|
||
<table class="data-table rules-table">
|
||
<thead>
|
||
<tr>
|
||
<th style="width:60px;">#</th>
|
||
<th style="width:160px;">动作</th>
|
||
<th>ACL</th>
|
||
<th>备注</th>
|
||
<th style="width:80px;">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for r in rules %}
|
||
<tr>
|
||
<td>{{ loop.index }}
|
||
<input type="hidden" name="id[]" value="{{ loop.index }}">
|
||
</td>
|
||
<td>
|
||
<select name="action_type[]" class="form-input">
|
||
{% for a in actions %}
|
||
<option value="{{ a }}" {% if r.action == a %}selected{% endif %}>{{ a }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</td>
|
||
<td><input type="text" name="acls[]" value="{{ r.acls | join(' ') }}" class="form-input" placeholder="!localhost trusted_net"></td>
|
||
<td><input type="text" name="comment[]" value="{{ r.comment }}" class="form-input"></td>
|
||
<td>
|
||
<button type="button" class="btn btn-danger btn-tiny" onclick="this.closest('tr').remove()">删除</button>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
{% if not rules %}
|
||
<tr><td colspan="5" class="empty-row">暂无规则。点击"添加规则"开始,或先在下方配置 sslcrtd / sslproxy_ca_* 再添加 peek/splice 规则。</td></tr>
|
||
{% endif %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{% if rules %}
|
||
<div class="form-actions">
|
||
<button type="submit" class="btn btn-primary">💾 保存所有规则与 SSL 设置</button>
|
||
</div>
|
||
{% endif %}
|
||
</form>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3 class="card-title">🗄️ SSL 数据库与 CA 证书设置</h3>
|
||
<p class="meta-text">
|
||
这些是让 SSL Bump 真正起作用的底层配置。
|
||
<b>sslcrtd_program</b> + <b>sslcrtd_children</b> 控制 on-the-fly 自签证书生成器;
|
||
<b>sslproxy_ca_certfile</b> + <b>sslproxy_ca_keyfile</b> 指向你用作 CA 的证书与私钥。
|
||
</p>
|
||
<form method="post">
|
||
<input type="hidden" name="_csrf" value="{{ csrf_token() }}">
|
||
<input type="hidden" name="action" value="save">
|
||
<div class="filter-grid">
|
||
<div class="form-group" style="grid-column: span 3;">
|
||
<label>sslcrtd_program <span class="hint">(完整命令行: 可执行文件 + 参数,空格分隔)</span></label>
|
||
<input type="text" name="sslcrtd_program" class="form-input"
|
||
value="{{ simple.sslcrtd_program }}"
|
||
placeholder="security_file_certgen -s /var/lib/squid/ssl_db -M 4 MB">
|
||
</div>
|
||
<div class="form-group" style="grid-column: span 3;">
|
||
<label>sslcrtd_children <span class="hint">(空格分隔,如 <code>5 startup=1 idle=1</code>)</span></label>
|
||
<input type="text" name="sslcrtd_children" class="form-input"
|
||
value="{{ simple.sslcrtd_children }}"
|
||
placeholder="5 startup=1 idle=1">
|
||
</div>
|
||
<div class="form-group" style="grid-column: span 3;">
|
||
<label>sslproxy_ca_certfile <span class="hint">(CA 证书路径,绝对路径)</span></label>
|
||
<input type="text" name="sslproxy_ca_certfile" class="form-input"
|
||
value="{{ simple.sslproxy_ca_certfile }}"
|
||
placeholder="/etc/squid/bump_ca.crt">
|
||
</div>
|
||
<div class="form-group" style="grid-column: span 3;">
|
||
<label>sslproxy_ca_keyfile <span class="hint">(CA 私钥路径,绝对路径)</span></label>
|
||
<input type="text" name="sslproxy_ca_keyfile" class="form-input"
|
||
value="{{ simple.sslproxy_ca_keyfile }}"
|
||
placeholder="/etc/squid/bump_ca.key">
|
||
</div>
|
||
</div>
|
||
<div class="form-actions">
|
||
<button type="submit" class="btn btn-primary">💾 保存 SSL 数据库与 CA 设置</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="card" id="cert-form" style="display:none;">
|
||
<h3 class="card-title">🪪 生成 SSL Bump 自签 CA (便利工具)</h3>
|
||
<p class="meta-text">
|
||
一键生成自签 CA 证书到 <code>ssl_certs/</code>。生成后请将证书安装到所有需要被 SSL Bump 的客户端的"受信任的根证书颁发机构"。
|
||
<b>注意:</b> 不要复用生产 CA 私钥。
|
||
</p>
|
||
<form method="post">
|
||
<input type="hidden" name="_csrf" value="{{ csrf_token() }}">
|
||
<input type="hidden" name="action" value="generate-cert">
|
||
<div class="filter-grid">
|
||
<div class="form-group">
|
||
<label>Common Name (CN)</label>
|
||
<input type="text" name="common_name" class="form-input" value="Squid Bump CA" placeholder="Squid Bump CA">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>有效期 (天)</label>
|
||
<input type="number" name="days" class="form-input" value="3650" min="1" max="36500">
|
||
</div>
|
||
</div>
|
||
<div class="form-actions">
|
||
<button type="submit" class="btn btn-primary">🪪 生成</button>
|
||
<button type="button" onclick="document.getElementById('cert-form').style.display='none'" class="btn btn-secondary">取消</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3 class="card-title">📖 参考</h3>
|
||
<ul>
|
||
<li><code>peek</code>: 解密 client hello 拿到 SNI/ALPN,然后视后续 step 再决定;不让代理完整解密流量。</li>
|
||
<li><code>splice</code>: 直接把 TCP 流透传给 origin,不解密;性能最佳,适合大批流量。</li>
|
||
<li><code>bump</code>: 完整解密 TLS,代理用 sslproxy_ca_certfile 签发 leaf cert;</li>
|
||
<li><code>terminate</code>: 客户端 TCP 被代理关闭 (用于拒绝)。</li>
|
||
<li>ACL 列表里用 <code>!</code> 取反,多个 ACL 之间为 AND (全部满足)。</li>
|
||
<li>常见配套: <code>acl step1 at_step SslBump1</code> + <code>ssl_bump peek step1</code> 然后 <code>ssl_bump splice all</code>。</li>
|
||
</ul>
|
||
</div>
|
||
{% endblock %}
|