[修复] 更新代理配置以支持 SSL 服务器名称和主机头覆盖

This commit is contained in:
ryan
2026-03-16 12:39:34 +08:00
parent 4daf681eff
commit 5e2503ca50
3 changed files with 35 additions and 3 deletions
@@ -427,6 +427,12 @@ func TestPhase2CustomHeadersPreviewAndDiffLifecycle(t *testing.T) {
if !strings.Contains(renderedConfig, `proxy_set_header Host "preview-upstream.internal";`) {
t.Fatalf("expected preview endpoint to return overridden host header, got %s", renderedConfig)
}
if !strings.Contains(renderedConfig, "proxy_ssl_server_name on;") {
t.Fatalf("expected preview endpoint to enable proxy ssl server name, got %s", renderedConfig)
}
if !strings.Contains(renderedConfig, `proxy_ssl_name "preview-upstream.internal";`) {
t.Fatalf("expected preview endpoint to return proxy ssl name, got %s", renderedConfig)
}
diffResp := performJSONRequest(t, engine, token, http.MethodGet, "/api/config-versions/diff", nil)
var diff map[string]any
+23 -3
View File
@@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net/url"
"openflare/common"
"openflare/model"
"sort"
@@ -749,7 +750,7 @@ func nextVersionNumber(now time.Time) (string, error) {
}
func renderHTTPProxyServer(domain string, originURL string, originHost string, customHeaders []ProxyRouteCustomHeaderInput) string {
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s\n location / {\n%s proxy_pass %s;\n }\n}\n\n", domain, renderExactHostGuard(domain), renderProxyHeaderBlock(originHost, customHeaders), originURL)
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s\n location / {\n%s proxy_pass %s;\n }\n}\n\n", domain, renderExactHostGuard(domain), renderProxyHeaderBlock(originURL, originHost, customHeaders), originURL)
}
func renderHTTPRedirectServer(domain string) string {
@@ -759,20 +760,24 @@ func renderHTTPRedirectServer(domain string) string {
func renderHTTPSServer(domain string, originURL string, originHost string, certificateID uint, customHeaders []ProxyRouteCustomHeaderInput) string {
certPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateCertFileName(certificateID))
keyPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateKeyFileName(certificateID))
return fmt.Sprintf("server {\n listen 443 ssl;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s\n location / {\n%s proxy_pass %s;\n }\n}\n\n", domain, certPath, keyPath, renderExactHostGuard(domain), renderProxyHeaderBlock(originHost, customHeaders), originURL)
return fmt.Sprintf("server {\n listen 443 ssl;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s\n location / {\n%s proxy_pass %s;\n }\n}\n\n", domain, certPath, keyPath, renderExactHostGuard(domain), renderProxyHeaderBlock(originURL, originHost, customHeaders), originURL)
}
func renderExactHostGuard(domain string) string {
return fmt.Sprintf(" if ($host != %q) {\n return 404;\n }\n", domain)
}
func renderProxyHeaderBlock(originHost string, customHeaders []ProxyRouteCustomHeaderInput) string {
func renderProxyHeaderBlock(originURL string, originHost string, customHeaders []ProxyRouteCustomHeaderInput) string {
var builder strings.Builder
if strings.TrimSpace(originHost) != "" {
builder.WriteString(fmt.Sprintf(" proxy_set_header Host %s;\n", quoteNginxHeaderValue(originHost)))
} else {
builder.WriteString(" proxy_set_header Host $host;\n")
}
if upstreamServerName := resolveUpstreamServerName(originURL, originHost); upstreamServerName != "" {
builder.WriteString(" proxy_ssl_server_name on;\n")
builder.WriteString(fmt.Sprintf(" proxy_ssl_name %s;\n", quoteNginxHeaderValue(upstreamServerName)))
}
builder.WriteString(" proxy_set_header X-Real-IP $remote_addr;\n")
builder.WriteString(" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n")
builder.WriteString(" proxy_set_header X-Forwarded-Proto $scheme;\n")
@@ -790,6 +795,21 @@ func renderProxyHeaderBlock(originHost string, customHeaders []ProxyRouteCustomH
return builder.String()
}
func resolveUpstreamServerName(originURL string, originHost string) string {
parsed, err := url.Parse(originURL)
if err != nil || !strings.EqualFold(parsed.Scheme, "https") {
return ""
}
if strings.TrimSpace(originHost) != "" {
parsedHost, err := url.Parse("//" + originHost)
if err == nil && parsedHost.Hostname() != "" {
return parsedHost.Hostname()
}
return originHost
}
return parsed.Hostname()
}
func quoteNginxHeaderValue(value string) string {
escaped := strings.ReplaceAll(value, `\`, `\\`)
escaped = strings.ReplaceAll(escaped, `"`, `\"`)
@@ -160,6 +160,12 @@ func TestPublishConfigVersionOverridesOriginHostHeader(t *testing.T) {
if !strings.Contains(result.Version.RenderedConfig, `proxy_set_header Host "git.arctel.net";`) {
t.Fatal("expected rendered config to override host header for origin routing")
}
if !strings.Contains(result.Version.RenderedConfig, "proxy_ssl_server_name on;") {
t.Fatal("expected rendered config to enable proxy ssl server name for https origin")
}
if !strings.Contains(result.Version.RenderedConfig, `proxy_ssl_name "git.arctel.net";`) {
t.Fatal("expected rendered config to set proxy ssl name from origin host override")
}
if !strings.Contains(result.Version.SnapshotJSON, `"origin_host":"git.arctel.net"`) {
t.Fatal("expected snapshot to include origin_host override")
}