From bddf641bf1c4c849e6fe4d4c7cd20e077ac4db74 Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 26 May 2026 09:10:08 +0800 Subject: [PATCH] =?UTF-8?q?[=E4=BC=98=E5=8C=96]=20=E6=B7=BB=E5=8A=A0=20Ope?= =?UTF-8?q?nRestyResolvers=20=E9=85=8D=E7=BD=AE=E6=94=AF=E6=8C=81=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=20DNS=20=E8=A7=A3=E6=9E=90=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openflare_agent/internal/nginx/manager.go | 1 + .../internal/nginx/manager_test.go | 1 + openflare_server/common/constants.go | 3 ++- openflare_server/controller/option.go | 8 ++++++- openflare_server/controller/option_test.go | 3 ++- openflare_server/model/option.go | 5 ---- openflare_server/service/config_version.go | 5 +++- .../components/performance-page.tsx | 24 +++++++++++++++++++ 8 files changed, 41 insertions(+), 9 deletions(-) diff --git a/openflare_agent/internal/nginx/manager.go b/openflare_agent/internal/nginx/manager.go index dbb0e155..445010a2 100644 --- a/openflare_agent/internal/nginx/manager.go +++ b/openflare_agent/internal/nginx/manager.go @@ -213,6 +213,7 @@ func (e *DockerExecutor) runContainer(ctx context.Context) error { runArgs := []string{ "run", "-d", "--name", e.ContainerName, + "--restart", "always", "-p", "80:80", "-p", "443:443", "-p", fmt.Sprintf("127.0.0.1:%d:%d", e.OpenrestyObservabilityPort, e.OpenrestyObservabilityPort), diff --git a/openflare_agent/internal/nginx/manager_test.go b/openflare_agent/internal/nginx/manager_test.go index 3a5bf367..2bd460b6 100644 --- a/openflare_agent/internal/nginx/manager_test.go +++ b/openflare_agent/internal/nginx/manager_test.go @@ -399,6 +399,7 @@ func TestDockerExecutorRunContainerMountsManagedFiles(t *testing.T) { expectedArgs := []string{ "run", "-d", "--name", "openflare-openresty", + "--restart", "always", "-p", "80:80", "-p", "443:443", "-p", "127.0.0.1:18081:18081", diff --git a/openflare_server/common/constants.go b/openflare_server/common/constants.go index a8a1ca4d..c5d82d6c 100644 --- a/openflare_server/common/constants.go +++ b/openflare_server/common/constants.go @@ -71,6 +71,7 @@ var OpenRestyClientBodyTimeout = 15 var OpenRestyClientMaxBodySize = "64m" var OpenRestyLargeClientHeaderBuffers = "4 16k" var OpenRestySendTimeout = 30 +var OpenRestyResolvers = "" var OpenRestyProxyConnectTimeout = 3 var OpenRestyProxySendTimeout = 60 var OpenRestyProxyReadTimeout = 60 @@ -127,7 +128,7 @@ http { gzip {{OpenRestyGzip}}; gzip_min_length {{OpenRestyGzipMinLength}}; gzip_comp_level {{OpenRestyGzipCompLevel}}; -{{OpenRestyCacheBlock}} include {{OpenRestyRouteConfigInclude}}; +{{OpenRestyResolverDirective}}{{OpenRestyCacheBlock}} include {{OpenRestyRouteConfigInclude}}; } ` diff --git a/openflare_server/controller/option.go b/openflare_server/controller/option.go index 13a6921b..09f0a396 100644 --- a/openflare_server/controller/option.go +++ b/openflare_server/controller/option.go @@ -133,7 +133,13 @@ func validateOpenRestyOption(key string, value string) error { return fmt.Errorf("%s 仅支持 epoll、kqueue、poll、select、rtsig、/dev/poll、eventport 或留空", key) } case "OpenRestyResolvers": - return fmt.Errorf("%s 已废弃,不再支持配置 resolver", key) + if trimmed == "" { + return nil + } + if !regexp.MustCompile(`^[a-zA-Z0-9.:\-\s]+$`).MatchString(trimmed) { + return fmt.Errorf("%s 包含非法字符,请填入有效的 IP 地址或域名,以空格分隔", key) + } + return nil case "OpenRestyEventsMultiAcceptEnabled", "OpenRestyWebsocketEnabled", "OpenRestyProxyRequestBufferingEnabled", diff --git a/openflare_server/controller/option_test.go b/openflare_server/controller/option_test.go index 7c3925ff..c5a10c8d 100644 --- a/openflare_server/controller/option_test.go +++ b/openflare_server/controller/option_test.go @@ -14,7 +14,8 @@ func TestValidateOpenRestyOption(t *testing.T) { {name: "worker processes invalid", key: "OpenRestyWorkerProcesses", value: "0", wantErr: true}, {name: "events use empty", key: "OpenRestyEventsUse", value: ""}, {name: "events use invalid", key: "OpenRestyEventsUse", value: "io_uring", wantErr: true}, - {name: "resolvers deprecated", key: "OpenRestyResolvers", value: "1.1.1.1", wantErr: true}, + {name: "resolvers valid", key: "OpenRestyResolvers", value: "1.1.1.1 8.8.8.8"}, + {name: "resolvers invalid", key: "OpenRestyResolvers", value: "1.1.1.1; 8.8.8.8", wantErr: true}, {name: "proxy buffers valid", key: "OpenRestyProxyBuffers", value: "16 16k"}, {name: "proxy buffers invalid", key: "OpenRestyProxyBuffers", value: "16x16k", wantErr: true}, {name: "cache max size valid", key: "OpenRestyCacheMaxSize", value: "2g"}, diff --git a/openflare_server/model/option.go b/openflare_server/model/option.go index 0afd9c84..18e26e0f 100644 --- a/openflare_server/model/option.go +++ b/openflare_server/model/option.go @@ -153,11 +153,6 @@ func updateOptionMap(key string, value string) { common.OptionMap = make(map[string]string) } common.OptionMap[key] = value - if key == "OpenRestyResolvers" { - delete(common.OptionMap, key) - common.OptionMapRWMutex.Unlock() - return - } if strings.HasSuffix(key, "Permission") { intValue, _ := strconv.Atoi(value) switch key { diff --git a/openflare_server/service/config_version.go b/openflare_server/service/config_version.go index fb6e4bd6..3a840c45 100644 --- a/openflare_server/service/config_version.go +++ b/openflare_server/service/config_version.go @@ -133,6 +133,7 @@ type openRestyConfigSnapshot struct { GzipEnabled bool `json:"gzip_enabled"` GzipMinLength int `json:"gzip_min_length"` GzipCompLevel int `json:"gzip_comp_level"` + Resolvers string `json:"resolvers,omitempty"` CacheEnabled bool `json:"cache_enabled"` CachePath string `json:"cache_path,omitempty"` CacheLevels string `json:"cache_levels"` @@ -766,6 +767,7 @@ func buildOpenRestyConfigSnapshot() openRestyConfigSnapshot { GzipEnabled: common.OpenRestyGzipEnabled, GzipMinLength: common.OpenRestyGzipMinLength, GzipCompLevel: common.OpenRestyGzipCompLevel, + Resolvers: common.OpenRestyResolvers, CacheEnabled: common.OpenRestyCacheEnabled, CachePath: common.OpenRestyCachePath, CacheLevels: common.OpenRestyCacheLevels, @@ -827,6 +829,7 @@ func diffOpenRestyOptionDetails(left openRestyConfigSnapshot, right openRestyCon appendIfChanged("OpenRestyGzipEnabled", fmt.Sprintf("%t", left.GzipEnabled), fmt.Sprintf("%t", right.GzipEnabled)) appendIfChanged("OpenRestyGzipMinLength", fmt.Sprintf("%d", left.GzipMinLength), fmt.Sprintf("%d", right.GzipMinLength)) appendIfChanged("OpenRestyGzipCompLevel", fmt.Sprintf("%d", left.GzipCompLevel), fmt.Sprintf("%d", right.GzipCompLevel)) + appendIfChanged("OpenRestyResolvers", left.Resolvers, right.Resolvers) appendIfChanged("OpenRestyCacheEnabled", fmt.Sprintf("%t", left.CacheEnabled), fmt.Sprintf("%t", right.CacheEnabled)) appendIfChanged("OpenRestyCachePath", left.CachePath, right.CachePath) appendIfChanged("OpenRestyCacheLevels", left.CacheLevels, right.CacheLevels) @@ -1063,7 +1066,7 @@ func renderMainConfigTemplate(templateText string, cfg openRestyConfigSnapshot) "{{OpenRestyGzip}}", onOff(cfg.GzipEnabled), "{{OpenRestyGzipMinLength}}", fmt.Sprintf("%d", cfg.GzipMinLength), "{{OpenRestyGzipCompLevel}}", fmt.Sprintf("%d", cfg.GzipCompLevel), - "{{OpenRestyResolverDirective}}", "", + "{{OpenRestyResolverDirective}}", renderTemplateDirective(cfg.Resolvers != "", fmt.Sprintf("resolver %s;", cfg.Resolvers)), "{{OpenRestyCacheBlock}}", renderOpenRestyCacheTemplateBlock(cfg), "{{OpenRestyRouteConfigInclude}}", nginxRouteConfigPlaceholder, ) diff --git a/openflare_server/web/features/performance/components/performance-page.tsx b/openflare_server/web/features/performance/components/performance-page.tsx index 2abb7ee0..44e4c73e 100644 --- a/openflare_server/web/features/performance/components/performance-page.tsx +++ b/openflare_server/web/features/performance/components/performance-page.tsx @@ -65,6 +65,7 @@ const defaultPerformanceFields = { OpenRestyCacheLockTimeout: '5s', OpenRestyCacheUseStale: 'error timeout updating http_500 http_502 http_503 http_504', + OpenRestyResolvers: '', }; const performanceFieldTooltips: Record = { @@ -114,6 +115,8 @@ const performanceFieldTooltips: Record = { proxy_cache_lock_timeout: '等待缓存锁的最长时间,例如 5s。', proxy_cache_use_stale: '上游异常时允许返回旧缓存的条件列表,例如 error、timeout、http_500。', + resolvers: + '自定义 DNS 解析器,留空表示不配置。若配置,当上游源站需要动态解析且 DNS 服务器失效时,能防止容器异常挂掉。例如:1.1.1.1 8.8.8.8', }; type PerformanceTab = 'settings' | 'editor'; @@ -256,6 +259,7 @@ export function PerformancePage() { OpenRestyCacheUseStale: optionMap.OpenRestyCacheUseStale ?? 'error timeout updating http_500 http_502 http_503 http_504', + OpenRestyResolvers: optionMap.OpenRestyResolvers ?? '', }); setTemplateContent(optionMap.OpenRestyMainConfigTemplate ?? ''); }, [optionsQuery.data]); @@ -333,6 +337,10 @@ export function PerformancePage() { 'OpenRestyWorkerProcesses', performanceFields.OpenRestyWorkerProcesses.trim(), ], + [ + 'OpenRestyResolvers', + performanceFields.OpenRestyResolvers.trim(), + ], [ 'OpenRestyWorkerConnections', performanceFields.OpenRestyWorkerConnections.trim(), @@ -689,6 +697,22 @@ export function PerformancePage() { } >
+ + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyResolvers: event.target.value, + })) + } + placeholder="留空表示不配置" + /> +