Repository navigation
fix: Cloudflare 在前时按 CF-Connecting-IP 取来源地址 - #30
Merged
Merged
Conversation
hub 前面套 Cloudflare(域名开代理)再接本地反代时,X-Forwarded-For 的最后一跳是 Cloudflare 边缘的地址。 节点的出口、按出口查的国家码、登录限流与注册锁定、登录通知里的地址,都会变成边缘的地址。 来源地址(XFF 链尾,或直连时的 peer)落在 Cloudflare 公布的网段里时,改读 CF-Connecting-IP。 Cloudflare 每次转发都会重写这个头;网段之外的连接带着它也不采信,直连源站伪造不了。 Closes #28
This was referenced Sep 19, 2026
上一版按「来源在 Cloudflare 网段内」采信这个头,但能从 Cloudflare 网络连到源站的不只 Cloudflare 自己的代理:Worker 的原始 TCP socket 同样从这些网段出来,请求头随便写。于是任何人都能换着值绕过 登录锁定,或填上管理员的地址把他锁在外面;而且这条规则对不在 Cloudflare 后面的 hub 也生效。 改为新增 auth::node_ip,只在 agent 握手、节点 token 验过之后读这个头,用作节点的出口与国家码的 来源。持有 token 的一方本来就能上报任意地址,没有新增的伪造面。client_ip 回到原样,登录限流、 注册锁定仍按链尾计。网段表随之删除;隧道先经本机 nginx 再到 hub 的链路,节点地址也一并取对。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
#28:域名开了 Cloudflare 代理、再由本地 nginx / caddy 反代到 hub 时,
X-Forwarded-For的最后一跳是 Cloudflare 边缘的地址(截图里的162.158.88.126)。hub 把它当成节点的连接来源:节点取址的规则是「网卡上的地址归 agent,出口归 hub」,Cloudflare 在前时出口这一半从来就不对。
改动
新增
auth::node_ip,agent 握手在验过节点 token 之后用它取来源:请求带CF-Connecting-IP时用它,否则与client_ip相同。Cloudflare 的代理与隧道都会把节点的真实地址写进这个头。登录限流、注册锁定、登录通知仍用
client_ip,不读这个头。 能从 Cloudflare 网络连到源站的不只 Cloudflare 的代理:Worker 的原始 TCP socket 同样从 Cloudflare 的网段出来,请求头随便写。按「来源在 Cloudflare 网段内就采信」的做法(本 PR 第一个提交),任何人都能换着值绕过登录锁定,或填上管理员的地址把他锁在外面,而且对不在 Cloudflare 后面的 hub 同样生效。第二个提交改成现在的做法,网段表随之删除。只在节点连接上读这个头不新增伪造面:持有节点 token 的一方本来就能上报任意地址(hello 里的
ipv4/ipv6)。顺带覆盖的:隧道先到本机 nginx 再到 hub 的链路,链尾是 127.0.0.1,但
CF-Connecting-IP一路带着,节点地址同样取对。开了代理时,登录限流仍按边缘地址计,同一个边缘后面的访客共用一个桶,这一点与现在相同。别家 CDN 由反代的 realip 配置把边缘换回访客地址,见配套文档 PR。
验证
cargo fmt --check、cargo clippy --all-targets -- -D warnings、cargo test(108 个)通过。forwarded_header_is_trusted_only_behind_a_local_proxy补了断言:Cloudflare 在前时client_ip仍是边缘,node_ip是节点;没有这个头时两者相同。端到端:独立的 network namespace 里给 lo 加上一个 Cloudflare 边缘地址、一个「直连访客」地址和一个「别家 CDN」地址,前面放 nginx,用带有效节点 token 的 WebSocket 握手看 hub 记下的节点来源:
CF-Connecting-IP登录限流:从同一个 Cloudflare 边缘连续 6 次输错密码,每次换一个伪造的
CF-Connecting-IP,结果401 401 401 401 401 429,头没有被当成新的身份。兼容
无 schema、接口、agent 协议变化。升级后节点重连时按新的来源更新出口,地址变了的会重新查一次国家码。
配套文档:monitor-probe/monitor-document#9。
Closes #28