Commit Graph

638 Commits

Author SHA1 Message Date
ginuerzh 419f4c4c73 docs(ctx): add doc comments, remove dead WithContext interface, simplify HashFromContext
Remove unused WithContext interface (zero references in codebase), add
doc comments for all 14 exported symbols, and simplify HashFromContext
to match the one-liner pattern used by the other four getters.
Add 22 unit tests covering round-trip, empty context, wrong type, nil
values, multiple values, independent keys, and the Context interface.
2026-05-24 14:26:45 +08:00
ginuerzh 4efb4b9974 fix(direct): guard nil dialer and nil logger in Connect, add doc comments
Add nil checks for connect-options dialer and logger to prevent
nil-pointer panics when Connect is called without a DialerConnectOption
or LoggerOption. Add package and NewConnector godoc comments.

Add 10 unit tests covering construction, Init metadata parsing,
Connect success/reject/dial-error paths, nil dialer, nil logger,
and the reject conn stub.
2026-05-24 14:19:08 +08:00
ginuerzh effba3b690 docs(parsing): add package and symbol doc comments
Add godoc comments for all 62 exported symbols across 20 files in
config/parsing/: 23 MDKey constants, 35 Parse*/List/Default* functions,
3 TLS helpers, 1 Args struct with 7 fields, and the package doc.
2026-05-24 13:58:37 +08:00
ginuerzh 2b1e4ca3a7 test(parsing): add 229 unit tests across 18 config/parsing packages
Covering nil-input safety, plugin backends (HTTP/gRPC/default), loaders
(File/HTTP/Redis), selector strategies, edge cases (empty/invalid inputs),
and hop-to-node metadata inheritance. All tests passing.
2026-05-24 13:34:33 +08:00
ginuerzh 9febb23bc9 fix(config): stop mutating shared config structs during parsing
Prevent data loss and nil panics across 5 parse functions:
- chain: nil-guard hop entries to avoid deref on empty YAML lists
- hop: build merged metadata map instead of writing inherited values
  into the original NodeConfig; swap+restore around ParseNode call
- node: use local connCfg/dialCfg instead of overwriting cfg.Connector
  and cfg.Dialer fields; only fill in Type when empty
- parser: preserve existing config file fields when env vars override
  Level/Addr (was replacing the entire struct)
- router: only update ipNet from dst CIDR if parse succeeds, keeping
  the route.Net fallback instead of overwriting with nil
2026-05-24 12:56:54 +08:00
ginuerzh 8390ccadab test(config): add unit tests for loader, doc comments, fix fmt.Errorf misuse
- Add 808-line loader_test.go covering registerGroup, register, and Load
- Add package and exported symbol doc comments to loader.go
- Fix fmt.Errorf(resp.Status) → errors.New(resp.Status) in sd/plugin/http.go
  (resp.Status is a plain string, not a format string)
2026-05-24 12:36:51 +08:00
ginuerzh 82e7e50120 fix(config): nil deref on Load, SoMark/Metadata gating, netns copy-paste bug, and partial-reg-failure side effects
- loader: guard cfg == nil in Load() to prevent nil-pointer dereference on
  cfg.Log / cfg.TLS access.
- loader: defer logger.SetDefault and parsing.SetDefaultTLSConfig until
  after register() succeeds, so a failed reload does not leave global
  state (logger, default TLS) pointing at the new config while components
  remain from the old config.
- loader: extract registerGroup[T] helper to eliminate repeated
  unregister-then-register boilerplate.  Entries are parsed and collected
  before unregistering; a parse error now preserves the previous group
  (old code unregistered first, then parsed, leaving an empty registry on
  parse failure).
- hop: move cfg.SockOpts.Mark extraction outside the cfg.Metadata != nil
  block so the socket mark is read even when hop-level metadata is absent.
- hop: fix copy-paste error in netns inheritance: v.Name was incorrectly
  stored as MDKeyNetns instead of v.Netns (introduced in f71351f).
