From 9cd1a393acd2863d94212308bdcdcb0da6035509 Mon Sep 17 00:00:00 2001 From: xuans Date: Sat, 3 Oct 2026 12:22:01 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E7=AC=AC=E4=B8=80=E5=8F=B0?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=85=A5=E5=8F=A3=E4=BF=9D=E6=8A=A4=E5=85=9C?= =?UTF-8?q?=E5=BA=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当独立管理策略文件不存在时,读取 Nginx 有效配置识别受保护的管理站点,避免普通证书部署覆盖管理域名。 --- backend/internal/deployment/service.go | 76 +++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/backend/internal/deployment/service.go b/backend/internal/deployment/service.go index b182377..a00cf93 100644 --- a/backend/internal/deployment/service.go +++ b/backend/internal/deployment/service.go @@ -608,7 +608,7 @@ func checkManagementDomainConflict(ctx context.Context, client Client, domainNam return fmt.Errorf("核查服务器管理入口失败:%w", err) } if probe.ExitCode == 1 { - return nil + return checkNginxManagementDomainConflict(ctx, client, domainName) } if probe.ExitCode != 0 { return fmt.Errorf("核查服务器管理入口失败:命令退出码 %d", probe.ExitCode) @@ -635,6 +635,80 @@ func checkManagementDomainConflict(ctx context.Context, client Client, domainNam return nil } +func checkNginxManagementDomainConflict(ctx context.Context, client Client, domainName string) error { + result, err := client.Run(ctx, []string{"nginx", "-T"}) + if err != nil { + return fmt.Errorf("?? Nginx ???????%w", err) + } + if result.ExitCode != 0 { + return fmt.Errorf("?? Nginx ???????????? %d", result.ExitCode) + } + if nginxContainsManagedServer(string(result.Output), domainName) { + return ErrManagementDomainConflict + } + return nil +} + +func nginxContainsManagedServer(config, domainName string) bool { + domainName = normalizeDeploymentDomain(domainName) + if domainName == "" { + return false + } + depth := 0 + serverDepth := -1 + serverLines := make([]string, 0, 32) + for _, line := range strings.Split(config, "\n") { + trimmed := strings.TrimSpace(strings.SplitN(line, "#", 2)[0]) + if serverDepth < 0 && strings.HasPrefix(trimmed, "server") && strings.Contains(trimmed, "{") { + serverDepth = depth + serverLines = serverLines[:0] + } + if serverDepth >= 0 { + serverLines = append(serverLines, trimmed) + } + depth += strings.Count(trimmed, "{") - strings.Count(trimmed, "}") + if serverDepth >= 0 && depth <= serverDepth { + if nginxServerBlockIsManaged(serverLines, domainName) { + return true + } + serverDepth = -1 + serverLines = serverLines[:0] + } + } + return false +} + +func nginxServerBlockIsManaged(lines []string, domainName string) bool { + hasDomain := false + hasUpstream := false + hasSNI := false + hasVerify := false + for _, line := range lines { + fields := strings.Fields(line) + if len(fields) < 2 { + continue + } + for i := range fields { + fields[i] = strings.Trim(fields[i], ";{}") + } + switch fields[0] { + case "server_name": + for _, value := range fields[1:] { + if normalizeDeploymentDomain(value) == domainName { + hasDomain = true + } + } + case "proxy_pass": + hasUpstream = fields[1] == "https://127.0.0.1:8443" + case "proxy_ssl_name": + hasSNI = normalizeDeploymentDomain(fields[1]) == domainName + case "proxy_ssl_verify": + hasVerify = fields[1] == "on" + } + } + return hasDomain && hasUpstream && hasSNI && hasVerify +} + func normalizeDeploymentDomain(value string) string { return strings.ToLower(strings.TrimSuffix(strings.TrimSpace(value), ".")) }