From c2c60cf52f2534b3e82d7f41eec2239d10b9d31b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 15 Sep 2026 13:42:35 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=85=20Sync=202026-09-15=2013:42:35?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- luci-app-homeproxy/Makefile | 2 +- .../etc/homeproxy/scripts/generate_client.uc | 6 +- sing-box/Makefile | 2 +- .../001-support-remote-rule-set-path.patch | 134 ------------------ .../002-support-clash-proxy-providers.patch | 52 +++---- 5 files changed, 22 insertions(+), 174 deletions(-) delete mode 100644 sing-box/patches/001-support-remote-rule-set-path.patch diff --git a/luci-app-homeproxy/Makefile b/luci-app-homeproxy/Makefile index 941c3be24..4549d164d 100644 --- a/luci-app-homeproxy/Makefile +++ b/luci-app-homeproxy/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-homeproxy PKG_VERSION:=2.0.0 -PKG_RELEASE:=12 +PKG_RELEASE:=13 LUCI_TITLE:=Sing-box proxy management platform for OpenWrt LUCI_PKGARCH:=all diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc index 70a16948c..7a655d8c8 100755 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc @@ -1223,7 +1223,7 @@ if (!isEmpty(main_node)) { tag: 'geoip-cn', format: 'binary', url: 'https://fastly.jsdelivr.net/gh/1715173329/IPCIDR-CHINA@rule-set/cn.srs', - path: ruleset_default_path('geoip-cn', 'binary'), + initial_path: ruleset_default_path('geoip-cn', 'binary'), download_detour: 'main-out' }); push(config.route.rule_set, { @@ -1231,7 +1231,7 @@ if (!isEmpty(main_node)) { tag: 'geosite-cn', format: 'binary', url: 'https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-cn.srs', - path: ruleset_default_path('geosite-cn', 'binary'), + initial_path: ruleset_default_path('geosite-cn', 'binary'), download_detour: 'main-out' }); push(config.route.rule_set, { @@ -1239,7 +1239,7 @@ if (!isEmpty(main_node)) { tag: 'geosite-noncn', format: 'binary', url: 'https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-!cn.srs', - path: ruleset_default_path('geosite-noncn', 'binary'), + initial_path: ruleset_default_path('geosite-noncn', 'binary'), download_detour: 'main-out' }); } diff --git a/sing-box/Makefile b/sing-box/Makefile index 5de609eb1..048503038 100644 --- a/sing-box/Makefile +++ b/sing-box/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=sing-box PKG_VERSION:=1.14.1 -PKG_RELEASE:=32 +PKG_RELEASE:=33 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)? diff --git a/sing-box/patches/001-support-remote-rule-set-path.patch b/sing-box/patches/001-support-remote-rule-set-path.patch deleted file mode 100644 index 9f6068919..000000000 --- a/sing-box/patches/001-support-remote-rule-set-path.patch +++ /dev/null @@ -1,134 +0,0 @@ -diff --git a/option/rule_set.go b/option/rule_set.go -index b063422..1ce631a 100644 ---- a/option/rule_set.go -+++ b/option/rule_set.go -@@ -122,6 +122,7 @@ type LocalRuleSet struct { - - type RemoteRuleSet struct { - URL string `json:"url"` -+ Path string `json:"path,omitempty"` - DownloadDetour string `json:"download_detour,omitempty"` - UpdateInterval badoption.Duration `json:"update_interval,omitempty"` - } -diff --git a/route/rule/rule_set_remote.go b/route/rule/rule_set_remote.go -index bda6e23..8f84796 100644 ---- a/route/rule/rule_set_remote.go -+++ b/route/rule/rule_set_remote.go -@@ -7,6 +7,8 @@ import ( - "io" - "net" - "net/http" -+ "os" -+ "path/filepath" - "runtime" - "strings" - "sync" -@@ -27,6 +29,7 @@ import ( - "github.com/sagernet/sing/common/ntp" - "github.com/sagernet/sing/common/x/list" - "github.com/sagernet/sing/service" -+ "github.com/sagernet/sing/service/filemanager" - "github.com/sagernet/sing/service/pause" - - "go4.org/netipx" -@@ -94,14 +97,36 @@ func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext *adapter. - dialer = s.outbound.Default() - } - s.dialer = dialer -+ loadedFromPath := false -+ pathMissing := false -+ if s.options.RemoteOptions.Path != "" { -+ err := s.loadFromPath() -+ if err == nil { -+ loadedFromPath = true -+ } else if os.IsNotExist(err) { -+ pathMissing = true -+ s.logger.Warn("rule-set file not found: ", s.options.RemoteOptions.Path) -+ } else { -+ s.logger.Warn("restore rule-set file ", s.options.RemoteOptions.Path, ": ", err) -+ } -+ } - if s.cacheFile != nil { - if savedSet := s.cacheFile.LoadRuleSet(s.options.Tag); savedSet != nil { -- err := s.loadBytes(savedSet.Content) -- if err != nil { -- return E.Cause(err, "restore cached rule-set") -+ if !loadedFromPath && !pathMissing { -+ err := s.loadBytes(savedSet.Content) -+ if err != nil { -+ return E.Cause(err, "restore cached rule-set") -+ } -+ s.lastUpdated = savedSet.LastUpdated -+ } -+ if !pathMissing { -+ if s.lastUpdated.IsZero() { -+ s.lastUpdated = savedSet.LastUpdated -+ } -+ if s.lastEtag == "" { -+ s.lastEtag = savedSet.LastEtag -+ } - } -- s.lastUpdated = savedSet.LastUpdated -- s.lastEtag = savedSet.LastEtag - } - } - if s.lastUpdated.IsZero() { -@@ -159,6 +184,46 @@ func (s *RemoteRuleSet) UnregisterCallback(element *list.Element[adapter.RuleSet - s.callbacks.Remove(element) - } - -+func (s *RemoteRuleSet) localPath() string { -+ if s.options.RemoteOptions.Path == "" { -+ return "" -+ } -+ return filemanager.BasePath(s.ctx, s.options.RemoteOptions.Path) -+} -+ -+func (s *RemoteRuleSet) loadFromPath() error { -+ path := s.localPath() -+ if path == "" { -+ return os.ErrNotExist -+ } -+ content, err := os.ReadFile(path) -+ if err != nil { -+ return err -+ } -+ err = s.loadBytes(content) -+ if err != nil { -+ return err -+ } -+ if info, err := os.Stat(path); err == nil { -+ s.lastUpdated = info.ModTime() -+ } -+ return nil -+} -+ -+func (s *RemoteRuleSet) saveToPath(content []byte) error { -+ path := s.localPath() -+ if path == "" { -+ return nil -+ } -+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { -+ return err -+ } -+ if err := os.WriteFile(path, content, 0o644); err != nil { -+ return err -+ } -+ return filemanager.Chown(s.ctx, path) -+} -+ - func (s *RemoteRuleSet) loadBytes(content []byte) error { - var ( - ruleSet option.PlainRuleSetCompat -@@ -308,6 +373,11 @@ func (s *RemoteRuleSet) fetch(ctx context.Context, startContext *adapter.HTTPSta - s.logger.Error("save rule-set cache: ", err) - } - } -+ if s.options.RemoteOptions.Path != "" { -+ if err := s.saveToPath(content); err != nil { -+ s.logger.Error("save rule-set file: ", err) -+ } -+ } - s.logger.Info("updated rule-set ", s.options.Tag) - return nil - } diff --git a/sing-box/patches/002-support-clash-proxy-providers.patch b/sing-box/patches/002-support-clash-proxy-providers.patch index 9de3cf99a..639069b9c 100644 --- a/sing-box/patches/002-support-clash-proxy-providers.patch +++ b/sing-box/patches/002-support-clash-proxy-providers.patch @@ -337,66 +337,48 @@ index ef88ff3..1f7d14d 100644 func getProxyDelay(server *Server) func(w http.ResponseWriter, r *http.Request) { diff --git a/experimental/clashapi/server.go b/experimental/clashapi/server.go -index 950dca0..e4c1210 100644 +index b9222ad5440..d4fd9dd3db1 100644 --- a/experimental/clashapi/server.go +++ b/experimental/clashapi/server.go -@@ -60,6 +60,7 @@ type Server struct { +@@ -57,6 +57,7 @@ type Server struct { externalUI string externalUIDownloadURL string externalUIDownloadDetour string + proxyProviders []option.ClashProxyProviderOptions } - func NewServer(ctx context.Context, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) { -@@ -82,6 +83,7 @@ func NewServer(ctx context.Context, logFactory log.ObservableFactory, options op + func NewServer(ctx context.Context, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.LifecycleService, error) { +@@ -92,6 +93,7 @@ func NewServer(ctx context.Context, logFactory log.ObservableFactory, options op externalController: options.ExternalController != "", externalUIDownloadURL: options.ExternalUIDownloadURL, externalUIDownloadDetour: options.ExternalUIDownloadDetour, + proxyProviders: options.ProxyProviders, } - s.urlTestHistory = service.FromContext[adapter.URLTestHistoryStorage](ctx) - if s.urlTestHistory == nil { -@@ -122,7 +124,7 @@ func NewServer(ctx context.Context, logFactory log.ObservableFactory, options op + //goland:noinspection GoDeprecation + //nolint:staticcheck +@@ -120,7 +122,7 @@ func NewServer(ctx context.Context, logFactory log.ObservableFactory, options op r.Mount("/proxies", proxyRouter(s, s.router)) r.Mount("/rules", ruleRouter(s.router)) - r.Mount("/connections", connectionRouter(s.ctx, s.router, trafficManager)) + r.Mount("/connections", connectionRouter(s.ctx, s.network, trafficManager)) - r.Mount("/providers/proxies", proxyProviderRouter()) + r.Mount("/providers/proxies", proxyProviderRouter(s)) r.Mount("/providers/rules", ruleProviderRouter()) r.Mount("/script", scriptRouter()) r.Mount("/profile", profileRouter()) diff --git a/option/experimental.go b/option/experimental.go -index bf0df9e..50de31d 100644 +index bf144ad4452..89f303a7b26 100644 --- a/option/experimental.go +++ b/option/experimental.go -@@ -19,15 +19,16 @@ type CacheFileOptions struct { - } - - type ClashAPIOptions struct { -- ExternalController string `json:"external_controller,omitempty"` -- ExternalUI string `json:"external_ui,omitempty"` -- ExternalUIDownloadURL string `json:"external_ui_download_url,omitempty"` -- ExternalUIDownloadDetour string `json:"external_ui_download_detour,omitempty"` -- Secret string `json:"secret,omitempty"` -- DefaultMode string `json:"default_mode,omitempty"` -- ModeList []string `json:"-"` -- AccessControlAllowOrigin badoption.Listable[string] `json:"access_control_allow_origin,omitempty"` -- AccessControlAllowPrivateNetwork bool `json:"access_control_allow_private_network,omitempty"` -+ ExternalController string `json:"external_controller,omitempty"` -+ ExternalUI string `json:"external_ui,omitempty"` -+ ExternalUIDownloadURL string `json:"external_ui_download_url,omitempty"` -+ ExternalUIDownloadDetour string `json:"external_ui_download_detour,omitempty"` -+ Secret string `json:"secret,omitempty"` -+ DefaultMode string `json:"default_mode,omitempty"` +@@ -34,6 +34,7 @@ type ClashAPIOptions struct { + ExternalUIDownloadDetour string `json:"external_ui_download_detour,omitempty" reference:"outbound"` + Secret string `json:"secret,omitempty"` + DefaultMode string `json:"default_mode,omitempty"` + ProxyProviders []ClashProxyProviderOptions `json:"proxy_providers,omitempty"` -+ ModeList []string `json:"-"` -+ AccessControlAllowOrigin badoption.Listable[string] `json:"access_control_allow_origin,omitempty"` -+ AccessControlAllowPrivateNetwork bool `json:"access_control_allow_private_network,omitempty"` + AccessControlAllowOrigin badoption.Listable[string] `json:"access_control_allow_origin,omitempty"` + AccessControlAllowPrivateNetwork bool `json:"access_control_allow_private_network,omitempty"` - // Deprecated: migrated to global cache file - CacheFile string `json:"cache_file,omitempty"` -@@ -41,6 +42,23 @@ type ClashAPIOptions struct { - StoreFakeIP bool `json:"store_fakeip,omitempty"` +@@ -49,6 +50,23 @@ type ClashAPIOptions struct { + StoreFakeIP bool `json:"store_fakeip,omitempty" schema:"omit"` } +type ClashProxyProviderOptions struct {