2026-05-24 10:15:37 +08:00
ginuerzh 5a838a7d47 fix(dtls): upgrade pion/dtls v2.2.6 to v3.1.1 fixing CVE-2026-26014
Upgrade github.com/pion/dtls from v2.2.6 to v3.1.1 to fix nonce reuse
vulnerability in AES-GCM ciphers (GHSA-9f3f-wv7r-qc8r). Migrate from
deprecated Config-struct API to ListenWithOptions/ClientWithOptions
options-based API.

v2 Config fields mapped to v3 functional options:
- Certificates, InsecureSkipVerify, ExtendedMasterSecret, ServerName,
  RootCAs, ClientCAs, ClientAuth, FlightInterval, MTU

ConnectContextMaker removed — no longer exists in v3; explicit
HandshakeContext(ctx) on *Conn is the replacement for timeout control.
2026-05-23 18:48:21 +08:00
ginuerzh 982ffa8149 test(cmd): add unit tests achieving 93.8% coverage 2026-05-23 18:36:24 +08:00
ginuerzh 1f62219c1a docs(cmd): add package and symbol doc comments 2026-05-23 18:14:05 +08:00
ginuerzh ee57a383c5 fix(cmd): shallow-copy leaks in node/service expansion, inconsistent auth priority
Three bugs in CLI-to-config conversion:

1. Comma-separated -F nodes shared Connector/Dialer/Metadata pointers
   due to struct value copy; add deep-copy helpers per node.

2. Port-range-expanded -L services shared Handler/Listener/Metadata
   pointers; deep-copy per service so metadata mutations don't cross-talk.

3. buildServiceConfig's ?auth= query param unconditionally overwrote
   URL-embedded auth; buildNodeConfig used fallback-only. Align both
   on URL-auth-first semantics (query param as fallback).
2026-05-23 17:44:39 +08:00
ginuerzh c59566d96f test(chain): add unit tests achieving 86.7% coverage
112 tests covering Transport, Chain, Route, Router, packetConn wrapper,
routePath, and all interface satisfaction checks.
2026-05-23 17:17:38 +08:00
ginuerzh c7f58a400b docs(chain): add package and symbol doc comments
Cover the three main abstractions (Router, Chain, Transport), route traversal
lifecycle (Dial → Handshake → Connect), and multiplexing sub-route splitting.
2026-05-23 16:36:47 +08:00
ginuerzh 569572d6f7 fix(chain): Copy returns wrong pointer, connection leaks in Connect/Handshake, deferred cancel accumulation in retry loops
- transport.go: Copy() returned original pointer instead of the allocated copy,
  causing data races and incorrect routing for multiplexed chains.
- route.go: Connect and Handshake failures in intermediate nodes leaked the
  returned connection. Handshake fix preserves the original Connect result
  (guaranteed non-nil) and closes both the Handshake return value and input.
- router.go: defer cancel() inside retry loops accumulated context timers
  across iterations. Wrapped each loop body in an IIFE so defer scopes
  per-iteration and timers are released immediately.
2026-05-23 16:30:53 +08:00
ginuerzh d015378654 test(bypass): add unit tests achieving 96.4% total coverage
- 88 tests: 70 for core (96.8%), 12 for gRPC plugin, 14 for HTTP plugin
- Cover all matchers (IP, CIDR, wildcard, IP range), loader sources,
  bypassGroup logic, periodReload, and plugin fail-open semantics
- Add nil-logger guard in httpPlugin.Contains to prevent panic
  when logger is nil
