diff --git a/adapter/inbound/addition.go b/adapter/inbound/addition.go index 2754ee1e2..df03b84a3 100644 --- a/adapter/inbound/addition.go +++ b/adapter/inbound/addition.go @@ -8,8 +8,10 @@ import ( type Addition func(metadata *C.Metadata) -func (a Addition) Apply(metadata *C.Metadata) { - a(metadata) +func ApplyAdditions(metadata *C.Metadata, additions ...Addition) { + for _, addition := range additions { + addition(metadata) + } } func WithInName(name string) Addition { @@ -36,26 +38,28 @@ func WithSpecialProxy(specialProxy string) Addition { } } -func WithSrcAddr(addr net.Addr) Addition { +func WithDstAddr(addr net.Addr) Addition { return func(metadata *C.Metadata) { - addrPort := parseAddr(addr) - metadata.SrcIP = addrPort.Addr().Unmap() - metadata.SrcPort = addrPort.Port() + _ = metadata.SetRemoteAddr(addr) } } -func WithDstAddr(addr net.Addr) Addition { +func WithSrcAddr(addr net.Addr) Addition { return func(metadata *C.Metadata) { - addrPort := parseAddr(addr) - metadata.DstIP = addrPort.Addr().Unmap() - metadata.DstPort = addrPort.Port() + m := C.Metadata{} + if err := m.SetRemoteAddr(addr);err ==nil{ + metadata.SrcIP = m.DstIP + metadata.SrcPort = m.DstPort + } } } func WithInAddr(addr net.Addr) Addition { return func(metadata *C.Metadata) { - addrPort := parseAddr(addr) - metadata.InIP = addrPort.Addr().Unmap() - metadata.InPort = addrPort.Port() + m := C.Metadata{} + if err := m.SetRemoteAddr(addr);err ==nil{ + metadata.InIP = m.DstIP + metadata.InPort = m.DstPort + } } } diff --git a/adapter/inbound/auth.go b/adapter/inbound/auth.go index 93c56c994..4022659f3 100644 --- a/adapter/inbound/auth.go +++ b/adapter/inbound/auth.go @@ -3,6 +3,8 @@ package inbound import ( "net" "net/netip" + + C "github.com/Dreamacro/clash/constant" ) var skipAuthPrefixes []netip.Prefix @@ -16,9 +18,25 @@ func SkipAuthPrefixes() []netip.Prefix { } func SkipAuthRemoteAddr(addr net.Addr) bool { - if addrPort := parseAddr(addr); addrPort.IsValid() { + m := C.Metadata{} + if err := m.SetRemoteAddr(addr); err != nil { + return false + } + return skipAuth(m.AddrPort().Addr()) +} + +func SkipAuthRemoteAddress(addr string) bool { + m := C.Metadata{} + if err := m.SetRemoteAddress(addr); err != nil { + return false + } + return skipAuth(m.AddrPort().Addr()) +} + +func skipAuth(addr netip.Addr) bool { + if addr.IsValid() { for _, prefix := range skipAuthPrefixes { - if prefix.Contains(addrPort.Addr().Unmap()) { + if prefix.Contains(addr.Unmap()) { return true } } diff --git a/adapter/inbound/http.go b/adapter/inbound/http.go index 153766061..2a6050e58 100644 --- a/adapter/inbound/http.go +++ b/adapter/inbound/http.go @@ -12,9 +12,7 @@ func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Ad metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = C.HTTP - additions = append(additions, WithSrcAddr(source), WithInAddr(conn.LocalAddr())) - for _, addition := range additions { - addition.Apply(metadata) - } + ApplyAdditions(metadata, WithSrcAddr(source), WithInAddr(conn.LocalAddr())) + ApplyAdditions(metadata, additions...) return conn, metadata } diff --git a/adapter/inbound/https.go b/adapter/inbound/https.go index 7353fe599..891ac9e7c 100644 --- a/adapter/inbound/https.go +++ b/adapter/inbound/https.go @@ -11,9 +11,7 @@ import ( func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) (net.Conn, *C.Metadata) { metadata := parseHTTPAddr(request) metadata.Type = C.HTTPS - additions = append(additions, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr())) - for _, addition := range additions { - addition.Apply(metadata) - } + ApplyAdditions(metadata, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr())) + ApplyAdditions(metadata, additions...) return conn, metadata } diff --git a/adapter/inbound/packet.go b/adapter/inbound/packet.go index f211f7a51..0e3f6c486 100644 --- a/adapter/inbound/packet.go +++ b/adapter/inbound/packet.go @@ -10,13 +10,11 @@ func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions metadata := parseSocksAddr(target) metadata.NetWork = C.UDP metadata.Type = source - additions = append(additions, WithSrcAddr(packet.LocalAddr())) + ApplyAdditions(metadata, WithSrcAddr(packet.LocalAddr())) if p, ok := packet.(C.UDPPacketInAddr); ok { - additions = append(additions, WithInAddr(p.InAddr())) - } - for _, addition := range additions { - addition.Apply(metadata) + ApplyAdditions(metadata, WithInAddr(p.InAddr())) } + ApplyAdditions(metadata, additions...) return packet, metadata } diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index dbe1712d9..21cb490b7 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -12,10 +12,7 @@ func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Ad metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = source - additions = append(additions, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr())) - for _, addition := range additions { - addition.Apply(metadata) - } - + ApplyAdditions(metadata, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr())) + ApplyAdditions(metadata, additions...) return conn, metadata } diff --git a/adapter/inbound/util.go b/adapter/inbound/util.go index e4d2630d1..acae7c3e1 100644 --- a/adapter/inbound/util.go +++ b/adapter/inbound/util.go @@ -61,31 +61,3 @@ func parseHTTPAddr(request *http.Request) *C.Metadata { return metadata } - -func parseAddr(addr net.Addr) netip.AddrPort { - // Filter when net.Addr interface is nil - if addr == nil { - return netip.AddrPort{} - } - if addr, ok := addr.(interface{ RawAddr() net.Addr }); ok { - if rawAddr := addr.RawAddr(); rawAddr != nil { - return parseAddr(rawAddr) - } - } - if addr, ok := addr.(interface{ AddrPort() netip.AddrPort }); ok { - return addr.AddrPort() - } - addrStr := addr.String() - host, port, err := net.SplitHostPort(addrStr) - if err != nil { - return netip.AddrPort{} - } - - var uint16Port uint16 - if port, err := strconv.ParseUint(port, 10, 16); err == nil { - uint16Port = uint16(port) - } - - ip, _ := netip.ParseAddr(host) - return netip.AddrPortFrom(ip, uint16Port) -} diff --git a/component/proxydialer/proxydialer.go b/component/proxydialer/proxydialer.go index 83010f967..2d14abaef 100644 --- a/component/proxydialer/proxydialer.go +++ b/component/proxydialer/proxydialer.go @@ -70,10 +70,7 @@ func (p proxyDialer) DialContext(ctx context.Context, network, address string) ( } func (p proxyDialer) ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error) { - currentMeta := &C.Metadata{Type: C.INNER} - if err := currentMeta.SetRemoteAddress(rAddrPort.String()); err != nil { - return nil, err - } + currentMeta := &C.Metadata{Type: C.INNER, DstIP: rAddrPort.Addr(), DstPort: rAddrPort.Port()} return p.listenPacket(ctx, currentMeta) } diff --git a/constant/metadata.go b/constant/metadata.go index 704789113..5f4722054 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -240,6 +240,34 @@ func (m *Metadata) Valid() bool { return m.Host != "" || m.DstIP.IsValid() } +func (m *Metadata) SetRemoteAddr(addr net.Addr) error { + if addr == nil { + return nil + } + if rawAddr, ok := addr.(interface{ RawAddr() net.Addr }); ok { + if rawAddr := rawAddr.RawAddr(); rawAddr != nil { + if err := m.SetRemoteAddr(rawAddr); err == nil { + return nil + } + } + } + if addr, ok := addr.(interface{ AddrPort() netip.AddrPort }); ok { // *net.TCPAddr, *net.UDPAddr, M.Socksaddr + if addrPort := addr.AddrPort(); addrPort.Port() != 0 { + m.DstPort = addrPort.Port() + if addrPort.IsValid() { // sing's M.Socksaddr maybe return an invalid AddrPort if it's a DomainName + m.DstIP = addrPort.Addr().Unmap() + return nil + } else { + if addr, ok := addr.(interface{ AddrString() string }); ok { // must be sing's M.Socksaddr + m.Host = addr.AddrString() // actually is M.Socksaddr.Fqdn + return nil + } + } + } + } + return m.SetRemoteAddress(addr.String()) +} + func (m *Metadata) SetRemoteAddress(rawAddress string) error { host, port, err := net.SplitHostPort(rawAddress) if err != nil { diff --git a/listener/http/proxy.go b/listener/http/proxy.go index 173bb64a0..44ff04c71 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -100,7 +100,7 @@ func HandleConn(c net.Conn, tunnel C.Tunnel, cache *cache.LruCache[string, bool] func authenticate(request *http.Request, cache *cache.LruCache[string, bool]) *http.Response { authenticator := authStore.Authenticator() - if inbound.SkipAuthRemoteAddr(N.NewCustomAddr("", request.RemoteAddr, nil)) { + if inbound.SkipAuthRemoteAddress(request.RemoteAddr) { authenticator = nil } if authenticator != nil { diff --git a/listener/sing/context.go b/listener/sing/context.go index 32b2a161a..4204757ac 100644 --- a/listener/sing/context.go +++ b/listener/sing/context.go @@ -17,35 +17,15 @@ func WithAdditions(ctx context.Context, additions ...inbound.Addition) context.C return context.WithValue(ctx, ctxKeyAdditions, additions) } -func getAdditions(ctx context.Context) []inbound.Addition { +func getAdditions(ctx context.Context) (additions []inbound.Addition) { if v := ctx.Value(ctxKeyAdditions); v != nil { if a, ok := v.([]inbound.Addition); ok { - return a + additions = a } } - return nil -} - -func combineAdditions(ctx context.Context, additions []inbound.Addition, extraAdditions ...inbound.Addition) []inbound.Addition { - additionsCloned := false - if ctxAdditions := getAdditions(ctx); len(ctxAdditions) > 0 { - additions = slices.Clone(additions) - additionsCloned = true - additions = append(additions, ctxAdditions...) - } if user, ok := auth.UserFromContext[string](ctx); ok { - if !additionsCloned { - additions = slices.Clone(additions) - additionsCloned = true - } + additions = slices.Clone(additions) additions = append(additions, inbound.WithInUser(user)) } - if len(extraAdditions) > 0 { - if !additionsCloned { - additions = slices.Clone(additions) - additionsCloned = true - } - additions = append(additions, extraAdditions...) - } - return additions + return } diff --git a/listener/sing/sing.go b/listener/sing/sing.go index d03bebb1d..1837951d1 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -92,12 +92,10 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta cMetadata := &C.Metadata{ NetWork: C.TCP, Type: h.Type, - Host: metadata.Destination.Fqdn, - } - additions := combineAdditions(ctx, h.Additions, inbound.WithDstAddr(metadata.Destination), inbound.WithSrcAddr(metadata.Source), inbound.WithInAddr(conn.LocalAddr())) - for _, addition := range additions { - addition.Apply(cMetadata) } + inbound.ApplyAdditions(cMetadata, inbound.WithDstAddr(metadata.Destination), inbound.WithSrcAddr(metadata.Source), inbound.WithInAddr(conn.LocalAddr())) + inbound.ApplyAdditions(cMetadata, getAdditions(ctx)...) + inbound.ApplyAdditions(cMetadata, h.Additions...) h.Tunnel.HandleTCPConn(conn, cMetadata) // this goroutine must exit after conn unused return nil @@ -155,12 +153,10 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. cMetadata := &C.Metadata{ NetWork: C.UDP, Type: h.Type, - Host: dest.Fqdn, - } - additions := combineAdditions(ctx, h.Additions, inbound.WithDstAddr(dest), inbound.WithSrcAddr(metadata.Source), inbound.WithInAddr(conn.LocalAddr())) - for _, addition := range additions { - addition.Apply(cMetadata) } + inbound.ApplyAdditions(cMetadata, inbound.WithDstAddr(dest), inbound.WithSrcAddr(metadata.Source), inbound.WithInAddr(conn.LocalAddr())) + inbound.ApplyAdditions(cMetadata, getAdditions(ctx)...) + inbound.ApplyAdditions(cMetadata, h.Additions...) h.Tunnel.HandleUDPPacket(cPacket, cMetadata) } diff --git a/listener/tunnel/tcp.go b/listener/tunnel/tcp.go index dd2059db3..9fca14dd7 100644 --- a/listener/tunnel/tcp.go +++ b/listener/tunnel/tcp.go @@ -36,9 +36,7 @@ func (l *Listener) Close() error { func (l *Listener) handleTCP(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { N.TCPKeepAlive(conn) - conn, metadata := inbound.NewSocket(l.target, conn, C.TUNNEL, additions...) - metadata.SpecialProxy = l.proxy - tunnel.HandleTCPConn(conn, metadata) + tunnel.HandleTCPConn(inbound.NewSocket(l.target, conn, C.TUNNEL, additions...)) } func New(addr, target, proxy string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { @@ -59,6 +57,10 @@ func New(addr, target, proxy string, tunnel C.Tunnel, additions ...inbound.Addit addr: addr, } + if proxy != "" { + additions = append([]inbound.Addition{inbound.WithSpecialProxy(proxy)}, additions...) + } + go func() { for { c, err := l.Accept() diff --git a/listener/tunnel/udp.go b/listener/tunnel/udp.go index 38b779c42..00d616632 100644 --- a/listener/tunnel/udp.go +++ b/listener/tunnel/udp.go @@ -51,6 +51,11 @@ func NewUDP(addr, target, proxy string, tunnel C.Tunnel, additions ...inbound.Ad proxy: proxy, addr: addr, } + + if proxy != "" { + additions = append([]inbound.Addition{inbound.WithSpecialProxy(proxy)}, additions...) + } + go func() { for { buf := pool.Get(pool.UDPBufferSize) @@ -76,7 +81,5 @@ func (l *PacketConn) handleUDP(pc net.PacketConn, tunnel C.Tunnel, buf []byte, a payload: buf, } - packet, metadata := inbound.NewPacket(l.target, cPacket, C.TUNNEL, additions...) - metadata.SpecialProxy = l.proxy - tunnel.HandleUDPPacket(packet, metadata) + tunnel.HandleUDPPacket(inbound.NewPacket(l.target, cPacket, C.TUNNEL, additions...)) }