多隧道
一条隧道不够时(不同域名走不同后端、具名隧道与临时隧道并存……),把每条隧道写成一个 cfd_tunnel {} 块。块里的 inject_listen 决定「这条隧道来的请求送进哪个 listen」; 注入进去的请求就是那个 listen 上的一条普通客户端连接,于是落到那个 listen 的 server {} 里。
nginx
http {
# 模块级配置:对所有隧道生效
cfd_tunnel_edge region1.v2.argotunnel.com:7844;
cfd_tunnel_global_bq_limit 64m;
cfd_tunnel { # 具名隧道 A → 127.0.0.1:8080
name edge-a;
credentials /etc/nginx/cloudflared/a.json;
inject_listen 127.0.0.1:8080;
}
cfd_tunnel { # 具名隧道 B → 127.0.0.1:8082
name edge-b;
token_file /etc/nginx/cloudflared/b.token;
inject_listen 127.0.0.1:8082;
}
cfd_tunnel { # 临时隧道 → 127.0.0.1:8090
name quick-1;
quick on;
inject_listen 127.0.0.1:8090;
}
cfd_tunnel { # 与 quick-1 同一个端口(允许)
name quick-2;
quick on;
inject_listen 8090; # 也可以只写端口号
}
server { listen 127.0.0.1:8080; server_name a.example.com; ... }
server { listen 127.0.0.1:8082; server_name b.example.com; ... }
server { listen 127.0.0.1:8090; ... } # 随机域名只能靠默认 server 兜住
}块内 12 条指令
| 指令 | 含义 |
|---|---|
name | 可选;只进日志(cfd_tunnel: [edge-a] …),不写就用 #序号 |
credentials | 凭据文件路径(与 quick / token / token_file 四选一) |
quick | on = 这条隧道启动时申请临时地址 |
token | 这条隧道的 token(等价 cfd_tunnel_token) |
token_file | 这条隧道的 token 文件(等价 cfd_tunnel_token_file) |
quick_service / quick_timeout | 覆盖模块级同名配置 |
inject_listen | 注入目标(ip:port 或只写端口);开了 remote_config 可以不写 |
inject_source_addr | 这条隧道的注入来源地址(不写继承模块级) |
remote_config | on = 接受边缘下发的远程配置 |
host_override | 注入请求的 Host 覆盖值(同时写 X-Forwarded-Host) |
conn_index | 默认按 worker 自动分配 |
要点
- 允许多条隧道指向同一个端口。 注入期间临时改监听器标志位的窗口是同步的,并发安全; 但请求会落到该
listen的默认 server,除非注入的Host命中某个server_name。 - 一条坏掉不拖累其他。 凭据读不出、注入目标不存在、临时隧道申请失败,都只跳过那一条 (
error_log带隧道名说明原因),其余隧道照常注册、照常服务。 - 扁平写法仍然可用。 不写任何
cfd_tunnel {}时,原来那组cfd_tunnel_*就是「那一条隧道」, 行为与 0.10.0 完全一致(日志文本也逐字节相同)。两种写法不能混用,nginx -t直接失败。 - 多 worker。 每条隧道在每个 worker 各建一条连接(
connIndex取ngx_process_slot, 也可在块里用conn_index指定);临时隧道例外,每条都只由 0 号 worker 建。 - 内存。 背压阈值是模块级的一份配置,但记账每条隧道独立(严格对齐 cloudflared: 它一个进程一条隧道、一份预算,A 隧道积压绝不会让 B 隧道拒流)。所以请求体缓冲的内存上界是 N ×
cfd_tunnel_global_bq_limit(默认64m,3 条隧道就是 192m)—— 要压住就调小这个值。 - 查临时地址。
cfd-quick-url -a列出全部地址(每行一个 URL,不带隧道名); 要知道某个地址属于哪条隧道,在error_log里grep 'cfd_tunnel: \[',带名字的行里名字与地址同行。
配置期会拒绝的几件事
bash
nginx -t- 块与扁平写法混用(除非那些指令是「模块级 + 块内都允许」的,例如
inject_source_addr)。 - 同一个块里凭据来源写了两个(
credentials+token)。 - 块里既没开
remote_config又没写inject_listen。 inject_listen只写端口时,如果这个端口上存在多个监听地址(例如127.0.0.1:8090与0.0.0.0:8090同时存在),这条隧道会被判「有歧义」并单独跳过(只在日志里说明,不猜是哪 一个),其余隧道照常。