3ae96ef229
覆盖前端五端/后端/MySQL/弹性节点拓扑/Web安全/安全总纲,遵循 design/ 设计系统视觉呈现。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
188 lines
12 KiB
HTML
188 lines
12 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>04 机器与网络拓扑 · 穿山甲架构设计</title>
|
||
<link rel="stylesheet" href="assets/style.css">
|
||
</head>
|
||
<body>
|
||
|
||
<header class="site-header"><div class="inner">
|
||
<a class="brand" href="index.html"><img src="assets/logo-mark.svg" alt="Pangolin"><span><span class="zh">穿山甲 · 架构设计</span><br><span class="en">Pangolin Architecture</span></span></a>
|
||
<nav class="site-nav">
|
||
<a href="index.html">总览</a>
|
||
<a href="01-frontend.html">01 前端</a>
|
||
<a href="02-backend.html">02 后端</a>
|
||
<a href="03-database.html">03 数据库</a>
|
||
<a href="04-infra.html" class="active">04 网络拓扑</a>
|
||
<a href="05-web-security.html">05 Web 安全</a>
|
||
<a href="06-security.html">06 安全总纲</a>
|
||
</nav>
|
||
<button class="theme-btn" id="themeBtn" title="切换深浅主题"><i data-lucide="moon"></i></button>
|
||
</div></header>
|
||
|
||
<main class="doc">
|
||
|
||
<div class="doc-hero">
|
||
<div class="overline">Chapter 04 · Infrastructure & Topology</div>
|
||
<h1>机器与网络拓扑</h1>
|
||
<p class="lede">目标:<strong>弹性可变的网络拓扑</strong>——所有节点可一键更换或自动更换,IP 可随时轮换;任何单点被识别、被阻断都不影响整体服务。设计核心是「节点是牲口不是宠物」:节点无状态、可丢弃、分钟级重建。</p>
|
||
</div>
|
||
|
||
<section id="layers">
|
||
<h2><span class="num">§1</span>三层弹性拓扑</h2>
|
||
<div class="diagram">
|
||
<div class="flow">
|
||
<div class="fbox accent"><b>用户</b><span>REALITY / Hysteria2</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox"><b>入口层 Entry</b><span>消耗品 IP 池 · 多厂商 · 高频轮换</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox ghost"><b>中转层 Relay(可选)</b><span>内部隧道转发</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox ok"><b>落地层 Exit</b><span>精品 IP · 稳定出口 · 用户不可见</span></div>
|
||
</div>
|
||
<div class="flow">
|
||
<div class="fnote">免费用户:直连消耗品池入口(单跳直出)。付费用户:入口 → 落地两跳为主,中转层在入口与落地间链路质量差时按需启用。</div>
|
||
</div>
|
||
<div class="cap">被识别阻断的永远是入口 IP(暴露面);落地 IP 只对内部隧道可见,几乎不会被烧</div>
|
||
</div>
|
||
<div class="tbl-wrap"><table>
|
||
<thead><tr><th>角色</th><th>暴露面</th><th>IP 等级</th><th>更换频率</th><th>跑什么</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><strong>entry 入口</strong></td><td>直面用户与审查(唯一公网暴露)</td><td>消耗品池:冷门小厂、便宜、可隐私购买</td><td>被封即换;常态每 2–4 周主动轮换</td><td>sing-box(REALITY + Hy2 端口跳跃)+ agent</td></tr>
|
||
<tr><td><strong>relay 中转</strong></td><td>仅入口可见</td><td>低价大带宽</td><td>低频</td><td>内部隧道转发 + agent</td></tr>
|
||
<tr><td><strong>exit 落地</strong></td><td>仅中转/入口可见</td><td>精品池:稳定厂商、原生 IP、解锁好</td><td>极低频</td><td>出口 + agent</td></tr>
|
||
<tr><td><strong>probe 探针</strong></td><td>—</td><td>境内多 ISP 拨测点 + 境外对照点</td><td>—</td><td>探测脚本,结果回报控制面</td></tr>
|
||
</tbody>
|
||
</table></div>
|
||
<ul>
|
||
<li><strong>分级对应套餐</strong>(plan/ 既定策略):免费用户消耗免费池入口(tier=free),被封损失最小;付费用户走 tier=pro 入口 + 落地分层,体验稳定。</li>
|
||
<li>起步规模可以「入口=落地」单跳跑通,拓扑字段(role)从第一天就建模,后续平滑演进为分层,客户端无感。</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="cattle">
|
||
<h2><span class="num">§2</span>节点无状态化(可丢弃的前提)</h2>
|
||
<ul>
|
||
<li>节点上只有:sing-box + agent 二进制 + 由控制面下发的运行时配置(用户 UUID 表、伪装 SNI、密钥)。<strong>零用户库、零日志、零持久数据。</strong></li>
|
||
<li>全部由 <code>cloud-init</code> 一段脚本拉起:装 agent → agent 持引导 token 向控制面 mTLS 注册 → 控制面下发完整配置。重建一台 = 开机 + 等注册,约 3–5 分钟。</li>
|
||
<li>节点间不互信:中转/落地链路用独立隧道密钥,按节点对发放,回收节点即吊销。</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="lifecycle">
|
||
<h2><span class="num">§3</span>节点生命周期状态机</h2>
|
||
<div class="diagram">
|
||
<div class="flow">
|
||
<div class="fbox"><b>provisioning</b><span>厂商 API 开机中</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox warn"><b>probing</b><span>探活:境内外可达性验证</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox ok"><b>up</b><span>在目录 · 接受连接</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox warn"><b>draining</b><span>不接新连接 · 排空存量</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox bad"><b>down</b><span>已出目录</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox ghost"><b>destroyed</b><span>销毁 · IP 释放</span></div>
|
||
</div>
|
||
<div class="flow"><div class="fnote">up → down(跳过 draining):判封确认时立即下架。probing 失败 → 直接 destroyed(坏 IP 不入池)。每次迁移写 node_events 并 bump 目录 version。</div></div>
|
||
</div>
|
||
<ul>
|
||
<li><strong>目录灰度</strong>:<code>nodes</code> 任何变更 bump 全局 version;客户端带 <code>if_version</code> 轮询(在线连接中收到目录推送可平滑迁移);客户端缓存最后一份可用目录兜底。</li>
|
||
<li><strong>draining 排空</strong>:默认 30 分钟或存量连接归零,先到为准;免费节点可直接硬切(用户重连成本低)。</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="replace">
|
||
<h2><span class="num">§4</span>一键更换与自动更换</h2>
|
||
<h3>4.1 一键更换(管理端按钮 / CLI 一条命令)</h3>
|
||
<div class="diagram">
|
||
<div class="flow">
|
||
<div class="fbox accent"><b>replace(node)</b><span>管理端触发</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox"><b>开新机</b><span>厂商 API(同区域 · 厂商池内可换家)</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox"><b>cloud-init</b><span>装 agent · 自注册</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox warn"><b>probing</b><span>境内外探活通过</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox ok"><b>新机入池</b><span>version bump</span></div>
|
||
<div class="farr">→</div>
|
||
<div class="fbox"><b>旧机 draining</b><span>→ destroy · IP 释放</span></div>
|
||
</div>
|
||
<div class="cap">先建后拆(make-before-break):任何更换动作期间容量不下降</div>
|
||
</div>
|
||
<ul>
|
||
<li><strong>换 IP 不换机</strong>(更轻量):厂商支持弹性 IP 时直接 API 换绑 → 探活 → 更新 endpoint → version bump,全程分钟级。</li>
|
||
<li><strong>全量轮换</strong>:同一命令对整个池滚动执行(并发度 1–2),用于例行轮换或大面积事件后重建。</li>
|
||
<li>所有动作幂等、写 <code>audit_log</code> 与 <code>node_events</code>;基础设施定义用 Terraform + 厂商 API 适配层(providers 表登记,凭证独立 secrets 管理)。</li>
|
||
</ul>
|
||
<h3>4.2 自动更换:判封 → 下架 → 补新</h3>
|
||
<h4>判封信号(三路互证,避免误判)</h4>
|
||
<div class="tbl-wrap"><table>
|
||
<thead><tr><th>信号源</th><th>采集</th><th>说明</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><strong>境内探针</strong></td><td>电信 / 联通 / 移动 ≥3 个拨测点,每 5 分钟:TCP 连通 + TLS 握手 + 真实协议握手</td><td>核心信号;探针点用境内云函数/拨测服务,与运营身份隔离</td></tr>
|
||
<tr><td><strong>境外对照</strong></td><td>境外探针同款探测</td><td>区分「被墙」与「机器挂了」:境内挂 + 境外通 = 疑似被封;两边都挂 = 故障</td></tr>
|
||
<tr><td><strong>流量侧</strong></td><td>agent 上报在线数/带宽,环比骤降(如 15 分钟内 −80%)</td><td>辅助信号,提早怀疑</td></tr>
|
||
</tbody>
|
||
</table></div>
|
||
<h4>判定与处置规则(scheduler 驱动,阈值可配)</h4>
|
||
<ul>
|
||
<li><strong>疑似</strong>:境内 ≥2/3 拨测点连续 2 个周期失败,且境外正常 → <code>blocked_suspect</code>,节点降权(weight→10),加密探测频率。</li>
|
||
<li><strong>确认</strong>:连续 6 个周期(30 分钟)维持上述状态 → <code>blocked_confirmed</code> → 立即 <code>down</code> 出目录 + 自动触发 §4.1 补新流程。</li>
|
||
<li><strong>故障</strong>(境内外同挂):走告警人工介入,不消耗 IP 配额重建。</li>
|
||
<li><strong>容量保护</strong>:自动补新失败(厂商 API 错误、新机探活不过)连续 3 次 → 升级为告警;池内 up 节点低于水位线(如 tier 内 <70%)→ 无条件告警。</li>
|
||
<li><strong>熔断</strong>:1 小时内同池自动更换 >N 台(疑似大面积事件)→ 暂停自动重建、保留现场、人工决策(可能需要换厂商/换区域/换伪装 SNI 而非头铁补机)。</li>
|
||
</ul>
|
||
<div class="callout warn"><b>主动降低被封概率(比换得快更重要)</b>
|
||
<ul>
|
||
<li>REALITY 伪装 SNI 定期评估更换(目标站不可被墙、延迟特征合理);密钥/short_id 随节点轮换。</li>
|
||
<li>Hysteria2 端口跳跃(区间随机),抗 UDP QoS 与端口特征。</li>
|
||
<li>新 IP 上线前先「养」:探活通过后小流量灰度 24h 再放满 weight,避免新 IP 行为突变被标记。</li>
|
||
<li>免费池与付费池物理隔离(不同厂商账号),免费池被批量烧不殃及付费池。</li>
|
||
</ul></div>
|
||
</section>
|
||
|
||
<section id="scheduling">
|
||
<h2><span class="num">§5</span>调度、容量与厂商池</h2>
|
||
<h3>5.1 节点目录排序(服务端)与智能选择(客户端)</h3>
|
||
<ul>
|
||
<li>服务端目录按 <code>score = f(实时负载, 探针延迟, weight, tier)</code> 排序下发,给客户端一个好的默认顺序与「信号条」数据。</li>
|
||
<li>客户端「智能选择」(UI 默认选中):sing-box URLTest 在候选前 N 个节点本地实测自动择优——最终路径决策在端上,服务端只缩小候选集。</li>
|
||
</ul>
|
||
<h3>5.2 厂商池策略</h3>
|
||
<div class="tbl-wrap"><table>
|
||
<thead><tr><th>池</th><th>厂商画像</th><th>要求</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><strong>消耗品池</strong>(entry/free)</td><td>冷门小厂 ≥3 家,按量/小时计费,IP 便宜量大</td><td>有 API 可自动开退机;支持加密货币付款、隐私注册;避开被重点封锁的大厂 IP 段</td></tr>
|
||
<tr><td><strong>精品池</strong>(exit/pro entry)</td><td>稳定厂商 1–2 家,原生 IP、带宽质量好</td><td>同样隐私注册;区域:HK / JP / SG / US 起步</td></tr>
|
||
</tbody>
|
||
</table></div>
|
||
<ul>
|
||
<li>每家厂商独立账号、独立邮箱、加密货币付款——厂商之间、厂商与域名/收款之间不产生身份关联(红线,见 06 章)。</li>
|
||
<li>控制面(API + MySQL + Redis)部署在与节点完全无关的稳定云上,不放任何代理流量;节点全灭不影响控制面,反之亦然。</li>
|
||
</ul>
|
||
<h3>5.3 监控告警</h3>
|
||
<ul>
|
||
<li>节点心跳缺失(>90s)、池水位、自动更换熔断、探针自身失联、兑换失败率、注册转化漏斗。</li>
|
||
<li>告警出口:TG bot(运营专用匿名号)。所有告警附 runbook 链接(05 章)。</li>
|
||
</ul>
|
||
</section>
|
||
|
||
</main>
|
||
|
||
<nav class="pager">
|
||
<a href="03-database.html"><span>上一章</span><b>← 03 数据库</b></a>
|
||
<a class="next" href="05-web-security.html"><span>下一章</span><b>05 Web 安全与灾备 →</b></a>
|
||
</nav>
|
||
|
||
<footer class="colophon">穿山甲 · Pangolin — 内部架构设计文档 · 遵循 design/ 设计系统 · 2026-06</footer>
|
||
|
||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||
<script src="assets/doc.js"></script>
|
||
</body>
|
||
</html>
|