From 5f6fca5c59c28a2248023765cdb3fc1fcd95690f Mon Sep 17 00:00:00 2001 From: HomeDash Bot Date: Fri, 11 Sep 2026 20:34:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(gateway):=20=E6=9C=AA=E7=9F=A5=E5=9F=9F?= =?UTF-8?q?=E5=90=8D=E5=BF=85=E9=A1=BB=E8=A2=AB=E5=85=9C=E5=BA=95=E6=8B=92?= =?UTF-8?q?=E7=BB=9D=EF=BC=8C=E4=B8=8D=E8=83=BD=E8=90=BD=E8=BF=9B=E6=9F=90?= =?UTF-8?q?=E6=9D=A1=E8=B7=AF=E7=94=B1=E7=9A=84=E5=90=8E=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测发现:入口端口上若没有匹配 server_name 的请求,nginx 会交给该端口排序 第一的 server 块,于是一个打错的域名会访问到别的服务(若第一条恰好是开放 路由,等于把该服务暴露在错误域名下)。现在为 HTTP/HTTPS 各生成一个 default_server 返回 404,并在单测中断言其存在。 --- admin-server/gateway.go | 16 ++++++++++++---- admin-server/gateway_test.go | 4 ++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/admin-server/gateway.go b/admin-server/gateway.go index ac32d37..5cde081 100644 --- a/admin-server/gateway.go +++ b/admin-server/gateway.go @@ -162,13 +162,18 @@ func RenderGatewayConf(cfg *GatewayConfig) (string, error) { b.WriteString("# 由 HomeDash 后台生成,请勿手改:文件每次应用都会被整体覆盖。\n") b.WriteString("# 源: " + gatewayFile + "\n\n") + port := cfg.ListenPort + if port == 0 { + port = 8081 + } + // 兜底 server:没有匹配到任何 server_name 的请求必须当场拒绝。 + // 不加这一段,nginx 会把未知域名交给该端口上排序第一的 server 块—— + // 也就是"打错域名会访问到别的服务"。404 而不是 444,便于排查。 + fmt.Fprintf(&b, "server {\n listen %d default_server;\n server_name _;\n return 404 \"unknown host\\n\";\n}\n\n", port) + for _, r := range routes { host := strings.TrimSpace(r.Host) up := strings.TrimSpace(r.Upstream) - port := cfg.ListenPort - if port == 0 { - port = 8081 - } fmt.Fprintf(&b, "server {\n listen %d;\n server_name %s;\n", port, host) if r.MaxBodyMB > 0 { fmt.Fprintf(&b, " client_max_body_size %dm;\n", r.MaxBodyMB) @@ -210,6 +215,9 @@ func RenderGatewayConf(cfg *GatewayConfig) (string, error) { if tlsPort == 0 { tlsPort = 8443 } + fmt.Fprintf(&b, "server {\n listen %d ssl default_server;\n server_name _;\n", tlsPort) + fmt.Fprintf(&b, " ssl_certificate %s;\n ssl_certificate_key %s;\n", nginxQuote(cfg.CertFile), nginxQuote(cfg.KeyFile)) + b.WriteString(" ssl_protocols TLSv1.2 TLSv1.3;\n return 404 \"unknown host\\n\";\n}\n\n") for _, r := range routes { host := strings.TrimSpace(r.Host) fmt.Fprintf(&b, "server {\n listen %d ssl;\n server_name %s;\n", tlsPort, host) diff --git a/admin-server/gateway_test.go b/admin-server/gateway_test.go index cb8af70..6b4c06e 100644 --- a/admin-server/gateway_test.go +++ b/admin-server/gateway_test.go @@ -40,6 +40,10 @@ func TestRenderGatewayConfAuthPerRoute(t *testing.T) { if contains(open, "auth_request") { t.Fatalf("未受保护的域名不应有 auth_request:\n%s", open) } + // 兜底 server:未知域名必须被拒绝,而不是落进某条路由 + if !contains(out, "default_server") || !contains(out, "return 404") { + t.Fatalf("缺少未知域名兜底 server:\n%s", out) + } if contains(open, "client_max_body_size") { t.Fatalf("未设置上限时不应生成 client_max_body_size:\n%s", open) }