Browse Source

Freedom: Fix UDP reply mismatch-address (#4816)

patterniha 3 months ago
parent
commit
050f596e8f
1 changed files with 17 additions and 7 deletions
  1. 17 7
      proxy/freedom/freedom.go

+ 17 - 7
proxy/freedom/freedom.go

@@ -239,7 +239,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(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 +274,7 @@ func isTLSConn(conn stat.Connection) bool {
 	return false
 }
 
-func NewPacketReader(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 {
@@ -284,10 +284,15 @@ 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
+		if UDPOverride.Address != nil || UDPOverride.Port != 0 || DialDest.Address.Family().IsDomain() {
+			isAddrChanged = true
+		}
 		return &PacketReader{
 			PacketConnWrapper: c,
 			Counter:           counter,
+			IsAddrChanged:     isAddrChanged,
 		}
 	}
 	return &buf.PacketReader{Reader: conn}
@@ -296,6 +301,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) {
@@ -307,10 +313,14 @@ 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 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),
+			Port:    net.Port(d.(*net.UDPAddr).Port),
+			Network: net.Network_UDP,
+		}
 	}
 	if r.Counter != nil {
 		r.Counter.Add(int64(n))