2026-05-23 16:04:30 +08:00
ginuerzh bf4af78ebf docs(bypass): add package and symbol doc comments
Add Go doc comments for all exported symbols, option functions, and
internal types across the bypass package and plugin sub-package,
following the style of the admission package.
2026-05-23 15:55:52 +08:00
ginuerzh 54ca9161f7 fix(bypass): httpLoader.Close leak, httpPlugin fail-closed, missing Close method
- Add missing httpLoader.Close() in localBypass.Close (was leaking HTTP loader resources)
- Change httpPlugin.Contains to fail-open on errors, matching gRPC plugin
- Add error logging on all httpPlugin error paths (previously silent)
- Add httpPlugin.Close method to drain idle HTTP connections
- Document bypassGroup.Contains whitelist AND / blacklist OR logic
2026-05-23 15:52:22 +08:00
ginuerzh e99ef1c951 test(auth): add unit tests achieving 100% coverage for core, 100% for gRPC plugin, 96.6% for HTTP plugin 2026-05-22 22:59:30 +08:00
ginuerzh 91cae5bdeb fix(auth): redisLoader copy-paste bug, httpLoader.Close leak, reload data wipe, silent parse errors
- redisLoader branch used fileLoader instead of redisLoader (copy-paste bug)
- Close() was missing httpLoader.Close() (resource leak vs admission pattern)
- reload() now preserves kvs on load() error instead of wiping to static-only
- load() propagates first loader error, reload() returns early on load failure
- parseAuths scanner errors now logged instead of silently discarded
- http plugin drains body on non-200 to allow keep-alive connection reuse
- Replace manual map-copy loops with maps.Copy
2026-05-22 22:35:55 +08:00
ginuerzh 3f73c82d00 fix(ss): address review findings for PR #96 — nil guards, resource leaks, dead code
- Bump go-shadowsocks2 to v0.1.3 (new API symbols)
- Return error instead of nil when Target() is empty in TCP handler
- Reset wbuf unconditionally on write error to prevent unbounded growth
- Add nil guard on targetAddr before WriteTo to prevent panic
- Remove duplicate NewClientConfig call and dead ClientConfig literal
- Remove unused noDelay metadata field
- Fix buffer-size guard to catch negative values (len(b)==0 → bufSize<=0)
- Add address context to parse/session error messages
2026-05-22 21:40:33 +08:00
ginuerzh 5433ca580c Merge remote-tracking branch 'origin/pr/96' 2026-05-22 21:07:43 +08:00
ginuerzh 0c37224530 test(admission): add unit tests achieving 100% coverage for wrapper, 97.6% for core, 96.4% for plugin 2026-05-22 19:03:47 +08:00
ginuerzh b9d74c1b8e docs(admission): add package and symbol doc comments
Add package-level documentation and Go doc comments for all exported
types, functions, and methods across the admission package, its plugin
sub-packages, and connection/listener wrappers.
2026-05-22 17:19:48 +08:00
ginuerzh 174bc082d1 fix(tunnel): data race in CloseOnIdle and goroutine leak in sniffingWebsocketFrame
- Use write lock (Lock) instead of read lock (RLock) in CloseOnIdle since
  it modifies the close channel, preventing a race with Close() that could
  panic on double-close of channel.
- Buffer sniffingWebsocketFrame errc to capacity 2 and close both
  connections on first error to ensure the remaining copy goroutine
  unblocks and exits cleanly.
2026-05-22 16:31:37 +08:00
ginuerzh ed93d60004 fix(admission): use client network, fail-open on nil gRPC client, close http resources
- Use client address network instead of listener network in admission wrapper
- Return true (allow) when gRPC admission plugin client is nil to fail-open
- Add Close() to httpPlugin to close idle HTTP connections
- Close httpLoader in localAdmission.Close()
- Remove dead commented-out code in periodReload
2026-05-22 15:58:24 +08:00
kLiHz 3c8995027a adapt newest go-shadowsocks2 lib 2026-05-22 13:35:01 +08:00
ginuerzh 70dee081a4 chore(deps): bump Go 1.26.3, update gosocks4/5, plugin, relay, tls-dissector 2026-05-21 22:59:12 +08:00
ginuerzh 01a2bbaa11 fix(masque): address review findings for PR #76
- Return errors from MasqueConn.Read/Write instead of silently
  succeeding (prevents infinite busy-loops and silent data loss
  if these methods are accidentally called).
- Set recorder Network field in protocol dispatch switch rather
  than hardcoding "udp", so early errors don't misreport type.
- Clarify that DatagramConn context-ID handling only supports
  context ID 0 (sufficient for CONNECT-UDP per RFC 9298).
