fix(gateway): 未知域名必须被兜底拒绝,不能落进某条路由的后端

实测发现:入口端口上若没有匹配 server_name 的请求,nginx 会交给该端口排序
第一的 server 块,于是一个打错的域名会访问到别的服务(若第一条恰好是开放
路由,等于把该服务暴露在错误域名下)。现在为 HTTP/HTTPS 各生成一个
default_server 返回 404,并在单测中断言其存在。
This commit is contained in:
HomeDash Bot
2026-09-11 20:34:20 +08:00
parent 507632609d
commit 5f6fca5c59
2 changed files with 16 additions and 4 deletions

View File

@ -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)

View File

@ -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)
}