一键导入
probe-audit
修改回落机制、伪装方案状态机、协议识别、连接处理代码后触发。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
修改回落机制、伪装方案状态机、协议识别、连接处理代码后触发。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
写入新模块文档、重构模块、或用户要求分析模块时触发。
Bug 修复或对接问题排查确认有效后,将经验记录到知识库。
修改 PMR 分配器、内存池配置、热路径容器、对象生命周期管理代码后触发。
编写或修改性能基准测试、分析 benchmark 结果、优化热路径性能时触发。
新增或修改 enable_shared_from_this 类、co_spawn 调用、shared_ptr 捕获的 lambda、co_await 后的成员访问时触发。
新增或修改原子操作、异步定时器、无锁通道、跨线程状态同步、CAS 竞争相关代码时触发。
| name | probe-audit |
| description | 修改回落机制、伪装方案状态机、协议识别、连接处理代码后触发。 |
在修改涉及回落(Fallback)机制、伪装方案状态机、协议识别、连接处理代码后,必须对变更部分执行以下审计清单。审查系统通过发送各种探测报文(重放、乱码、半截请求、跨协议握手、大规模并发)来验证服务端是否为代理服务器。
审查系统的主动探测分为三个阶段:
核心原则:服务端必须对每字节输入都有定义的标准输出。任何"未定义行为"都会暴露代理身份。
审查系统使用多种探针,每种有不同目的和检测逻辑。防御方必须理解每种探针的预期行为,确保响应不暴露代理特征:
| 探针目的 | 探针类型 | 预期观察 |
|---|---|---|
| 存在性确认 | 重放合法握手包 | 响应是否等于标准 TLS/Web 响应? |
| 协议识别 | 跨协议握手(SSH/HTTP/SOCKS5 到 443) | 是否暴露非 TLS 行为? |
| 认证探测 | 构造认证包(密码 hash/UUID) | 响应长度/时间是否因认证成功/失败而不同? |
| 密钥空间探测 | 逐字节变异(256 个变体) | 响应差异是否泄漏密钥信息? |
| 资源压力 | 大量并发 + 半开连接 | 降级行为是否暴露代理? |
| 时序分析 | 精确测量认证路径响应时间 | 时间差是否暴露认证逻辑? |
| 重放确认 | 数小时/数天后重放捕获的包 | 响应是否与首次连接不同? |
防御要点:
重放攻击防御的完整审计见
replay-audit技能
连接处理采用多方案管道架构,按优先级依次尝试已注册的伪装方案:
polluted 标志 — 如果数据已被修改到无法恢复,直接返回错误而非回卷审计时需关注:快照回卷是否完整、方案间状态是否泄漏、polluted 标志是否正确传播。
| 检查项 | 说明 |
|---|---|
| 首包窥探(Peek) | 是否在解密后对首包进行快速校验(长度、版本、认证)?校验失败必须回落 |
| 回落目标合法性 | 回落目标是否为真实的、工业级 Web 服务器?不得回落到空白页或自签名证书服务 |
| 回落转发完整性 | 回落转发时是否将原始数据完整传递给回落目标?不得丢弃或修改任何字节 |
| 连接不断开 | 校验失败时是否保持 TCP 连接并转发给回落目标?直接断开(RST)或黑洞不响应都会暴露代理 |
| 内存分配平稳 | 处理探针时是否避免异常的内存分配峰值?探针导致的 OOM 会间接暴露代理 |
| 回落目标可达性 | 回落目标是否始终可达?如果回落目标偶尔不可达,探针会收到不同响应,行为不一致暴露代理 |
| 检查项 | 说明 |
|---|---|
| HTTP 探针响应 | 探针发送 HTTP 请求时,服务端是否返回标准 HTTP 响应(如 400 Bad Request)?不得返回代理协议特有的错误格式 |
| 乱码探针响应 | 收到随机二进制数据时,服务端是否表现得与标准 Web 服务器一致? |
| 半截请求响应 | 收到不完整的 TLS 记录或 HTTP 请求时,服务端是否等待超时而非立即断开? |
| 错误响应格式 | 所有错误响应是否使用标准格式?不得包含代理软件特有的 header 或 body |
| 响应延迟一致性 | 同一类型的探针是否总是返回相同延迟的响应?如果有时快有时慢(依赖内部状态),延迟差异可能暴露内部逻辑 |
| 检查项 | 说明 |
|---|---|
| SSH 握手探测 | 审查系统会向 443 端口发送 SSH-2.0-OpenSSH 握手。服务端是否按标准 TLS 行为处理(TLS Alert 或忽略)?不得返回 SSH 错误或挂起 |
| 明文 HTTP 探测 | 向 443 端口发送 GET / HTTP/1.1。服务端是否在 TLS 层拒绝(返回 TLS Alert)而非在应用层处理? |
| SOCKS5 探测 | 向 443 端口发送 SOCKS5 握手头 \x05\x01\x00。服务端是否不返回 SOCKS5 响应? |
| 协议状态机隔离 | 同一端口上的不同协议处理器是否完全隔离?一个协议的解析错误不得影响另一个协议的状态 |
| 非 TLS 数据处理 | 在期望 TLS 握手的端口上收到非 TLS 数据时,是否发送标准 TLS Alert 后优雅关闭? |
| 检查项 | 说明 |
|---|---|
| 认证成功/失败时间差 | 认证成功路径和认证失败(回落)路径的响应时间是否接近?如果失败路径明显更快(直接回落 vs 建立代理连接),时间差可被测量 |
| 回落开销隐藏 | 回落到 dest 的连接建立开销是否被掩盖?可以在回落前添加随机延迟来抹平时间差异 |
| 密钥交换时间 | 不同认证阶段的处理时间是否一致?如果某种认证失败比其他失败更快,时间差暴露认证逻辑 |
| 错误响应时间 | 各种错误响应(400/403/404/407)的延迟是否与标准 Web 服务器的延迟一致? |
回落的正确性可以通过四个形式化属性来定义。任何回落实现都必须同时满足这四个属性:
不可区分性(Indistinguishability):对于任意输入 x,服务端响应必须在计算上与真实 Web 服务器的响应不可区分 — 包括响应内容和响应时间。这是最核心的安全目标。不可区分性必须覆盖所有可能的探针类型,而非仅针对已知探针类型。
完备性(Completeness):对于任意输入 x,服务端始终有一条定义好的响应路径。不存在"未处理"的输入。任何意外的输入格式、意外的长度、意外的协议标记都必须有明确的回落路径。如果存在未覆盖的输入,审查系统可以通过遍历来发现未定义行为,从而暴露代理。
状态无关性(State independence):回落行为不得依赖于先前的探测历史。如果第一次探测影响了第二次探测的响应行为,审查系统可以通过串行探测来推断内部状态机的存在。例如:如果第一个探针触发了某种内部缓存或错误状态,使得第二个不同类型的探针收到不同的响应,两个探针的响应矛盾就会暴露代理。每次连接的回落行为必须是独立的、无状态的。
资源公平性(Resource fairness):探针处理的资源消耗必须与正常请求一致。如果探针触发了异常的 CPU/内存消耗(例如正则回溯、超长缓冲区分配),审查系统可以通过资源压力探测来确认目标为代理(标准 Web 服务器在负载下的降级行为是已知的和可预测的)。
审查系统的探测不是单次行为,而是多阶段协调攻击。单一探针的防御是不够的 — 所有探针响应在联合分析时也必须一致。
典型的多阶段探测流程:
关键洞察:单次探针防御是不够的。当审查系统将多次探针的响应联合分析时,不同探针之间的矛盾会暴露代理身份。
典型的矛盾暴露场景:
Server: nginx),但 TLS 探针触发 OpenSSL 风格的 Alert — 矛盾暴露"声称 Nginx 但后端是 OpenSSL"防御要求:
所有探针类型的响应必须在内容和格式上相互一致(模拟同一个 Web 服务器)
所有探针的 TLS 指纹必须一致(同一个 TLS 库的实现特征)
所有探针的响应时间分布必须一致(与正常请求无明显差异)
大规模并发下,降级行为必须与真实 Web 服务器一致
TLS 1.2 降级路径合规:审查系统可能发送仅支持 TLS 1.2 的 ClientHello 来强制降级。降级后服务端的行为是否与标准 TLS 1.2 实现一致?降级路径的响应行为、密码套件选择、证书格式必须符合 TLS 1.2 规范,不得因降级而暴露非标准行为
| 检查项 | 说明 |
|---|---|
| 握手后 HMAC 验证 | TLS 通道建立后,第一个 application_data 记录是否携带 HMAC 签名?验证失败是否安全回落? |
| 验证时序 | HMAC 验证是否在数据传递给后端代理引擎之前完成?先传递后验证会暴露侧信道 |
| 常量时间比较 | HMAC 验证是否使用常量时间比较函数?非常量时间比较会通过响应时间差异泄漏 HMAC 值的信息 |
| 检查项 | 说明 |
|---|---|
| 前置代理架构 | 是否将工业级反向代理(CDN/Nginx/Caddy)置于代理核心之前?直接暴露代理核心会增加攻击面 |
| L7 路由验证 | 是否通过 HTTP 层的 Authorization header 进行第七层路由?仅匹配的请求才转发给代理引擎 |
| 默认页面 | 未匹配的请求是否返回合法的默认网页?空白响应或 404 是可疑特征 |
| 检查项 | 说明 |
|---|---|
| 外层 TLS 合规 | 如果使用双 TLS 架构(外层正常 TLS + 内层加密隧道),外层 TLS 是否完全模拟标准 Web 服务器行为? |
| 内层隐藏 | 内层加密隧道是否对外层完全不可见?审查系统的探针只能触及外层 TLS |
| WebSocket+TLS | 如果使用 WebSocket 作为传输,是否正确实现 HTTP 升级握手?升级前的 HTTP 行为必须与标准 Web 服务器一致 |
| CDN 前置 | 如果通过 CDN 前置,CDN 是否正确处理所有探针?CDN 的响应行为(错误页面、超时)是否与直接部署一致? |
| 检查项 | 说明 |
|---|---|
| 连接数限制 | 是否有最大连接数限制?审查系统可能通过大量并发连接来探测服务器的资源管理行为 |
| 单连接内存限制 | 单个连接的内存使用是否有上限?畸形或超大请求是否被限制? |
| 全阶段超时保护 | 所有握手和认证阶段是否有合理的超时?无超时则探针可占用连接资源,同时大量半开连接可导致服务降级 |
| 半开连接清理 | 半开连接(如只发了 ClientHello 未完成握手)是否被及时清理?积累的半开连接会影响正常用户的响应时间,响应时间异常间接暴露代理 |
| 降级行为模拟 | 资源耗尽时的降级行为是否与标准 Web 服务器一致?突然拒绝所有连接 vs 优雅降级是可区分的 |
| 检查项 | 说明 |
|---|---|
| 未授权探针处理 | 无密钥的探针到达时,是否退化为透明 TCP 转发器? |
| 证书篡改隐蔽性 | 合法客户端的证书签名篡改是否精确?篡改范围不得超出原始签名字段 |
| dest 连接可靠性 | 回落建立的到真实网站的连接是否可靠?dest 不可达会导致探针无法获得合法响应 |
| 握手超时保护 | 握手是否有超时保护?无超时则探针可占用连接资源 |
| 转发透明性 | 透明转发时是否完全透传所有字节?包括 TCP 紧急数据和窗口更新 |
重放攻击防御的完整审计见
replay-audit技能,涵盖时间戳校验、Nonce 唯一性、AEAD 认证、选择密文攻击防御、延迟重放防御、响应行为分析等。
replay-audit 覆盖了本 skill 未深入探讨的重放攻击 nonce 记忆持久化、选择密文攻击 256 变体防御、多用户分区预言攻击维度leak-audit 覆盖了本 skill 未深入探讨的错误响应格式指纹、日志泄漏、部署规模追踪维度traffic-audit 覆盖了本 skill 未深入探讨的流量统计分析、包长分布、时间间隔模式、多会话关联分析维度dpi-audit 覆盖了本 skill 未深入探讨的 TLS 指纹一致性、ALPN 协商状态机、TCP/IP 栈指纹维度security-audit 提供了安全审计 skills 的编排指南,确定修改特定代码时应按何种顺序执行哪些审计// ❌ 认证失败直接断开 — 暴露代理行为
if (!authenticated)
{
transport_->close();
}
// ✅ 认证失败透明转发到真实网站
if (!authenticated)
{
co_await fallback_dest(session, inbound, raw_record);
}
// ❌ 非常量时间比较 — 侧信道泄露
if (memcmp(received_hash, expected_hash, hash_len) == 0) { ... }
// ✅ 常量时间比较
if (CRYPTO_memcmp(received_hash, expected_hash, hash_len) == 0) { ... }
// ❌ 回落转发丢弃原始数据
auto [ec, raw_record] = co_await read_tls_record(inbound);
co_await async_write(dest, net::buffer(raw_record.data(), partial_size));
// ✅ 完整转发所有原始数据
co_await async_write(dest, net::buffer(raw_record.data(), raw_record.size()));
// ❌ 跨协议探测暴露身份 — 443 端口返回 SSH 错误
if (data.starts_with("SSH-2.0"))
{
co_await send("Protocol mismatch\r\n");
}
// ✅ 跨协议探测按 TLS 标准处理
if (!looks_like_tls_record(data))
{
co_await send_tls_alert(alert_level::fatal, alert_description::handshake_failure);
}
// ❌ 时序侧信道 — 认证失败路径明显更快
if (!authenticated)
{
co_return; // 立即返回,无回落开销
}
// ✅ 认证失败路径与成功路径时间接近
if (!authenticated)
{
co_await fallback_dest(session, inbound, raw_record); // 有回落开销
}
// ❌ 未处理输入 — 违反完备性
// 未知协议版本号直接忽略,无回落
if (version != expected_v1 && version != expected_v2)
{
co_return; // 未定义行为,探针无法获得任何响应
}
// ✅ 所有输入都有明确回落路径 — 满足完备性
if (version != expected_v1 && version != expected_v2)
{
co_await fallback_dest(session, inbound, raw_record); // 任何未知输入都回落
}
// ❌ 状态依赖 — 第二次探针收到不同响应
// 全局计数器导致第一次和第二次探针行为不同
static std::int32_t probe_count = 0;
probe_count++;
if (probe_count > threshold)
{
close_immediately(); // 降级行为异常,暴露内部状态
}
// ✅ 每次连接独立处理 — 满足状态无关性
// 不依赖全局探针计数,每次连接的回落行为独立
co_await fallback_dest(session, inbound, raw_record);
// ❌ 多探针矛盾 — HTTP 探针返回 Nginx 错误但 TLS 层暴露 OpenSSL
// HTTP 处理器
send_http_400_with_header("Server: nginx");
// TLS Alert 处理器
send_openssl_style_tls_alert(); // 与 Nginx 的 TLS 指纹不一致
// ✅ 所有响应层使用一致的 Web 服务器身份
// 统一使用目标回落服务器的完整指纹(HTTP 头 + TLS 行为 + 证书链)
co_await transparent_forward_to_dest(session, inbound, raw_record);
// ❌ 资源耗尽降级异常 — 达到连接上限后直接 RST
if (active_conns >= max_conns)
{
socket.close(); // 突然断开,标准 Web 服务器不会这样
}
// ✅ 资源耗尽降级行为与标准 Web 服务器一致
if (active_conns >= max_conns)
{
co_await send_http_503(); // 标准服务不可用响应
co_await graceful_close();
}