From d34035e644ab7e4495ce0a5cfa28b2a27df02b2d Mon Sep 17 00:00:00 2001 From: patterniha <71074308+patterniha@users.noreply.github.com> Date: Sun, 15 Jun 2025 08:54:55 +0330 Subject: [PATCH 1/4] Freedom: Fix UDP reply mismatch-address --- proxy/freedom/freedom.go | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 779992f7..edb1f6c8 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -238,7 +238,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte if destination.Network == net.Network_TCP { reader = buf.NewReader(conn) } else { - reader = NewPacketReader(conn, UDPOverride) + reader = NewPacketReader(ctx, conn, UDPOverride) } if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil { return errors.New("failed to process response").Base(err) @@ -273,7 +273,7 @@ func isTLSConn(conn stat.Connection) bool { return false } -func NewPacketReader(conn net.Conn, UDPOverride net.Destination) buf.Reader { +func NewPacketReader(ctx context.Context, conn net.Conn, UDPOverride net.Destination) buf.Reader { iConn := conn statConn, ok := iConn.(*stat.CounterConnection) if ok { @@ -283,10 +283,17 @@ func NewPacketReader(conn net.Conn, UDPOverride net.Destination) buf.Reader { if statConn != nil { counter = statConn.ReadCounter } - if c, ok := iConn.(*internet.PacketConnWrapper); ok && UDPOverride.Address == nil && UDPOverride.Port == 0 { + if c, ok := iConn.(*internet.PacketConnWrapper); ok { + isAddrChanged := false + outbounds := session.OutboundsFromContext(ctx) + targetAddr := outbounds[len(outbounds)-1].Target.Address + if UDPOverride.Address != nil || UDPOverride.Port != 0 || targetAddr.Family().IsDomain() { + isAddrChanged = true + } return &PacketReader{ PacketConnWrapper: c, Counter: counter, + IsAddrChanged: isAddrChanged, } } return &buf.PacketReader{Reader: conn} @@ -295,6 +302,7 @@ func NewPacketReader(conn net.Conn, UDPOverride net.Destination) buf.Reader { type PacketReader struct { *internet.PacketConnWrapper stats.Counter + IsAddrChanged bool } func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { @@ -306,10 +314,12 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { return nil, err } b.Resize(0, int32(n)) - b.UDP = &net.Destination{ - Address: net.IPAddress(d.(*net.UDPAddr).IP), - Port: net.Port(d.(*net.UDPAddr).Port), - Network: net.Network_UDP, + if !r.IsAddrChanged { + b.UDP = &net.Destination{ + Address: net.IPAddress(d.(*net.UDPAddr).IP), + Port: net.Port(d.(*net.UDPAddr).Port), + Network: net.Network_UDP, + } } if r.Counter != nil { r.Counter.Add(int64(n)) From 1cdca10352ea6dbeb180b4c7344c4b313363831b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A3=8E=E6=89=87=E6=BB=91=E7=BF=94=E7=BF=BC?= Date: Sat, 12 Jul 2025 00:56:12 +0800 Subject: [PATCH 2/4] Update freedom.go --- proxy/freedom/freedom.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index edb1f6c8..a519a8e0 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -314,6 +314,8 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { return nil, err } b.Resize(0, int32(n)) + // if udp dest addr is changed, we are unable to get the correct src addr + // so we don't attach src info to udp packet, break cone behavior, assuming the dial dest is the expected scr addr if !r.IsAddrChanged { b.UDP = &net.Destination{ Address: net.IPAddress(d.(*net.UDPAddr).IP), From adea0161ace632cf4c99748c2abe35eb4fe13c74 Mon Sep 17 00:00:00 2001 From: patterniha <71074308+patterniha@users.noreply.github.com> Date: Wed, 16 Jul 2025 10:00:38 +0330 Subject: [PATCH 3/4] copy ctx-outbounds to newCtx-outbounds --- proxy/freedom/freedom.go | 1 + 1 file changed, 1 insertion(+) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index a519a8e0..43fa8218 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -175,6 +175,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte var newCancel context.CancelFunc if session.TimeoutOnlyFromContext(ctx) { newCtx, newCancel = context.WithCancel(context.Background()) + newCtx = session.ContextWithOutbounds(newCtx, session.OutboundsFromContext(ctx)) } plcy := h.policy() From 31c1a8f974d634807b37029eba872903db75c0df Mon Sep 17 00:00:00 2001 From: patterniha <71074308+patterniha@users.noreply.github.com> Date: Wed, 16 Jul 2025 22:21:56 +0330 Subject: [PATCH 4/4] pass destination --- proxy/freedom/freedom.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 43fa8218..af66e2a4 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -175,7 +175,6 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte var newCancel context.CancelFunc if session.TimeoutOnlyFromContext(ctx) { newCtx, newCancel = context.WithCancel(context.Background()) - newCtx = session.ContextWithOutbounds(newCtx, session.OutboundsFromContext(ctx)) } plcy := h.policy() @@ -239,7 +238,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte if destination.Network == net.Network_TCP { reader = buf.NewReader(conn) } else { - reader = NewPacketReader(ctx, conn, UDPOverride) + reader = NewPacketReader(conn, UDPOverride, destination) } if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil { return errors.New("failed to process response").Base(err) @@ -274,7 +273,7 @@ func isTLSConn(conn stat.Connection) bool { return false } -func NewPacketReader(ctx context.Context, conn net.Conn, UDPOverride net.Destination) buf.Reader { +func NewPacketReader(conn net.Conn, UDPOverride net.Destination, DialDest net.Destination) buf.Reader { iConn := conn statConn, ok := iConn.(*stat.CounterConnection) if ok { @@ -286,9 +285,7 @@ func NewPacketReader(ctx context.Context, conn net.Conn, UDPOverride net.Destina } if c, ok := iConn.(*internet.PacketConnWrapper); ok { isAddrChanged := false - outbounds := session.OutboundsFromContext(ctx) - targetAddr := outbounds[len(outbounds)-1].Target.Address - if UDPOverride.Address != nil || UDPOverride.Port != 0 || targetAddr.Family().IsDomain() { + if UDPOverride.Address != nil || UDPOverride.Port != 0 || DialDest.Address.Family().IsDomain() { isAddrChanged = true } return &PacketReader{