Direct/Freedom outbound: Block UDP responses that are come from ipsBlocked as well (#5952)

https://github.com/XTLS/Xray-core/pull/5947#issuecomment-4258980670

https://github.com/XTLS/Xray-core/pull/5952#issuecomment-4259324234

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
Meow
2026-04-18 06:56:27 +08:00
committed by GitHub
parent 31ab22c33d
commit d52f15060b

View File

@@ -290,7 +290,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
if destination.Network == net.Network_TCP { if destination.Network == net.Network_TCP {
reader = buf.NewReader(conn) reader = buf.NewReader(conn)
} else { } else {
reader = NewPacketReader(conn, UDPOverride, destination) reader = NewPacketReader(conn, UDPOverride, destination, blockedIPMatcher)
} }
if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil { if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to process response").Base(err) return errors.New("failed to process response").Base(err)
@@ -309,7 +309,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
return nil return nil
} }
func NewPacketReader(conn net.Conn, UDPOverride net.Destination, DialDest net.Destination) buf.Reader { func NewPacketReader(conn net.Conn, UDPOverride net.Destination, DialDest net.Destination, blockedIPMatcher geodata.IPMatcher) buf.Reader {
iConn := conn iConn := conn
statConn, ok := iConn.(*stat.CounterConnection) statConn, ok := iConn.(*stat.CounterConnection)
if ok { if ok {
@@ -328,6 +328,7 @@ func NewPacketReader(conn net.Conn, UDPOverride net.Destination, DialDest net.De
return &PacketReader{ return &PacketReader{
PacketConnWrapper: c, PacketConnWrapper: c,
Counter: counter, Counter: counter,
BlockedIPMatcher: blockedIPMatcher,
IsOverridden: isOverridden, IsOverridden: isOverridden,
InitUnchangedAddr: DialDest.Address, InitUnchangedAddr: DialDest.Address,
InitChangedAddr: net.DestinationFromAddr(conn.RemoteAddr()).Address, InitChangedAddr: net.DestinationFromAddr(conn.RemoteAddr()).Address,
@@ -339,6 +340,7 @@ func NewPacketReader(conn net.Conn, UDPOverride net.Destination, DialDest net.De
type PacketReader struct { type PacketReader struct {
*internet.PacketConnWrapper *internet.PacketConnWrapper
stats.Counter stats.Counter
BlockedIPMatcher geodata.IPMatcher
IsOverridden bool IsOverridden bool
InitUnchangedAddr net.Address InitUnchangedAddr net.Address
InitChangedAddr net.Address InitChangedAddr net.Address
@@ -346,30 +348,38 @@ type PacketReader struct {
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
b := buf.New() b := buf.New()
b.Resize(0, buf.Size) for {
n, d, err := r.PacketConnWrapper.ReadFrom(b.Bytes()) b.Resize(0, buf.Size)
if err != nil { n, d, err := r.PacketConnWrapper.ReadFrom(b.Bytes())
b.Release() if err != nil {
return nil, err b.Release()
} 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.IsOverridden {
address := net.IPAddress(d.(*net.UDPAddr).IP)
if r.InitChangedAddr == address {
address = r.InitUnchangedAddr
} }
b.UDP = &net.Destination{ b.Resize(0, int32(n))
Address: address,
Port: net.Port(d.(*net.UDPAddr).Port), udpAddr := d.(*net.UDPAddr)
Network: net.Network_UDP, sourceAddr := net.IPAddress(udpAddr.IP)
if isBlockedAddress(r.BlockedIPMatcher, sourceAddr) {
continue
} }
// 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.IsOverridden {
if r.InitChangedAddr == sourceAddr {
sourceAddr = r.InitUnchangedAddr
}
b.UDP = &net.Destination{
Address: sourceAddr,
Port: net.Port(udpAddr.Port),
Network: net.Network_UDP,
}
}
if r.Counter != nil {
r.Counter.Add(int64(n))
}
return buf.MultiBuffer{b}, nil
} }
if r.Counter != nil {
r.Counter.Add(int64(n))
}
return buf.MultiBuffer{b}, nil
} }
// DialDest means the dial target used in the dialer when creating conn // DialDest means the dial target used in the dialer when creating conn
@@ -468,10 +478,8 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
} }
} }
if isBlockedAddress(w.BlockedIPMatcher, b.UDP.Address) { if isBlockedAddress(w.BlockedIPMatcher, b.UDP.Address) {
blockedAddr := b.UDP.Address
b.Release() b.Release()
buf.ReleaseMulti(mb) continue
return errors.New("blocked target IP: ", blockedAddr).AtDebug()
} }
destAddr := b.UDP.RawNetAddr() destAddr := b.UDP.RawNetAddr()
if destAddr == nil { if destAddr == nil {