Sync upstream: keepalive config, TCP BBR, TCP_USER_TIMEOUT, TCP_NOTSENT_LOWAT, sockopts refactor#455
Closed
dolonet wants to merge 36 commits into9seconds:masterfrom
Closed
Sync upstream: keepalive config, TCP BBR, TCP_USER_TIMEOUT, TCP_NOTSENT_LOWAT, sockopts refactor#455dolonet wants to merge 36 commits into9seconds:masterfrom
dolonet wants to merge 36 commits into9seconds:masterfrom
Conversation
Support multiple named secrets in [secrets] config section. During FakeTLS handshake each secret is tried until HMAC validates. Matched secret name is logged and used for per-user statistics tracking. Built-in HTTP stats API (configurable via api-bind-to) exposes GET /stats with per-user connection counts, bytes in/out, and last-seen timestamps. Backward compatible: single "secret" config key still works.
- Simplify goreleaser to linux/darwin amd64/arm64 only - Remove Docker CI job (using GitHub Releases instead) - Add release workflow with goreleaser - Add monthly upstream sync workflow with conflict detection - Add mtg-multi binaries to gitignore
# Conflicts: # mtglib/proxy.go
# Conflicts: # .github/workflows/ci.yaml
Rewrite README
Benchmarks added in the per-connection-overhead work triggered errcheck warnings (37 unchecked Close/Fprintf in tool/bench code) and a data race on package-level `sink` variable written by concurrent goroutines. - Exclude benchmarks/ and *_bench_test.go from errcheck/ineffassign - Replace concurrent `sink = buf[X]` with runtime.KeepAlive(&buf)
issues.exclude-rules is the v1 schema; golangci-lint v2 moved exclusion rules to linters.exclusions.rules.
Fix CI: benchmark lint exclusions and data race
Upstream changes: - More idiomatic Golang (b6427ee) - Change IP address set priority (1fcec38) - Flaky CI test fixes (eedee63, 73c6a3a, e54d9d6) Conflicts resolved: - README.md: keep fork version - default.pgo: removed (causes SEGV in fork builds) - proxy.go: keep fork's counting conn, use upstream's tracker - proxy_opts.go: keep fork's APIBindTo field
go install github.com/dolonet/mtg-multi@latest was broken because go.mod declared module path as github.com/9seconds/mtg/v2 while the repo lives at github.com/dolonet/mtg-multi. Users ended up installing upstream binary without multi-secret support. Fixes 9seconds#376 (comment)
Sync upstream + fix module path for go install
In TOML, all keys after a [section] header belong to that table. The examples had api-bind-to after [secrets], causing it to be parsed as secrets.api-bind-to and triggering "incorrect secret format" errors. Fixes #6
…order # Conflicts: # .github/workflows/ci.yaml # README.md # default.pgo # mtglib/internal/tls/fake/client_side.go # mtglib/internal/tls/fake/client_side_test.go # mtglib/proxy.go # mtglib/proxy_opts.go
fix: move [secrets] after global keys in config examples
When total connections exceed a configurable limit, a background goroutine (every 5s by default) computes per-user caps using a fair-share algorithm: small users keep their connections, remaining budget is split equally among heavy users. New connections from over-cap users are rejected; existing connections are not killed. Config: [throttle] max-connections = 5000 check-interval = "5s" Stats API response now includes throttle state with active caps.
Add per-user connection throttling
Upstream replaced our reassembleTLSHandshake with a cleaner fragmentedHandshakeReader + parseClientHello in utils.go. Adapted ReadClientHelloMulti to use the new API.
Add throttling docs to README
Sync upstream: refactor TLS fragmentation
Sync upstream: update goreleaser
TCP keepalive was configured (SetKeepAlivePeriod) but never actually enabled (SO_KEEPALIVE) on accepted client connections. Go 1.26's SetKeepAlivePeriod only sets TCP_KEEPIDLE — it does not call setsockopt(SO_KEEPALIVE, 1). Without SO_KEEPALIVE the kernel never sends probe packets, so dead connections from sleeping mobile clients linger until the idle timeout fires. Replace SetKeepAlive + SetKeepAlivePeriod with net.KeepAliveConfig (available since Go 1.24) for explicit per-socket control: Idle: 30s (time before first probe) Interval: 10s (between probes) Count: 3 (failed probes to declare dead) This detects dead connections in ~60s instead of relying on system defaults (tcp_keepalive_intvl=75s, probes=9 → up to 11 minutes). Increase the default idle timeout from 1 minute to 5 minutes. MTProto clients send ping_delay_disconnect every ~60s, which resets the idle timer. The previous 1-minute default created a race: if a ping arrived even 1–2 seconds late the relay was killed. A 5-minute window also survives typical mobile sleep periods (phone idle 2–5 min) where the NAT mapping is still alive and the connection can resume without reconnection. Cherry-picked from 9seconds/mtg@5f81ae3 with fork-specific fixes: - keep "time" import in run_proxy.go (used by throttle feature) - fix network/sockopts_test.go import path to dolonet/mtg-multi
Sync upstream: improve TCP keepalive and idle timeout for mobile clients
Sync upstream history (no-op merge after cherry-pick of 9seconds#441)
…cipher Merges upstream commits: - bec321d Fix DPI detection: skip GREASE cipher suite in ClientHello parsing - eb56493 Add separate handshake timeout - 39ab557 Small refactoring - 5bf218f Do not use default TLS cipher Conflict resolution: - Kept ReadClientHelloMulti for multi-secret support - Preserved Secrets/Throttle/APIBindTo features from dolonet fork - Removed per-connection SetReadDeadline from ReadClientHelloMulti (superseded by proxy-level handshake timeout via SetDeadline)
Sync upstream: handshake timeout, GREASE cipher fix, no-default TLS cipher
This small commits conditionally sets TCP BBR as a preferrable algorithm for TCP congestion control
Contributor
Author
|
Created by mistake - wrong target repo |
dolonet
added a commit
to dolonet/mtg-multi
that referenced
this pull request
Apr 9, 2026
….0, go-dns v1.3.3)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Syncs 5 substantive commits from upstream 9seconds/mtg (PRs #451–#454), skipping merge commits.
Changes
sockopts_congestion,sockopts_reuseaddr,sockopts_usertimeout,sockopts_lowat)Fork-specific checks
"time"import ininternal/cli/run_proxy.gopreserved (needed forThrottleCheckInterval)network/v2/sockopts_test.gopackage declaration unchangedgo build ./...passes cleanly