2026-05-21 22:50:29 +08:00
ginuerzh 66b53580af merge: PR #76 — MASQUE CONNECT-UDP and CONNECT-TCP support (RFC 9298/9114)
Extend MASQUE implementation to support TCP tunneling via standard
HTTP/3 CONNECT method, in addition to UDP via CONNECT-UDP.
2026-05-21 22:50:23 +08:00
ginuerzh 8435716166 merge: PR #93 — configurable TCP keepalives for all TCP-based listeners and dialers 2026-05-21 21:47:15 +08:00
ginuerzh 3402418573 merge: PR #92 — make pipe idle timeout configurable via idleTimeout metadata
Merge beezly/fix/configurable-pipe-timeout with conflict resolution
in pipe.go (PipeOption/WithReadTimeout functional options pattern).

Fix pipe_test.go: update 4 pipeHalf() calls to pass readTimeout arg
matching the new signature.
2026-05-21 21:38:32 +08:00
ginuerzh 238a0b95b7 feat: upgrade core to v0.4.0, pass network to admission, add dial options
Upgrade github.com/go-gost/core from v0.3.3 to v0.4.0, adapting to
interface changes:
- Admit(ctx, network, addr, opts) now accepts a network parameter
- Router.Dial now accepts variadic chain.DialOption, forwarded to
  the route's Dial call along with router-level options
- gRPC/HTTP admission plugins include the new Network field

Also fix two typos: ResoloverNodeOption -> ResolverNodeOption,
WithHostOpton -> WithHostOption.
2026-05-21 21:26:49 +08:00
ginuerzh ef58909fb7 fix(dialer): correct inverted setMark on FreeBSD/OpenBSD
Fix setMark early-return conditions that were inverted relative to
Linux: on FreeBSD (SO_USER_COOKIE) and OpenBSD (SO_RTABLE), a
non-zero mark was short-circuited instead of applied, disabling
socket marking entirely.

Also fix GetClientIP to trim leading whitespace from X-Forwarded-For
entries (per RFC 7239), and fix Body.Read to subtract len(b) instead
of n from recordSize when a single read exceeds the remaining quota.

Add unit tests for internal/net/ (addr, dialer, http, ip, net, pipe,
transport, resolve, proxyproto, udp).
2026-05-21 20:58:48 +08:00
ginuerzh d189dc7967 fix(pipe): prevent error swallowing and goroutine leak in Pipe/Transport
Pipe: remove context.WithCancel that caused premature ctx.Done()
before the second pipeHalf could return its error. Replace with a
completed counter that drains both errors even on cancellation.

Transport: increase error channel buffer from 1 to 2 to prevent
goroutine leak when both CopyBuffer goroutines complete.
2026-05-21 10:28:55 +08:00
Andrew Beresford ac99425002 feat: extend TCP keepalive support to all TCP-based listeners and dialers
Add configurable TCP keepalive (keepalive, keepalive.idle,
keepalive.interval, keepalive.count) to all TCP-based transport types:
tls, mtls, mtcp, ws/wss, mws/mwss, http2, ssh, sshd listeners and
tls, mtls, mtcp, ws/wss, mws/mwss, ssh, sshd dialers.

For types that already use "keepalive" for an app-level protocol
(grpc listener/dialer, ws/mws dialers, ssh/sshd dialers), the TCP
keepalive parameters are exposed under the tcp.keepalive.* prefix to
avoid ambiguity.

Also extract shared helpers into internal/net/keepalive.go:
- WrapKeepaliveListener: applies KeepAliveConfig on every accepted TCPConn
- ApplyKeepalive: applies KeepAliveConfig to a single TCPConn

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 14:32:53 +01:00
Andrew Beresford cf70a0cbe1 Add configurable TCP keepalives to TCP listener and dialer
Exposes TCP keepalive configuration via listener and dialer metadata:

  keepalive: true
  keepalive.idle: 30s
  keepalive.interval: 10s
  keepalive.count: 6

When enabled, the OS sends keepalive probes after the idle period and
tears down the socket if the remote does not respond. This causes any
blocked Read() on a dead connection to return promptly, releasing
goroutines and memory — covering both legs of a CONNECT tunnel (the
inbound client connection via the listener, and the outbound upstream
connection via the dialer).

This is the correct alternative to a hard application-level read
deadline (SetReadDeadline) for detecting dead connections, as it
distinguishes truly dead connections from legitimately idle ones.

