From ee35b61dedb010d2116cb0c351bde2d0fe6d7c76 Mon Sep 17 00:00:00 2001 From: Magnus Root Date: Tue, 9 Jun 2026 17:34:53 +0300 Subject: [PATCH] Fix --- nginx.go | 122 ++++++++++++++++++++++++++++++++++++++++++++++--------- types.go | 3 +- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/nginx.go b/nginx.go index cc8c636..bce17f9 100755 --- a/nginx.go +++ b/nginx.go @@ -54,6 +54,21 @@ func generateAngieConfigsWithoutReload(config Config, clientTitle string, client } } + // Если есть ресурсы с x_sid_check = true — генерируем map блоки + hasSidCheck := false + for _, res := range resources { + if res.AppsSettings.XSidCheck { + hasSidCheck = true + break + } + } + if hasSidCheck { + if err := writeAngieXSidMap(f, resources, resourcePortMap); err != nil { + os.Remove(tmpFile) + return false, fmt.Errorf("ошибка генерации x_sid map: %w", err) + } + } + f.Close() newHash, err := getFileHash(tmpFile) @@ -106,6 +121,57 @@ func generateAngieConfigs(config Config, clientTitle string, clientInfo ClientIn return nil } +// writeAngieXSidMap генерирует map блок для маршрутизации по $http_x_sid +// Используется когда x_sid_check = true в apps_settings хотя бы для одного ресурса +func writeAngieXSidMap(f *os.File, resources []ResourceData, resourcePortMap map[int][]PortMapping) error { + // Собираем уникальные порты только для ресурсов с x_sid_check = true + httpsPortSet := make(map[int]bool) + httpPortSet := make(map[int]bool) + for _, res := range resources { + if !res.AppsSettings.XSidCheck { + continue + } + for _, p := range getInputHTTPSPorts(res.AppsSettings) { + httpsPortSet[p] = true + } + for _, p := range getInputHTTPPorts(res.AppsSettings) { + httpPortSet[p] = true + } + } + + // Map для HTTPS: $http_x_sid → имя upstream + for port := range httpsPortSet { + f.WriteString(fmt.Sprintf("\n# x_sid_check: маршрутизация по X-SID для HTTPS порта %d\n", port)) + f.WriteString(fmt.Sprintf("map $http_x_sid $x_sid_upstream_https_%d {\n", port)) + f.WriteString(" default \"\";\n") + for _, res := range resources { + if !res.AppsSettings.XSidCheck { + continue + } + upstreamName := fmt.Sprintf("secure%d_%d_%s", res.L7ResourceID, port, res.ServerName) + f.WriteString(fmt.Sprintf(" \"%d\" \"%s\";\n", res.L7ResourceID, upstreamName)) + } + f.WriteString("}\n") + } + + // Map для HTTP: $http_x_sid → имя upstream + for port := range httpPortSet { + f.WriteString(fmt.Sprintf("\n# x_sid_check: маршрутизация по X-SID для HTTP порта %d\n", port)) + f.WriteString(fmt.Sprintf("map $http_x_sid $x_sid_upstream_http_%d {\n", port)) + f.WriteString(" default \"\";\n") + for _, res := range resources { + if !res.AppsSettings.XSidCheck { + continue + } + upstreamName := fmt.Sprintf("unsecure%d_%d_%s", res.L7ResourceID, port, res.ServerName) + f.WriteString(fmt.Sprintf(" \"%d\" \"%s\";\n", res.L7ResourceID, upstreamName)) + } + f.WriteString("}\n") + } + + return nil +} + // writeAngieResourceConfig записывает конфигурацию для одного ресурса в Angie func writeAngieResourceConfig(f *os.File, config Config, clientInfo ClientInfo, res ResourceData, containerPorts []PortMapping, debug bool) error { allDomains := []string{res.ServerName} @@ -267,8 +333,12 @@ func writeAngieResourceConfig(f *os.File, config Config, clientInfo ClientInfo, f.WriteString("server {\n") f.WriteString(fmt.Sprintf(" listen %d;\n", httpPort)) - f.WriteString(fmt.Sprintf(" server_name %s;\n\n", strings.Join(defaultDomains, " "))) - f.WriteString(fmt.Sprintf(" access_log /var/log/angie/%d_%s_access.log waf;\n", res.L7ResourceID, res.ServerName)) + if res.AppsSettings.XSidCheck { + f.WriteString(" server_name _;\n\n") + } else { + f.WriteString(fmt.Sprintf(" server_name %s;\n\n", strings.Join(defaultDomains, " "))) + } + f.WriteString(fmt.Sprintf(" access_log /var/log/angie/%d_%s_access.log waf buffer=32m flush=5s;\n", res.L7ResourceID, res.ServerName)) f.WriteString(fmt.Sprintf(" error_log /var/log/angie/%d_%s_error.log error;\n\n", res.L7ResourceID, res.ServerName)) writeNetworkSettings(f, config, clientInfo) @@ -281,11 +351,16 @@ func writeAngieResourceConfig(f *os.File, config Config, clientInfo ClientInfo, } f.WriteString(" location / {\n") - if res.AppsSettings.ServerAngieCustom.Valid && serverDirectivesWithoutBlocks != "" { - log.Printf(" └─ Добавление server_angie_custom для l7ResourceID %d (HTTP location /)", res.L7ResourceID) - writeIndentedLines(f, serverDirectivesWithoutBlocks) + if res.AppsSettings.XSidCheck { + f.WriteString(fmt.Sprintf(" if ($x_sid_upstream_http_%d = \"\") { return 444; }\n", httpPort)) + f.WriteString(fmt.Sprintf(" proxy_pass http://$x_sid_upstream_http_%d;\n", httpPort)) + } else { + if res.AppsSettings.ServerAngieCustom.Valid && serverDirectivesWithoutBlocks != "" { + log.Printf(" └─ Добавление server_angie_custom для l7ResourceID %d (HTTP location /)", res.L7ResourceID) + writeIndentedLines(f, serverDirectivesWithoutBlocks) + } + f.WriteString(fmt.Sprintf(" proxy_pass http://%s;\n", upstreamName)) } - f.WriteString(fmt.Sprintf(" proxy_pass http://%s;\n", upstreamName)) f.WriteString(" }\n") f.WriteString("}\n\n") } else { @@ -316,8 +391,12 @@ func writeAngieResourceConfig(f *os.File, config Config, clientInfo ClientInfo, } else { f.WriteString(fmt.Sprintf(" listen %d;\n", httpsPort)) } - f.WriteString(fmt.Sprintf(" server_name %s;\n\n", strings.Join(defaultDomains, " "))) - f.WriteString(fmt.Sprintf(" access_log /var/log/angie/%d_%s_access.log waf;\n", res.L7ResourceID, res.ServerName)) + if res.AppsSettings.XSidCheck { + f.WriteString(" server_name _;\n\n") + } else { + f.WriteString(fmt.Sprintf(" server_name %s;\n\n", strings.Join(defaultDomains, " "))) + } + f.WriteString(fmt.Sprintf(" access_log /var/log/angie/%d_%s_access.log waf buffer=32m flush=5s;\n", res.L7ResourceID, res.ServerName)) f.WriteString(fmt.Sprintf(" error_log /var/log/angie/%d_%s_error.log error;\n\n", res.L7ResourceID, res.ServerName)) if sslEnabled { @@ -334,11 +413,16 @@ func writeAngieResourceConfig(f *os.File, config Config, clientInfo ClientInfo, } f.WriteString(" location / {\n") - if res.AppsSettings.ServerAngieCustom.Valid && serverDirectivesWithoutBlocks != "" { - log.Printf(" └─ Добавление server_angie_custom для l7ResourceID %d (HTTPS location /)", res.L7ResourceID) - writeIndentedLines(f, serverDirectivesWithoutBlocks) + if res.AppsSettings.XSidCheck { + f.WriteString(fmt.Sprintf(" if ($x_sid_upstream_https_%d = \"\") { return 444; }\n", httpsPort)) + f.WriteString(fmt.Sprintf(" proxy_pass http://$x_sid_upstream_https_%d;\n", httpsPort)) + } else { + if res.AppsSettings.ServerAngieCustom.Valid && serverDirectivesWithoutBlocks != "" { + log.Printf(" └─ Добавление server_angie_custom для l7ResourceID %d (HTTPS location /)", res.L7ResourceID) + writeIndentedLines(f, serverDirectivesWithoutBlocks) + } + f.WriteString(fmt.Sprintf(" proxy_pass http://%s;\n", upstreamName)) } - f.WriteString(fmt.Sprintf(" proxy_pass http://%s;\n", upstreamName)) f.WriteString(" }\n") f.WriteString("}\n\n") } else { @@ -418,7 +502,7 @@ func writeStandardServerSettings(f *os.File, customDirectives string, debug bool f.WriteString("\n") f.WriteString(" js_set $safe_host main.sanitizeHost;\n") f.WriteString(" proxy_set_header X-Real-IP $remote_addr;\n") - f.WriteString(" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n") + f.WriteString(" proxy_set_header X-Forwarded-For $remote_addr;\n") f.WriteString(" proxy_set_header Connection $proxy_connection;\n") f.WriteString(" proxy_set_header Upgrade $http_upgrade;\n") f.WriteString(" proxy_set_header Host $safe_host;\n") @@ -442,7 +526,7 @@ func writeNginxStandardSettings(f *os.File, customDirectives string, proxyNextUp f.WriteString(" proxy_http_version 1.1;\n") f.WriteString("\n") f.WriteString(" #proxy_set_header X-Real-IP $remote_addr;\n") - f.WriteString(" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n") + f.WriteString(" proxy_set_header X-Forwarded-For $remote_addr;\n") f.WriteString(" proxy_set_header Connection $proxy_connection;\n") f.WriteString(" proxy_set_header Upgrade $http_upgrade;\n") f.WriteString(" proxy_set_header Host $backend_host;\n") @@ -541,7 +625,7 @@ func generateAngieCustomServerBlock(f *os.File, config Config, clientInfo Client f.WriteString(fmt.Sprintf(" server_name %s;\n\n", block.ServerName)) } - f.WriteString(fmt.Sprintf(" access_log /var/log/angie/%d_%s_port%d_access.log waf;\n", + f.WriteString(fmt.Sprintf(" access_log /var/log/angie/%d_%s_port%d_access.log waf buffer=32m flush=5s;\n", res.L7ResourceID, sanitizeServerName(block.ServerName), block.Port)) f.WriteString(fmt.Sprintf(" error_log /var/log/angie/%d_%s_port%d_error.log error;\n\n", res.L7ResourceID, sanitizeServerName(block.ServerName), block.Port)) @@ -734,7 +818,7 @@ func generateNginxResourceConfig(filepath string, config Config, res ResourceDat f.WriteString("server {\n") f.WriteString(fmt.Sprintf(" listen %d;\n", httpPort)) f.WriteString(fmt.Sprintf(" server_name %s;\n\n", strings.Join(defaultDomains, " "))) - f.WriteString(fmt.Sprintf(" access_log /var/log/nginx/%d_%s_access.log waf;\n", res.L7ResourceID, res.ServerName)) + f.WriteString(fmt.Sprintf(" access_log /var/log/nginx/%d_%s_access.log waf buffer=32m flush=5s;\n", res.L7ResourceID, res.ServerName)) f.WriteString(fmt.Sprintf(" error_log /var/log/nginx/%d_%s_error.log error;\n\n", res.L7ResourceID, res.ServerName)) f.WriteString(" set_real_ip_from 172.16.0.0/12;\n") f.WriteString(" real_ip_header X-Forwarded-For;\n") @@ -771,7 +855,7 @@ func generateNginxResourceConfig(filepath string, config Config, res ResourceDat f.WriteString("server {\n") f.WriteString(fmt.Sprintf(" listen %d;\n", httpsPort)) f.WriteString(fmt.Sprintf(" server_name %s;\n\n", strings.Join(defaultDomains, " "))) - f.WriteString(fmt.Sprintf(" access_log /var/log/nginx/%d_%s_access.log waf;\n", res.L7ResourceID, res.ServerName)) + f.WriteString(fmt.Sprintf(" access_log /var/log/nginx/%d_%s_access.log waf buffer=32m flush=5s;\n", res.L7ResourceID, res.ServerName)) f.WriteString(fmt.Sprintf(" error_log /var/log/nginx/%d_%s_error.log error;\n\n", res.L7ResourceID, res.ServerName)) f.WriteString(" proxy_ssl_server_name on;\n") f.WriteString(" proxy_ssl_name $host;\n\n") @@ -863,7 +947,7 @@ func generateCustomServerBlock(f *os.File, res ResourceData, block CustomServerB f.WriteString(fmt.Sprintf(" server_name %s;\n\n", block.ServerName)) } - f.WriteString(fmt.Sprintf(" access_log /var/log/nginx/%d_%s_port%d_access.log waf;\n", + f.WriteString(fmt.Sprintf(" access_log /var/log/nginx/%d_%s_port%d_access.log waf buffer=32m flush=5s;\n", res.L7ResourceID, sanitizeServerName(block.ServerName), block.Port)) f.WriteString(fmt.Sprintf(" error_log /var/log/nginx/%d_%s_port%d_error.log error;\n\n", res.L7ResourceID, sanitizeServerName(block.ServerName), block.Port)) @@ -896,4 +980,4 @@ func generateCustomServerBlock(f *os.File, res ResourceData, block CustomServerB f.WriteString(fmt.Sprintf(" proxy_pass %s://%s;\n", protocol, upstreamName)) f.WriteString(" }\n") f.WriteString("}\n\n") -} +} \ No newline at end of file diff --git a/types.go b/types.go index f720514..f0e3544 100755 --- a/types.go +++ b/types.go @@ -38,6 +38,7 @@ type AppsSettings struct { FailTimeout sql.NullInt64 // Время в секундах после которого origin снова доступен (дефолт 15) BalancingMethod sql.NullString // Метод балансировки: least_conn, ip_hash, random и т.д. ProxyNextUpstreamCodes sql.NullString // HTTP-коды для proxy_next_upstream (дефолт: 500,502,503,504) + XSidCheck bool // Маршрутизация в Angie по x-sid вместо server_name (дефолт: false) CustomSWNginxSSL sql.NullString // Кастомные SSL директивы для SW nginx - полностью заменяют дефолтные если заполнено } @@ -156,4 +157,4 @@ type CustomServerBlock struct { Aliases []string Content string IsHTTPS bool -} +} \ No newline at end of file