diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index a0f91cd..a1d0be7 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -31,8 +31,11 @@ jobs: with: submodules: recursive - - uses: jdx/mise-action@v3 - name: Install mise + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod - - name: Run tests - run: mise tasks run vuln + - name: Check for vulnerabilities + run: | + go run golang.org/x/vuln/cmd/govulncheck@latest ./... diff --git a/example.config.toml b/example.config.toml index 01ab257..0e40c3f 100644 --- a/example.config.toml +++ b/example.config.toml @@ -48,6 +48,11 @@ concurrency = 8192 # Only ipv4 connectivity is used prefer-ip = "prefer-ipv6" +# If this setting is set, then mtg will try to get proxy updates from Telegram +# Usually this is completely fine to have it disabled, because mtg has a list +# of some core proxies hardcoded. +auto-update = false + # FakeTLS uses domain fronting protection. So it needs to know a port to # access. # diff --git a/go.mod b/go.mod index e75cb4c..b78ee66 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/panjf2000/ants/v2 v2.11.5 github.com/prometheus/client_golang v1.23.2 github.com/prometheus/common v0.67.5 // indirect - github.com/prometheus/procfs v0.19.2 // indirect + github.com/prometheus/procfs v0.20.0 // indirect github.com/rs/zerolog v1.34.0 github.com/smira/go-statsd v1.3.4 github.com/stretchr/objx v0.5.2 // indirect diff --git a/go.sum b/go.sum index 13d71bb..6c41391 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= -github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= -github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= +github.com/prometheus/procfs v0.20.0 h1:AA7aCvjxwAquZAlonN7888f2u4IN8WVeFgBi4k82M4Q= +github.com/prometheus/procfs v0.20.0/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= diff --git a/internal/cli/run_proxy.go b/internal/cli/run_proxy.go index 307d154..773f1a8 100644 --- a/internal/cli/run_proxy.go +++ b/internal/cli/run_proxy.go @@ -255,6 +255,7 @@ func runProxy(conf *config.Config, version string) error { //nolint: funlen DomainFrontingIP: conf.GetDomainFrontingIP(nil), DomainFrontingProxyProtocol: conf.GetDomainFrontingProxyProtocol(false), PreferIP: conf.PreferIP.Get(mtglib.DefaultPreferIP), + AutoUpdate: conf.AutoUpdate.Get(false), AllowFallbackOnUnknownDC: conf.AllowFallbackOnUnknownDC.Get(false), TolerateTimeSkewness: conf.TolerateTimeSkewness.Value, diff --git a/internal/config/config.go b/internal/config/config.go index 30c0c20..15a76ab 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -28,6 +28,7 @@ type Config struct { BindTo TypeHostPort `json:"bindTo"` ProxyProtocolListener TypeBool `json:"proxyProtocolListener"` PreferIP TypePreferIP `json:"preferIp"` + AutoUpdate TypeBool `json:"autoUpdate"` 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 e58bc14..bb5ccce 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -15,6 +15,7 @@ type tomlConfig struct { BindTo string `toml:"bind-to" json:"bindTo"` ProxyProtocolListener bool `toml:"proxy-protocol-listener" json:"proxyProtocolListener"` PreferIP string `toml:"prefer-ip" json:"preferIp,omitempty"` + AutoUpdate bool `toml:"auto-update" json:"autoUpdate,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/mise.lock b/mise.lock index ac22b61..bfa377d 100644 --- a/mise.lock +++ b/mise.lock @@ -33,10 +33,10 @@ backend = "aqua:golangci/golangci-lint" "platforms.windows-x64" = { checksum = "sha256:c60c87695e79db8e320f0e5be885059859de52bb5ee5f11be5577828570bc2a3", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-windows-amd64.zip"} [[tools.goreleaser]] -version = "2.13.3" +version = "2.14.1" backend = "aqua:goreleaser/goreleaser" -"platforms.linux-arm64" = { checksum = "sha256:156656d0f874542d618568bd50afd3d33ced2e8aab2c60cc7c21e1b9fa52031e", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Linux_arm64.tar.gz"} -"platforms.linux-x64" = { checksum = "sha256:4b66f2f78f78561330350651ade557b70328664718490f37834749073af21d20", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Linux_x86_64.tar.gz"} -"platforms.macos-arm64" = { checksum = "sha256:5516c37779efb3935d5b213cda3b0b9025ae94ddbcb51df6919acbcdef4194b0", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Darwin_all.tar.gz"} -"platforms.macos-x64" = { checksum = "sha256:5516c37779efb3935d5b213cda3b0b9025ae94ddbcb51df6919acbcdef4194b0", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Darwin_all.tar.gz"} -"platforms.windows-x64" = { checksum = "sha256:c5586c4ed749ca358ad61ed73ee4b8039cfa68daae8c23e69fb086d549dfb31d", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Windows_x86_64.zip"} +"platforms.linux-arm64" = { checksum = "sha256:a84d3b27f052c12ad5c8342d7caf1450a7174a305730aed21d72db09301e49a5", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.14.1/goreleaser_Linux_arm64.tar.gz"} +"platforms.linux-x64" = { checksum = "sha256:2df975a7acbfdeaf888d596cab0024d48ec7fb7d747e1d08b90948b791f40a5f", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.14.1/goreleaser_Linux_x86_64.tar.gz"} +"platforms.macos-arm64" = { checksum = "sha256:9f2e47f847b4f4177376fc6aa6914fbc7f673f59720076747e738b578c2e896e", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.14.1/goreleaser_Darwin_all.tar.gz"} +"platforms.macos-x64" = { checksum = "sha256:9f2e47f847b4f4177376fc6aa6914fbc7f673f59720076747e738b578c2e896e", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.14.1/goreleaser_Darwin_all.tar.gz"} +"platforms.windows-x64" = { checksum = "sha256:d7a3d8ba795e97ab8c4f8003630d300da164adf21fde5a4049440c20f15c3137", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.14.1/goreleaser_Windows_x86_64.zip"} diff --git a/mtglib/internal/dc/init.go b/mtglib/internal/dc/init.go index fd8befa..1af0545 100644 --- a/mtglib/internal/dc/init.go +++ b/mtglib/internal/dc/init.go @@ -57,6 +57,9 @@ var defaultDCAddrSet = dcAddrSet{ 5: { {Network: "tcp4", Address: "149.154.171.5:443"}, }, + 203: { + {Network: "tcp4", Address: "91.105.192.100:443"}, + }, }, v6: map[int][]Addr{ 1: { @@ -74,5 +77,8 @@ var defaultDCAddrSet = dcAddrSet{ 5: { {Network: "tcp6", Address: "[2001:b28:f23f:f005::a]:443"}, }, + 203: { + {Network: "tcp6", Address: "[2a0a:f280:0203:000a:5000:0000:0000:0100]:443"}, + }, }, } diff --git a/mtglib/internal/dc/updater.go b/mtglib/internal/dc/updater.go index 72adf38..e8b3339 100644 --- a/mtglib/internal/dc/updater.go +++ b/mtglib/internal/dc/updater.go @@ -32,7 +32,7 @@ func (u *updater) run(ctx context.Context, callback func() error) { for { u.logger.Info("start update") if err := callback(); err != nil { - u.logger.WarningError("cannot update: %w", err) + u.logger.WarningError("cannot update", err) } u.logger.Info("updated") diff --git a/mtglib/internal/dc/view_test.go b/mtglib/internal/dc/view_test.go index 90742c0..7dbf554 100644 --- a/mtglib/internal/dc/view_test.go +++ b/mtglib/internal/dc/view_test.go @@ -41,6 +41,7 @@ func (suite *ViewTestSuite) TestGetV4() { }, 203: { {Network: "tcp4", Address: "127.0.0.2:443"}, + {Network: "tcp4", Address: "91.105.192.100:443"}, }, 2: { {Network: "tcp4", Address: "149.154.167.51:443"}, @@ -60,6 +61,7 @@ func (suite *ViewTestSuite) TestGetV6() { 111: {}, 203: { {Network: "tcp6", Address: "xxx"}, + {Network: "tcp6", Address: "[2a0a:f280:0203:000a:5000:0000:0000:0100]:443"}, }, 1: { {Network: "tcp6", Address: "[2001:b28:f23d:f001::a]:443"}, diff --git a/mtglib/proxy.go b/mtglib/proxy.go index a0e4965..ce740a1 100644 --- a/mtglib/proxy.go +++ b/mtglib/proxy.go @@ -252,6 +252,9 @@ func (p *Proxy) doTelegramCall(ctx *streamContext) error { if err != nil { return fmt.Errorf("no addresses to call: %w", err) } + if conn == nil { + return fmt.Errorf("no available addresses for DC %d", ctx.dc) + } tgConn, err := foundAddr.Obfuscator.SendHandshake(conn, ctx.dc) if err != nil { @@ -346,8 +349,10 @@ func NewProxy(opts ProxyOpts) (*Proxy, error) { domainFrontingProxyProtocol: opts.DomainFrontingProxyProtocol, } - proxy.configUpdater.Run(ctx, dc.PublicConfigUpdateURLv4, "tcp4") - proxy.configUpdater.Run(ctx, dc.PublicConfigUpdateURLv6, "tcp6") + if opts.AutoUpdate { + proxy.configUpdater.Run(ctx, dc.PublicConfigUpdateURLv4, "tcp4") + proxy.configUpdater.Run(ctx, dc.PublicConfigUpdateURLv6, "tcp6") + } pool, err := ants.NewPoolWithFunc(opts.getConcurrency(), func(arg any) { diff --git a/mtglib/proxy_opts.go b/mtglib/proxy_opts.go index 09f47f2..88af9ea 100644 --- a/mtglib/proxy_opts.go +++ b/mtglib/proxy_opts.go @@ -85,6 +85,12 @@ type ProxyOpts struct { // This is an optional setting. PreferIP string + // AutoUpdate defines if it is required to auto update proxy list from + // Telegram instead of relying on a hardcoded list. + // + // This is an optional setting. + AutoUpdate bool + // 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