Relates to: https://github.com/go-gost/x/issues/91
2026-05-08 11:33:54 +01:00
Andrew Beresford 290e9c37d5 Make pipe read timeout configurable via idleTimeout metadata
The 30s hardcoded readTimeout in Pipe() caused all CONNECT tunnel
connections to be hard-closed after 30s of inactivity, breaking
WebSocket and long-polling connections through the proxy.

Pipe() now accepts a WithReadTimeout(d) option. When d is 0 (the
default) no read deadline is set, relying on TCP keepalives or context
cancellation to detect dead connections instead.

The HTTP handler exposes this as the idleTimeout metadata key.

Fixes: https://github.com/go-gost/x/issues/91
2026-05-08 11:31:53 +01:00
dependabot[bot] 07ca57055a Bump google.golang.org/grpc from 1.67.1 to 1.79.3
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.1 to 1.79.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.1...v1.79.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.79.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-21 21:37:46 +08:00
ginuerzh 2acc669976 fix webtransport listener 2026-04-21 21:34:50 +08:00
misakydrip 6c32dda058 fix a udp bug
fix udp bug error: use of closed network connection
2026-04-21 21:07:00 +08:00
RMT 2a2643a6b7 WIP 2026-04-21 21:05:43 +08:00
Evsyukov Denis 802943bd28 fix(ss): propagate cipher errors and decode SIP002 base64 auth
- Return err instead of nil in SS TCP/UDP connector Init when
  NewClientConfig fails, preventing nil pointer dereference in WrapConn
- Initialize tcpClient in UDP connector for UDP-over-TCP path
- Add decodeSIP002Auth to handle ss://BASE64(method:password)@host:port
  URL format with RawURLEncoding and StdEncoding fallback
- Update buildServiceConfig and buildNodeConfig to decode SIP002 auth
  for ss* schemes before falling back to standard userinfo parsing
- Support RawURLEncoding in parseAuthFromCmd with StdEncoding fallback
- Add tests for decodeSIP002Auth, parseAuthFromCmd, and integration
  tests for buildNodeConfig/buildServiceConfig
2026-04-21 20:55:45 +08:00
pak.wzq f373f2f4b9 fix 2026-04-21 20:53:10 +08:00
Vasileios Papadimas 96f35bd7aa feat: add custom header support to PHT protocol
- Add Header field to PHT Client and clientConn structs
- Support custom headers in authorize, push, and pull requests
- Add metadata parsing for header configuration as map[string]string
- Enables PHT usage with header-based authentication (e.g., Cloudflare Access)

Backwards compatible - headers are optional.
2026-04-21 20:51:17 +08:00
Jason Lyu cd7bf9521f fix sshd connection type 2026-04-21 20:49:28 +08:00
21paradox 180145189f add SetReadDeadline in Pipe, to prevent memory not auto release in mws/mtcp 2026-04-21 20:02:32 +08:00
David Manouchehri 7625973ca1 Add MASQUE/CONNECT-UDP support (RFC 9298)
Implement UDP tunneling over HTTP/3 using HTTP Datagrams (RFC 9297):
- Add masque handler for server-side CONNECT-UDP
- Add masque connector and h3-masque dialer for client-side
- Add enableDatagrams option to HTTP/3 listener
- Add shared utilities for datagram connections and path parsing

Resource management and connection caching:
- Add deferred stream cleanup in connector on error paths
- Add IsClosed() and Close() methods to Client for proper session management
- Clean up stale cached clients in dialer before reuse
- Close underlying stream when DatagramConn is closed
- Move RequestStream opening from connector to dialer to enable dead
  connection detection and cache invalidation (follows QUIC dialer pattern)
2026-04-21 19:53:07 +08:00
Rehtt b3b5986b63 fix command line resolution path-based protocols (such as unix socket) address resolution problem 2026-04-21 19:47:38 +08:00
dependabot[bot] 254699e176 Bump github.com/quic-go/quic-go from 0.54.1 to 0.57.0
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.54.1 to 0.57.0.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.54.1...v0.57.0)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-version: 0.57.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-21 19:42:58 +08:00
RMT 6389378610 Remove usage of ShadowConn for ssHandler and ssConnector (#68)
The new ss library has integrated the function of ShadowConn.
2025-12-29 16:22:42 +08:00