Repository navigation
[PR] fix: stop the welcome 302 and favicon routes hijacking MITM-vhost requests (#5024) - #5035
ranxianglei wants to merge 4 commits into
Conversation
…uests (#5024) The GET / welcome branch and the /favicon.ico local answer matched on path alone, so a MITM-decrypted vhost request re-entering the same handler with the upstream vhost's Host header (GET https://chatgpt.com/ => Host: chatgpt.com) was 302'd onto the local admin UI, answered with the {ok:true} health JSON, or served bili's bundled icon instead of being forwarded. Gate both routes on the request being addressed to the gateway itself via isTrustedAdminOrigin + adminTrustedHostnames - the same identity judgment as the /__bili/ origin gate (#1537): loopback names + concrete bind host, port-insensitive so SSH forwards keep working. Foreign-Host requests fall through to the normal forward path like every other path. Regression: tests/issue5024-welcome-host-gate.test.ts - 7 cases over the full proxy on real TCP; all three fixed facets fail on the unfixed code.
4432c5e to
a130185
Compare
📦 Built Package ArtifactBranch: Latest build — install this exact versionnpm install -g billion-context@0.0.7402-pr.5035.653bd8bThis exact version is immutable and reproducible. The rolling Recent builds (commit → version)
Download artifact
tar xzf billion-context-pr5035.tgz
npm install -g packageInstall instructions are refreshed on each push. |
(ai: vllm-qwen/qwen3.8-27b) 查重:不重复。 本 PR 即 #5024 的修复本身(Closes #5024);检索 open/closed issue 与近期 PR,无其他针对「welcome/favicon 路由缺 Host 判定」的在途修复。 独立审核结论:代码面通过。 我没有照抄 PR 描述与 #5024 triage 的结论,以下各项均自行重验: ① 方向关(原 issue):根因判断成立且修到了根机制——两个本地便利路由只按 path 匹配、不识别请求寻址对象;MITM 解密 socket 经 ② 回归审查(既有行为逐项清点):
③ 代码审查:复用既有身份判定而非新增机制;命名达意( ④ 测试有效性:新套件 7 case 断言有牙(具体状态码 + content-type + upstream 命中计数 + body 内容),不是恒真断言。红→绿我亲自复验:临时摘掉两处 gate 后恰好 3 个「fixed」case 失败(302 劫持 / JSON 兜底 / favicon 泄漏)、4 个「preserved」case 仍过,恢复后 7/7——该 bug 回归时它抓得住。相邻定向套件本地 39/39 通过(issue3536-favicon-local · mitm · issue3343-marker-divert-gate · issue3245-zcode-self-tunnel · dsh-panel-embed-cors)。 ⑤ diff 整洁度:2 文件 1 commit,每行都与本修复相关,无无关改动/锁文件/生成物。通过。 结构化八问:
合并前待办(唯一拦点,非代码问题):当前 PR head(4432c5e50)上的 CI runs 全部 cancelled,且 GitHub 显示分支 behind master(rebase 基 b08fbf3 之后 master 又前进了)——没有一份有效绿 CI。按 §7.2 需 rebase 到最新 master 后以新 head 的 CI 为准。我正尝试 rebase+push 触发新一轮 CI,但此刻出网代理不稳定(连接重置/CONNECT aborted),成功后回帖更新结果;若持续不通,请 owner 侧知悉此状态后再行合并。 判定:代码审核通过,可合入条件 = rebase 后 CI 绿。 |
[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b) 收工摘要:已两次把 origin/master 同步进本分支(最终含 44067a5,+124 commits),均无冲突,新 head |
Closes #5024
What was wrong
The gateway's local convenience routes matched on path alone, with no check on which host the request was addressed to. In MITM mode a decrypted vhost request re-enters the same HTTP server carrying the UPSTREAM vhost's
Hostheader, so:GET https://chatgpt.com/(bare root, browser HTML Accept) →302 /__bili/— real browser navigation hijacked onto the local admin UI;GET /through the tunnel withAccept: */*→ the gateway's{ok:true, upstream}health JSON instead of the site;GET /favicon.icofrom a vhost → answered with bili's bundled icon bytes instead of forwarding to the vhost's own favicon.Fix
Gate both routes (
GET /welcome branch +GET /favicon.ico) insrc/server/admin.tson the request being addressed to the gateway itself, reusing the existing identity judgment —isTrustedAdminOrigin(req.headers.origin, req.headers.host, adminTrustedHostnames(opts.host))— i.e. the same trusted-hostname discipline as the/__bili/origin gate (#1537): loopback names (localhost/127.0.0.1/::1) + the concrete bind host, port-insensitive so SSH port forwards keep working. Foreign-Host requests fall through to the normal forward path, exactly like every other path.The issue's suggested regex was the alternative considered; reusing the helper keeps one definition of "addressed to us" and inherits the #1537 SSH-forward / IPv6-bracket semantics for free.
Behavior changes (old → new)
GET /, HTML Accept302 → /__bili/(admin UI rendered on the vhost)GET /, other Accept{ok:true, upstream}JSONGET /favicon.ico--host 0.0.0.0LAN peer browsinghttp://<lan-ip>:8787/, or a loopback hostname alias likehttp://mybox.local:8787/)302 → /__bili/→ 403 page (the alias fails the admin origin gate)Hostheader at all (raw clients)ok:trueat/No config surface change, no kernel change, no wire/message-shape change, no new env vars.
Verification
tests/issue5024-welcome-host-gate.test.ts: 7 cases over the full proxy on real TCP (self-addressed 302 preserved · self-addressed health JSON preserved · foreign-vhost root not 302'd — forwards · foreign-vhostAccept:*/*not JSON'd — forwards · foreign-vhost favicon forwards · self-addressed favicon preserved · SSH-forward-style self name on another port still serves). A forged foreignHoston a loopback connection reproduces exactly what the MITM inner socket presents to the handler (origin-form path + upstream Host); the socket marker only changes where the fallback forwards, never whether the admin layer answers locally.issue3536-favicon-local(existing The favicon.ico request in the dsh settings panel is being routed into proxy forwarding (hitting upstream and returning | dsh 设置面板里的 favicon.ico 请求掉进代理转发(打到上游 403),面板静态资源路径应全部由管理面自答 #3536/Add a local favicon.ico to the WebUI to prevent browser favicon requests from being forwarded upstream and triggering re | WebUI 增加本地 favicon.ico,避免浏览器图标请求被转发上游并反复报错 #4830 favicon behavior fully preserved),mitm.test.ts,issue3343-marker-divert-gate,issue3245-zcode-self-tunnel,dsh-panel-embed-cors— 39/39 total with the new file. Local typecheck + build clean; full-suite verdict left to remote CI.