From a00512ac35f354ac034410308ea6dc02a33fc2ef Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Sat, 19 Sep 2026 15:22:57 +0800 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20Cloudflare=20=E5=9C=A8=E5=89=8D?= =?UTF-8?q?=E4=B8=8D=E7=94=A8=E5=86=8D=E9=85=8D=E6=9D=A5=E6=BA=90=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=EF=BC=9B=E5=88=AB=E5=AE=B6=20CDN=20=E7=94=A8=20realip?= =?UTF-8?q?=EF=BC=8C=E5=88=A0=E6=8E=89=E5=8F=AF=E4=BC=AA=E9=80=A0=E7=9A=84?= =?UTF-8?q?=20CF-Connecting-IP=20=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原来建议的 `proxy_set_header X-Forwarded-For $http_cf_connecting_ip;` 无条件信任这个头: 有人绕过 Cloudflare 直连源站时由他自己填,登录限流拦不住,也能把管理员锁在登录页外。 hub 现在认得 Cloudflare 的网段,只在连接来自那里时读 CF-Connecting-IP。 别家 CDN 改用 nginx 的 realip 模块,只信任 CDN 的回源网段。 --- src/content/install/reverse-proxy.mdx | 21 +++++++++++++++++---- src/content/reference/faq.mdx | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/content/install/reverse-proxy.mdx b/src/content/install/reverse-proxy.mdx index 39e2770..da69fe6 100644 --- a/src/content/install/reverse-proxy.mdx +++ b/src/content/install/reverse-proxy.mdx @@ -108,14 +108,27 @@ Cloudflare 免费版那 100 MB 的上传上限也就不是天花板了,单个 hub 取 `X-Forwarded-For` 的最后一跳,且只在 peer 本身是本地地址时才采信。上面两种反代都是追加 而不是覆盖,所以链尾才是代理真正看到的地址。 -本地反代前面再套一层 CDN 时,链尾是边缘的地址:所有访客共用一个限流桶, -面板上 NAT 节点显示的出口是边缘的地址,网卡上没有公网地址的节点,国家码也按边缘算。那种部署要让边缘自己写客户端地址 -(Cloudflare 的 `CF-Connecting-IP`),再由本地反代覆盖 `X-Forwarded-For`: +前面是 Cloudflare 的不用额外配置。走隧道时 `cloudflared` 就在本机,链尾就是访客;域名开了代理时链尾是 +Cloudflare 边缘,落在 [Cloudflare 公布的网段](https://www.cloudflare.com/ips/)里,hub 改读 Cloudflare +每次都会重写的 `CF-Connecting-IP`。这个头谁都能发,所以只在连接确实来自 Cloudflare 时才读。 + +本地反代前面套的是别家 CDN 时,链尾是边缘的地址:所有访客共用一个限流桶,面板上 NAT 节点显示的出口 +是边缘的地址,网卡上没有公网地址的节点,国家码也按边缘算。在 nginx 的 `server` 里用 realip 模块把 +边缘换回访客地址: ```nginx -proxy_set_header X-Forwarded-For $http_cf_connecting_ip; +# 每个回源网段一行,照 CDN 公布的列表填 +set_real_ip_from 192.0.2.0/24; +real_ip_header X-Forwarded-For; +real_ip_recursive on; ``` + + 以前照这一页写过 `proxy_set_header X-Forwarded-For $http_cf_connecting_ip;` 的,删掉这一行。 + 有人绕过 Cloudflare 直连源站时,这个头由他自己填:换着值试密码,登录限流就拦不住;填上你的地址, + 你就被锁在登录页外 15 分钟。 + + ### 4. 放行 `POST` / `PUT` / `DELETE` 面板的写操作用到这三个方法。有些默认只放行 `GET` / `HEAD` 的 WAF 规则会把整个后台变成只读。 diff --git a/src/content/reference/faq.mdx b/src/content/reference/faq.mdx index 759f932..af1b41f 100644 --- a/src/content/reference/faq.mdx +++ b/src/content/reference/faq.mdx @@ -87,6 +87,8 @@ IPv6、出口。机器自己的地址优先,因为出口可能属于挡在它 - 网关做了分流或透明代理:去 hub 的连接从代理出去,出口是代理的。节点没有公网 IPv6 的话,国家码也只能按代理出口算 - hub 只有 IPv6 入口:没有 IPv4 连接,NAT 节点的公网 IPv4 无从得知 +- hub 前面套了 Cloudflare 以外的 CDN:出口是 CDN 边缘的地址,按[反向代理](/install/reverse-proxy)里的 + realip 配置把访客地址换回来。Cloudflare 不用配,hub 自己认得 - 一台机器有多个公网地址,想显示指定的那个 手动填的值会一直显示,IP 变了要自己改。手动填的 IP 只影响显示,不影响国家码。 From ccfbeef08b3b30af8e918d20731cef6ca8cb004a Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Sat, 19 Sep 2026 16:16:38 +0800 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20CF-Connecting-IP=20=E5=8F=AA?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E8=8A=82=E7=82=B9=E5=9C=B0=E5=9D=80=EF=BC=9B?= =?UTF-8?q?=E8=A1=A5=20caddy=20=E7=9A=84=E5=86=99=E6=B3=95=E4=B8=8E?= =?UTF-8?q?=E6=9C=AC=E6=9C=BA=E9=9A=A7=E9=81=93=E6=8E=A5=20nginx=20?= =?UTF-8?q?=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 跟随 monitor#30 的修正:hub 只在验过节点 token 的连接上读 CF-Connecting-IP,登录限流不读, 因为 Worker 也能从 Cloudflare 网络连到源站并写这个头。写明开了代理时限流仍按边缘计。 - 别家 CDN 补上 caddy 的 trusted_proxies 写法,nginx 写法注明需要 realip 模块。 - 隧道先到本机 nginx 再到 hub 时,链尾是 127.0.0.1,同样用 realip,set_real_ip_from 填 127.0.0.1。 --- src/content/install/reverse-proxy.mdx | 32 +++++++++++++++++++++------ src/content/reference/faq.mdx | 2 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/content/install/reverse-proxy.mdx b/src/content/install/reverse-proxy.mdx index da69fe6..fed9ba5 100644 --- a/src/content/install/reverse-proxy.mdx +++ b/src/content/install/reverse-proxy.mdx @@ -108,21 +108,39 @@ Cloudflare 免费版那 100 MB 的上传上限也就不是天花板了,单个 hub 取 `X-Forwarded-For` 的最后一跳,且只在 peer 本身是本地地址时才采信。上面两种反代都是追加 而不是覆盖,所以链尾才是代理真正看到的地址。 -前面是 Cloudflare 的不用额外配置。走隧道时 `cloudflared` 就在本机,链尾就是访客;域名开了代理时链尾是 -Cloudflare 边缘,落在 [Cloudflare 公布的网段](https://www.cloudflare.com/ips/)里,hub 改读 Cloudflare -每次都会重写的 `CF-Connecting-IP`。这个头谁都能发,所以只在连接确实来自 Cloudflare 时才读。 +前面是 Cloudflare 的(域名开了代理,或者走隧道),节点的出口地址和国家码不用额外配置:hub 在验过节点 +token 的 agent 连接上读 Cloudflare 写的 `CF-Connecting-IP`。登录限流不读这个头:能从 Cloudflare 网络 +连到源站的不只 Cloudflare 的代理,Worker 也可以,这个头能被伪造。所以域名开了代理时,限流仍按边缘的 +地址计,同一个边缘后面的访客共用一个桶。 -本地反代前面套的是别家 CDN 时,链尾是边缘的地址:所有访客共用一个限流桶,面板上 NAT 节点显示的出口 -是边缘的地址,网卡上没有公网地址的节点,国家码也按边缘算。在 nginx 的 `server` 里用 realip 模块把 -边缘换回访客地址: +本地反代前面是别家 CDN,或者隧道先到本机的 nginx 再到 hub 时,链尾是边缘或隧道的地址,所有访客共用 +一个限流桶;别家 CDN 后面,NAT 节点显示的出口、网卡上没有公网地址的节点的国家码也按边缘算。在反代上 +把边缘换回访客地址,只信任列出的网段: ```nginx -# 每个回源网段一行,照 CDN 公布的列表填 +# 写在 server 里。每个回源网段一行,照 CDN 公布的列表填;隧道在本机时填 127.0.0.1 set_real_ip_from 192.0.2.0/24; real_ip_header X-Forwarded-For; real_ip_recursive on; ``` +这要求 nginx 带 realip 模块,`nginx -V 2>&1 | grep realip` 有输出就有。caddy 的写法: + +```caddyfile +{ + servers { + trusted_proxies static 192.0.2.0/24 + trusted_proxies_strict + } +} + +hub.example.com { + reverse_proxy 127.0.0.1:28080 { + header_up X-Forwarded-For {client_ip} + } +} +``` + 以前照这一页写过 `proxy_set_header X-Forwarded-For $http_cf_connecting_ip;` 的,删掉这一行。 有人绕过 Cloudflare 直连源站时,这个头由他自己填:换着值试密码,登录限流就拦不住;填上你的地址, diff --git a/src/content/reference/faq.mdx b/src/content/reference/faq.mdx index af1b41f..b6671ba 100644 --- a/src/content/reference/faq.mdx +++ b/src/content/reference/faq.mdx @@ -88,7 +88,7 @@ IPv6、出口。机器自己的地址优先,因为出口可能属于挡在它 的话,国家码也只能按代理出口算 - hub 只有 IPv6 入口:没有 IPv4 连接,NAT 节点的公网 IPv4 无从得知 - hub 前面套了 Cloudflare 以外的 CDN:出口是 CDN 边缘的地址,按[反向代理](/install/reverse-proxy)里的 - realip 配置把访客地址换回来。Cloudflare 不用配,hub 自己认得 + realip 配置把访客地址换回来。Cloudflare 不用配,hub 读它写给节点连接的 `CF-Connecting-IP` - 一台机器有多个公网地址,想显示指定的那个 手动填的值会一直显示,IP 变了要自己改。手动填的 IP 只影响显示,不影响国家码。