架构总览
三层结构
text
┌──────────────────────────── nginx worker ────────────────────────────┐
│ │
│ 模块本体 ngx_http_cfd_tunnel_module.c │
│ ├─ 指令与配置(42 条,main conf = 一条隧道实例) │
│ ├─ 进程生命周期(init_process / exit_process) │
│ ├─ 1 s 内务定时器(背压采样、超时、停滞判定) │
│ └─ 启动期校验与告警 │
│ │
│ 传输层 cfd_ngx_transport.c ── nginx 自己的 OpenSSL(ALPN=h2) │
│ ├─ h2 会话:nghttp2 服务端 API(本端主动连边缘,但收流用 server) │
│ ├─ 写路径与背压(SSL_write 重试约束) │
│ └─ 控制流:Cap'n Proto RPC(register / heartbeat / update-config)│
│ │
│ 注入层 cfd_ngx_inject.c │
│ ├─ 造虚拟 ngx_connection_t → ngx_http_init_connection() │
│ ├─ 请求头序列化 cfd_hdr_ser.c(含 Upgrade / trailer) │
│ ├─ 远程规则匹配 cfd_rcfg.c(0.12.0) │
│ └─ MIME 嗅探 cfd_mimesniff.c(对齐 Go 的默认行为) │
│ │
│ 协议层 src/(26 个文件,与阶段 1 独立客户端共用同一份) │
│ cfd_h2 / capnp_* / cfd_rpc / cfd_creds / cfd_transport.h / │
│ cfd_client / cfd_tls / cfd_quick / cfd_tls_client / cfd_proxy / │
│ cfd_json / capnp_templates.h(生成物) │
└──────────────────────────────────────────────────────────────────────┘没有第四层:不需要额外的 cloudflared 进程、不需要共享内存、不需要一个要自己管理的 UDS 路径 (虚拟连接用的是 socketpair(AF_UNIX) 的 fd 作连接身份载体,数据一个字节都不经过它,而是由 模块通过 c->recv / c->send 直接喂给 nginx 的 HTTP 解析器 —— 详见 注入层)。
一条请求的完整路径
text
1. 边缘在隧道连接上新开一条 h2 流,带请求头(`:path`、`host`、`Cf-Connecting-IP` …)
2. 传输层把这条流交给注入层(裸 TCP 流的判据在这里:Cf-Cloudflared-Proxy-Src)
3. 注入层:远程规则匹配(可选)→ 定注入端口与 Host → 选监听器
4. 注入层:构造虚拟连接,把请求头序列化成 HTTP/1.1 字节喂进 nginx 的 HTTP 解析器
5. nginx:server_name / location / rewrite / proxy_pass / 变量 / access_log(全原生)
6. 注入层:把 nginx 的响应(含 chunked 解块、trailer)写回那条 h2 流
7. 记账释放(连接级配额一并归还),流关闭运行期模型
- 每 worker 一份:配置是 COW 拷贝;运行期状态(连接、流表、背压记账、定时器)每 worker 独立。
- 每条在途注入连接 = 一个连接槽 + 一条
socketpair:连接槽与 fd 都是真的(ngx_get_connection()/socketpair(AF_UNIX)),数据不经过 fd,只经c->recv/c->send三个函数指针。 - 每隧道一条连接:多 worker 时每条隧道在每个 worker 各建一条(
connIndex= worker 槽位, 可用conn_index指定);快速隧道例外,只由 0 号 worker 建。 - 单条 h2 连接上多流并发:控制流(Cap’n Proto RPC)与数据流并存,靠 nghttp2 统一调度。
- 1 s 内务定时器:背压采样、停滞判定、预算淘汰、拒绝线检查都在这里做(
CFD_HOUSEKEEPING_TICK)。
代码地图
| 文件 | 职责 |
|---|---|
ngx_http_cfd_tunnel_module.c | 指令、配置、生命周期、注入入口、定时器、背压五层、启动校验、快速隧道编排 |
cfd_ngx_transport.c/.h | TLS + h2 会话、写路径与背压、nghttp2 回调 |
cfd_ngx_inject.c/.h | 注入器:h2 流 → nginx 虚拟连接 + 原生请求 |
cfd_hdr_ser.c/.h | h1 请求头序列化与合成(WebSocket、请求 trailer) |
cfd_mimesniff.c/.h | 上游缺 Content-Type 时的 MIME 嗅探(对齐 cloudflared/Go) |
cfd_rcfg.c/.h | 远程配置规则表的解析、校验、匹配与惰性注入目标缓存 |
src/(26 个文件) | 协议层:h2、capnp、RPC、凭据、传输抽象、隧道编排、TLS、快速隧道、代理、JSON |
config | 动态模块构建描述(ngx_addon_name / ngx_module_srcs / -lnghttp2 -lz) |
tools/ | gen-template.py 生成 src/capnp_templates.h;regen-templates.sh --check 对账 |