fix(handler/socks5): RFC 1928 compliance — method negotiation, BND.ADDR, UDP ordering, and safe type assertions

- selector.go: Select() now only returns methods the client actually offered,
  defaulting to MethodNoAcceptable (0xFF) when no mutually-supported method
  exists. Prevents protocol desync when authenticator is set but client
  doesn't offer UserPass. (#1, #2)

- connect.go: CONNECT success reply now carries the outbound connection's
  actual local address as BND.ADDR per RFC 1928 §6, instead of 0.0.0.0:0. (#4)

- udp.go: UDP ASSOCIATE now verifies the upstream chain is reachable before
  sending Success to the client; on failure sends a proper Failure reply.
  Also adds safe type assertions for net.TCPAddr and net.UDPAddr to prevent
  panics on wrapped connections, and returns errors on DNS resolution failure
  instead of silently dropping datagrams. (#5, #1, #2, #3)
This commit is contained in:
ginuerzh
2026-06-25 15:41:15 +08:00
parent b01f5d065f
commit 39580f04ca
3 changed files with 72 additions and 31 deletions
+4 -1
View File
@@ -82,7 +82,10 @@ func (h *socks5Handler) handleConnect(ctx context.Context, conn net.Conn, networ
ro.SrcAddr = cc.LocalAddr().String()
ro.DstAddr = cc.RemoteAddr().String()
resp := gosocks5.NewReply(gosocks5.Succeeded, nil)
// Report the actual bound address (BND.ADDR) per RFC 1928 §6.
bndAddr := gosocks5.Addr{}
bndAddr.ParseFrom(cc.LocalAddr().String())
resp := gosocks5.NewReply(gosocks5.Succeeded, &bndAddr)
log.Trace(resp)
if err := resp.Write(conn); err != nil {
log.Error(err)