diff --git a/config/config.go b/config/config.go index 383b1194..87b9e11c 100644 --- a/config/config.go +++ b/config/config.go @@ -9,6 +9,8 @@ import ( "net" "net/netip" "net/url" + "os" + "regexp" "runtime" "strings" "time" @@ -16,6 +18,7 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" dns "github.com/sagernet/sing-dns" + "github.com/sagernet/sing/common/auth" ) const ( @@ -39,6 +42,29 @@ const ( InboundDNSTag = "dns-in" ) +func ReplaceEnvVariables(input string) string { + re := regexp.MustCompile(`\$\{(\w+)\}`) + return re.ReplaceAllStringFunc(input, func(m string) string { + varName := m[2 : len(m)-1] + return os.Getenv(varName) + }) +} + +func GetUsers(opt *HiddifyOptions) []auth.User { + var newUsers []auth.User + for _, user := range opt.InboundOptions.Users { + newUsername := ReplaceEnvVariables(user.Username) + newPassword := ReplaceEnvVariables(user.Password) + if newUsername != "" && newPassword != "" { + newUsers = append(newUsers, auth.User{ + Username: newUsername, + Password: newPassword, + }) + } + } + return newUsers +} + var OutboundMainProxyTag = OutboundSelectTag func BuildConfigJson(configOpt HiddifyOptions, input option.Options) (string, error) { @@ -269,15 +295,17 @@ func setClashAPI(options *option.Options, opt *HiddifyOptions) { if opt.EnableClashApi { if opt.ClashApiSecret == "" { opt.ClashApiSecret = generateRandomString(16) + } else { + opt.ClashApiSecret = ReplaceEnvVariables(opt.ClashApiSecret) } options.Experimental = &option.ExperimentalOptions{ ClashAPI: &option.ClashAPIOptions{ ExternalController: fmt.Sprintf("%s:%d", "127.0.0.1", opt.ClashApiPort), Secret: opt.ClashApiSecret, + ExternalUI: ReplaceEnvVariables(opt.ClashWebPath), }, - CacheFile: &option.CacheFileOptions{ - Enabled: true, + Enabled: false, Path: "clash.db", }, } @@ -365,6 +393,7 @@ func setInbound(options *option.Options, opt *HiddifyOptions) { DomainStrategy: inboundDomainStrategy, }, }, + Users: GetUsers(opt), SetSystemProxy: opt.SetSystemProxy, }, }, @@ -594,7 +623,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { Tag: "geosite-ads", Format: C.RuleSetFormatBinary, RemoteOptions: option.RemoteRuleSet{ - URL: "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geosite-category-ads-all.srs", + URL: opt.GeositeConfigOptions.GeositeAds, UpdateInterval: option.Duration(5 * time.Hour * 24), }, }) @@ -603,7 +632,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { Tag: "geosite-malware", Format: C.RuleSetFormatBinary, RemoteOptions: option.RemoteRuleSet{ - URL: "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geosite-malware.srs", + URL: opt.GeositeConfigOptions.GeositeMalware, UpdateInterval: option.Duration(5 * time.Hour * 24), }, }) @@ -612,7 +641,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { Tag: "geosite-phishing", Format: C.RuleSetFormatBinary, RemoteOptions: option.RemoteRuleSet{ - URL: "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geosite-phishing.srs", + URL: opt.GeositeConfigOptions.GeositePhishing, UpdateInterval: option.Duration(5 * time.Hour * 24), }, }) @@ -621,7 +650,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { Tag: "geosite-cryptominers", Format: C.RuleSetFormatBinary, RemoteOptions: option.RemoteRuleSet{ - URL: "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geosite-cryptominers.srs", + URL: opt.GeositeConfigOptions.GeositeCryptominers, UpdateInterval: option.Duration(5 * time.Hour * 24), }, }) @@ -630,7 +659,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { Tag: "geoip-phishing", Format: C.RuleSetFormatBinary, RemoteOptions: option.RemoteRuleSet{ - URL: "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geoip-phishing.srs", + URL: opt.GeositeConfigOptions.GeoipPhishing, UpdateInterval: option.Duration(5 * time.Hour * 24), }, }) @@ -639,7 +668,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { Tag: "geoip-malware", Format: C.RuleSetFormatBinary, RemoteOptions: option.RemoteRuleSet{ - URL: "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geoip-malware.srs", + URL: opt.GeositeConfigOptions.GeoipMalware, UpdateInterval: option.Duration(5 * time.Hour * 24), }, }) @@ -672,6 +701,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { }) } + opt.Region = ReplaceEnvVariables(opt.Region) if opt.Region != "other" { dnsRules = append(dnsRules, option.DefaultDNSRule{ DomainSuffix: []string{"." + opt.Region}, @@ -697,7 +727,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { Tag: "geoip-" + opt.Region, Format: C.RuleSetFormatBinary, RemoteOptions: option.RemoteRuleSet{ - URL: "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/country/geoip-" + opt.Region + ".srs", + URL: ReplaceEnvVariables(opt.GeositeConfigOptions.GeoipRegion), UpdateInterval: option.Duration(5 * time.Hour * 24), }, }) @@ -706,7 +736,7 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { Tag: "geosite-" + opt.Region, Format: C.RuleSetFormatBinary, RemoteOptions: option.RemoteRuleSet{ - URL: "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/country/geosite-" + opt.Region + ".srs", + URL: ReplaceEnvVariables(opt.GeositeConfigOptions.GeositeRegion), UpdateInterval: option.Duration(5 * time.Hour * 24), }, }) diff --git a/config/hiddify_option.go b/config/hiddify_option.go index 5b13242e..af1c828d 100644 --- a/config/hiddify_option.go +++ b/config/hiddify_option.go @@ -3,6 +3,7 @@ package config import ( "github.com/sagernet/sing-box/option" dns "github.com/sagernet/sing-dns" + "github.com/sagernet/sing/common/auth" ) type HiddifyOptions struct { @@ -11,6 +12,7 @@ type HiddifyOptions struct { LogFile string `json:"log-file"` EnableClashApi bool `json:"enable-clash-api"` ClashApiPort uint16 `json:"clash-api-port"` + ClashWebPath string `json:"clash-web-path"` ClashApiSecret string `json:"web-secret"` Region string `json:"region"` BlockAds bool `json:"block-ads"` @@ -26,6 +28,19 @@ type HiddifyOptions struct { InboundOptions URLTestOptions RouteOptions + GeositeConfigOptions +} + +// Move the download link to the configuration file +type GeositeConfigOptions struct { + GeositeAds string `json:"geosite-ads"` + GeositeMalware string `json:"geosite-malware"` + GeositePhishing string `json:"geosite-phishing"` + GeositeCryptominers string `json:"geosite-cryptominers"` + GeoipPhishing string `json:"geoip-phishing"` + GeoipMalware string `json:"geoip-malware"` + GeoipRegion string `json:"geoip-region"` + GeositeRegion string `json:"geosite-region"` } type DNSOptions struct { @@ -39,15 +54,16 @@ type DNSOptions struct { } type InboundOptions struct { - EnableTun bool `json:"enable-tun"` - EnableTunService bool `json:"enable-tun-service"` - SetSystemProxy bool `json:"set-system-proxy"` - MixedPort uint16 `json:"mixed-port"` - TProxyPort uint16 `json:"tproxy-port"` - LocalDnsPort uint16 `json:"local-dns-port"` - MTU uint32 `json:"mtu"` - StrictRoute bool `json:"strict-route"` - TUNStack string `json:"tun-implementation"` + EnableTun bool `json:"enable-tun"` + EnableTunService bool `json:"enable-tun-service"` + SetSystemProxy bool `json:"set-system-proxy"` + MixedPort uint16 `json:"mixed-port"` + TProxyPort uint16 `json:"tproxy-port"` + LocalDnsPort uint16 `json:"local-dns-port"` + MTU uint32 `json:"mtu"` + StrictRoute bool `json:"strict-route"` + TUNStack string `json:"tun-implementation"` + Users []auth.User `json:"users,omitempty"` } type URLTestOptions struct { diff --git a/v2/standalone.go b/v2/standalone.go index 173c9eef..d0eaae7f 100644 --- a/v2/standalone.go +++ b/v2/standalone.go @@ -167,7 +167,7 @@ func buildConfig(configContent string, options config.HiddifyOptions) (string, e } finalconfig.Log.Output = "" - finalconfig.Experimental.ClashAPI.ExternalUI = "webui" + // finalconfig.Experimental.ClashAPI.ExternalUI = "/etc/s6-overlay/s6-rc.d/hiddify/webui" if options.AllowConnectionFromLAN { finalconfig.Experimental.ClashAPI.ExternalController = "0.0.0.0:6756" } else {