fix(gateway): TLS 段的 http2 必须写成 listen 参数

容器的 nginx 是 1.22,独立的 `http2 on;` 会报 unknown directive
(该指令 1.25.1 才引入;原 portal-nginx 用 nginx:latest 所以没暴露)。
改为 `listen PORT ssl http2;`,1.22 与 1.25+ 都可用,并加单测锁住。

本轮由旁路端口 TLS 验证发现;apply 的校验-保留机制正确拦下了这次坏配置。
This commit is contained in:
HomeDash Bot
2026-09-11 22:09:57 +08:00
parent 53beff646a
commit 1844586feb
2 changed files with 26 additions and 3 deletions

View File

@ -169,7 +169,7 @@ func nginxQuote(s string) string {
func writeTLS(b *strings.Builder, cfg *GatewayConfig) {
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 http2 on;\n")
b.WriteString(" ssl_protocols TLSv1.2 TLSv1.3;\n")
}
func writeListeners(b *strings.Builder, cfg *GatewayConfig, defaultServer bool) {
@ -178,9 +178,11 @@ func writeListeners(b *strings.Builder, cfg *GatewayConfig, defaultServer bool)
suffix = " default_server"
}
if cfg.ListenHTTPS {
fmt.Fprintf(b, " listen %d ssl%s;\n", cfg.ListenPort, suffix)
// 注意:http2 只能作为 listen 的参数写。容器里是 nginx 1.22,
// 独立的 `http2 on;` 会直接报 unknown directive(本轮实测踩到)。
fmt.Fprintf(b, " listen %d ssl http2%s;\n", cfg.ListenPort, suffix)
if cfg.ListenTLSPort > 0 && cfg.ListenTLSPort != cfg.ListenPort {
fmt.Fprintf(b, " listen %d ssl%s;\n", cfg.ListenTLSPort, suffix)
fmt.Fprintf(b, " listen %d ssl http2%s;\n", cfg.ListenTLSPort, suffix)
}
return
}

View File

@ -314,3 +314,24 @@ func TestRenderGatewayConfAuthKind(t *testing.T) {
t.Fatalf("生成了空的 proxy_pass:\n%s", out)
}
}
// TLS 段不得使用 nginx 1.22 不认识的 `http2 on;`,必须写成 listen 参数。
func TestRenderGatewayConfTLSHttp2Compatible(t *testing.T) {
out, err := RenderGatewayConf(&GatewayConfig{
ListenHTTPS: true, ListenPort: 18443, ListenTLSPort: 18443,
CertFile: "/c/fullchain.pem", KeyFile: "/c/privkey.pem",
Routes: []Route{{Host: "a.com", Upstream: "http://a"}},
})
if err != nil {
t.Fatalf("渲染失败: %v", err)
}
if contains(out, "http2 on;") {
t.Fatalf("不得输出 `http2 on;`(nginx 1.22 不支持):\n%s", out)
}
if !contains(out, "listen 18443 ssl http2;") {
t.Fatalf("TLS 监听应带 http2 参数:\n%s", out)
}
if !contains(out, "ssl_certificate '/c/fullchain.pem';") {
t.Fatalf("证书路径未写入")
}
}