fix(handler/socks): bind UDP associate relay socket to BND.ADDR source IP (issue #763)
The client-facing UDP relay listener (cc) in handleUDP was bound to the wildcard address, so replies sent from it used the kernel-selected source IP (the interface's primary IP), which mismatches the BND.ADDR advertised to the client (the TCP control connection's local IP). Per RFC 1928 6, compliant clients drop such replies, breaking SOCKS5 UDP associate under multiple IP aliases where metadata.interface differs from the primary IP. Bind cc to the TCP control connection's local IP so its reply source IP always matches BND.ADDR. The outbound relay socket (pc) already binds the interface IP via Router.Dial -> dialer.ListenUDP(laddr).
This commit is contained in:
+10
-2
@@ -37,11 +37,19 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, network st
|
||||
return reply.Write(conn)
|
||||
}
|
||||
|
||||
// Bind the client-facing relay socket to the TCP control connection's local
|
||||
// IP — the address advertised to the client as BND.ADDR — so replies sent
|
||||
// from this socket carry the matching source IP. A wildcard bind lets the
|
||||
// kernel pick the interface's primary IP, which mismatches BND.ADDR and
|
||||
// makes compliant clients drop the replies (RFC 1928 §6). This is what
|
||||
// breaks UDP associate under multiple IP aliases (metadata.interface).
|
||||
host, _, _ := net.SplitHostPort(conn.LocalAddr().String())
|
||||
|
||||
lc := xnet.ListenConfig{
|
||||
Netns: h.options.Netns,
|
||||
}
|
||||
|
||||
cc, err := lc.ListenPacket(ctx, network, "")
|
||||
cc, err := lc.ListenPacket(ctx, network, net.JoinHostPort(host, "0"))
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
reply := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||
@@ -60,7 +68,7 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, network st
|
||||
saddr := gosocks5.Addr{}
|
||||
saddr.ParseFrom(cc.LocalAddr().String())
|
||||
|
||||
saddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||
saddr.Host = host
|
||||
if v := net.ParseIP(h.md.publicAddr); v != nil {
|
||||
saddr.Host = h.md.publicAddr
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user