From 57ff0a693d6ed59146d80f287d680f91cc318759 Mon Sep 17 00:00:00 2001 From: Artem Zyryanov Date: Fri, 20 Mar 2026 22:15:54 +0500 Subject: [PATCH] Add custom auto-update urls --- internal/cli/run_proxy.go | 2 ++ internal/config/config.go | 2 ++ internal/config/parse.go | 2 ++ internal/config/type_url.go | 53 +++++++++++++++++++++++++++++++++++++ mtglib/proxy.go | 13 +++++++-- mtglib/proxy_opts.go | 10 +++++++ 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 internal/config/type_url.go diff --git a/internal/cli/run_proxy.go b/internal/cli/run_proxy.go index 9453edaa3..841856ebb 100644 --- a/internal/cli/run_proxy.go +++ b/internal/cli/run_proxy.go @@ -258,6 +258,8 @@ func runProxy(conf *config.Config, version string) error { //nolint: funlen DomainFrontingProxyProtocol: conf.GetDomainFrontingProxyProtocol(false), PreferIP: conf.PreferIP.Get(mtglib.DefaultPreferIP), AutoUpdate: conf.AutoUpdate.Get(false), + AutoUpdateURLv4: conf.AutoUpdateURLv4.String(), + AutoUpdateURLv6: conf.AutoUpdateURLv6.String(), AllowFallbackOnUnknownDC: conf.AllowFallbackOnUnknownDC.Get(false), TolerateTimeSkewness: conf.TolerateTimeSkewness.Value, diff --git a/internal/config/config.go b/internal/config/config.go index 9ced83223..73d7d3311 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -30,6 +30,8 @@ type Config struct { ProxyProtocolListener TypeBool `json:"proxyProtocolListener"` PreferIP TypePreferIP `json:"preferIp"` AutoUpdate TypeBool `json:"autoUpdate"` + AutoUpdateURLv4 TypeURL `json:"autoUpdateURLv4"` + AutoUpdateURLv6 TypeURL `json:"autoUpdateURLv6"` DomainFrontingPort TypePort `json:"domainFrontingPort"` DomainFrontingIP TypeIP `json:"domainFrontingIp"` DomainFrontingProxyProtocol TypeBool `json:"domainFrontingProxyProtocol"` diff --git a/internal/config/parse.go b/internal/config/parse.go index 81a50f312..20af209ed 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -16,6 +16,8 @@ type tomlConfig struct { ProxyProtocolListener bool `toml:"proxy-protocol-listener" json:"proxyProtocolListener"` PreferIP string `toml:"prefer-ip" json:"preferIp,omitempty"` AutoUpdate bool `toml:"auto-update" json:"autoUpdate,omitempty"` + AutoUpdateURLv4 string `toml:"auto-update-url-v4" json:"autoUpdateURLv4,omitempty"` + AutoUpdateURLv6 string `toml:"auto-update-url-v6" json:"autoUpdateURLv6,omitempty"` DomainFrontingPort uint `toml:"domain-fronting-port" json:"domainFrontingPort,omitempty"` DomainFrontingIP string `toml:"domain-fronting-ip" json:"domainFrontingIp,omitempty"` DomainFrontingProxyProtocol bool `toml:"domain-fronting-proxy-protocol" json:"domainFrontingProxyProtocol,omitempty"` diff --git a/internal/config/type_url.go b/internal/config/type_url.go new file mode 100644 index 000000000..a90e66cf1 --- /dev/null +++ b/internal/config/type_url.go @@ -0,0 +1,53 @@ +package config + +import ( + "fmt" + "net/url" +) + +type TypeURL struct { + Value *url.URL +} + +func (t *TypeURL) Set(value string) error { + parsedURL, err := url.Parse(value) + if err != nil { + return fmt.Errorf("value is not correct URL (%s): %w", value, err) + } + + if parsedURL.Host == "" { + return fmt.Errorf("url has to have a schema: %s", value) + } + + if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { + return fmt.Errorf("unsupported schema: %s", parsedURL.Scheme) + } + + t.Value = parsedURL + + return nil +} + +func (t *TypeURL) Get(defaultValue *url.URL) *url.URL { + if t.Value == nil { + return defaultValue + } + + return t.Value +} + +func (t *TypeURL) UnmarshalText(data []byte) error { + return t.Set(string(data)) +} + +func (t TypeURL) MarshalText() ([]byte, error) { + return []byte(t.String()), nil +} + +func (t TypeURL) String() string { + if t.Value == nil { + return "" + } + + return t.Value.String() +} diff --git a/mtglib/proxy.go b/mtglib/proxy.go index 0e66e7c95..db10e2128 100644 --- a/mtglib/proxy.go +++ b/mtglib/proxy.go @@ -361,8 +361,17 @@ func NewProxy(opts ProxyOpts) (*Proxy, error) { proxy.doppelGanger.Run() if opts.AutoUpdate { - proxy.configUpdater.Run(ctx, dc.PublicConfigUpdateURLv4, "tcp4") - proxy.configUpdater.Run(ctx, dc.PublicConfigUpdateURLv6, "tcp6") + ipv4UpdateURL := opts.AutoUpdateURLv4 + if ipv4UpdateURL == "" { + ipv4UpdateURL = dc.PublicConfigUpdateURLv4 + } + proxy.configUpdater.Run(ctx, ipv4UpdateURL, "tcp4") + + ipv6UpdateURL := opts.AutoUpdateURLv6 + if ipv6UpdateURL == "" { + ipv6UpdateURL = dc.PublicConfigUpdateURLv6 + } + proxy.configUpdater.Run(ctx, ipv6UpdateURL, "tcp6") } pool, err := ants.NewPoolWithFunc(opts.getConcurrency(), diff --git a/mtglib/proxy_opts.go b/mtglib/proxy_opts.go index cea9cad8c..c860a6964 100644 --- a/mtglib/proxy_opts.go +++ b/mtglib/proxy_opts.go @@ -91,6 +91,16 @@ type ProxyOpts struct { // This is an optional setting. AutoUpdate bool + // AutoUpdate URL to update Telegram IPv4 proxy list + // + // This is an optional setting. + AutoUpdateURLv4 string + + // AutoUpdate URL to update Telegram IPv6 proxy list + // + // This is an optional setting. + AutoUpdateURLv6 string + // DomainFrontingPort is a port we use to connect to a fronting domain. // // This is required because secret does not specify a port. It specifies a