diff --git a/constant/metadata.go b/constant/metadata.go index ec7c0bde..059e41bf 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -89,11 +89,7 @@ type Metadata struct { } func (m *Metadata) RemoteAddress() string { - if m.DstIP.IsValid() { - return net.JoinHostPort(m.DstIP.String(), m.DstPort) - } else { - return net.JoinHostPort(m.String(), m.DstPort) - } + return net.JoinHostPort(m.String(), m.DstPort) } func (m *Metadata) SourceAddress() string { diff --git a/listener/tun/ipstack/gvisor/handler.go b/listener/tun/ipstack/gvisor/handler.go index 8c43a64d..8d93ce3a 100644 --- a/listener/tun/ipstack/gvisor/handler.go +++ b/listener/tun/ipstack/gvisor/handler.go @@ -16,16 +16,17 @@ import ( "github.com/Dreamacro/clash/transport/socks5" ) -var _ adapter.Handler = (*GVHandler)(nil) +var _ adapter.Handler = (*gvHandler)(nil) -type GVHandler struct { - DNSAdds []netip.AddrPort +type gvHandler struct { + gateway netip.Addr + dnsHijack []netip.AddrPort - TCPIn chan<- C.ConnContext - UDPIn chan<- *inbound.PacketAdapter + tcpIn chan<- C.ConnContext + udpIn chan<- *inbound.PacketAdapter } -func (gh *GVHandler) HandleTCP(tunConn adapter.TCPConn) { +func (gh *gvHandler) HandleTCP(tunConn adapter.TCPConn) { id := tunConn.ID() rAddr := &net.TCPAddr{ @@ -34,11 +35,11 @@ func (gh *GVHandler) HandleTCP(tunConn adapter.TCPConn) { Zone: "", } - addrPort := netip.AddrPortFrom(nnip.IpToAddr(rAddr.IP), id.LocalPort) + rAddrPort := netip.AddrPortFrom(nnip.IpToAddr(rAddr.IP), id.LocalPort) - if D.ShouldHijackDns(gh.DNSAdds, addrPort) { + if D.ShouldHijackDns(gh.dnsHijack, rAddrPort) { go func() { - log.Debugln("[TUN] hijack dns tcp: %s", addrPort.String()) + log.Debugln("[TUN] hijack dns tcp: %s", rAddrPort.String()) buf := pool.Get(pool.UDPBufferSize) defer func() { @@ -77,10 +78,10 @@ func (gh *GVHandler) HandleTCP(tunConn adapter.TCPConn) { return } - gh.TCPIn <- inbound.NewSocket(socks5.ParseAddrToSocksAddr(rAddr), tunConn, C.TUN) + gh.tcpIn <- inbound.NewSocket(socks5.ParseAddrToSocksAddr(rAddr), tunConn, C.TUN) } -func (gh *GVHandler) HandleUDP(tunConn adapter.UDPConn) { +func (gh *gvHandler) HandleUDP(tunConn adapter.UDPConn) { id := tunConn.ID() rAddr := &net.UDPAddr{ @@ -89,7 +90,13 @@ func (gh *GVHandler) HandleUDP(tunConn adapter.UDPConn) { Zone: "", } - addrPort := netip.AddrPortFrom(nnip.IpToAddr(rAddr.IP), id.LocalPort) + rAddrPort := netip.AddrPortFrom(nnip.IpToAddr(rAddr.IP), id.LocalPort) + + if rAddrPort.Addr() == gh.gateway { + _ = tunConn.Close() + return + } + target := socks5.ParseAddrToSocksAddr(rAddr) go func() { @@ -104,7 +111,7 @@ func (gh *GVHandler) HandleUDP(tunConn adapter.UDPConn) { payload := buf[:n] - if D.ShouldHijackDns(gh.DNSAdds, addrPort) { + if D.ShouldHijackDns(gh.dnsHijack, rAddrPort) { go func() { defer func() { _ = pool.Put(buf) @@ -130,7 +137,7 @@ func (gh *GVHandler) HandleUDP(tunConn adapter.UDPConn) { } select { - case gh.UDPIn <- inbound.NewPacket(target, gvPacket, C.TUN): + case gh.udpIn <- inbound.NewPacket(target, gvPacket, C.TUN): default: } } diff --git a/listener/tun/ipstack/gvisor/stack.go b/listener/tun/ipstack/gvisor/stack.go index c762e6a2..1307bc71 100644 --- a/listener/tun/ipstack/gvisor/stack.go +++ b/listener/tun/ipstack/gvisor/stack.go @@ -2,9 +2,12 @@ package gvisor import ( + "net/netip" + + "github.com/Dreamacro/clash/adapter/inbound" + C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/listener/tun/device" "github.com/Dreamacro/clash/listener/tun/ipstack" - "github.com/Dreamacro/clash/listener/tun/ipstack/gvisor/adapter" "github.com/Dreamacro/clash/listener/tun/ipstack/gvisor/option" "gvisor.dev/gvisor/pkg/tcpip" @@ -34,7 +37,7 @@ func (s *gvStack) Close() error { } // New allocates a new *gvStack with given options. -func New(device device.Device, handler adapter.Handler, opts ...option.Option) (ipstack.Stack, error) { +func New(device device.Device, dnsHijack []netip.AddrPort, tunAddress netip.Prefix, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter, opts ...option.Option) (ipstack.Stack, error) { s := &gvStack{ Stack: stack.New(stack.Options{ NetworkProtocols: []stack.NetworkProtocolFactory{ @@ -52,6 +55,13 @@ func New(device device.Device, handler adapter.Handler, opts ...option.Option) ( device: device, } + handler := &gvHandler{ + gateway: tunAddress.Masked().Addr().Next(), + dnsHijack: dnsHijack, + tcpIn: tcpIn, + udpIn: udpIn, + } + // Generate unique NIC id. nicID := tcpip.NICID(s.Stack.UniqueID()) diff --git a/listener/tun/ipstack/system/stack.go b/listener/tun/ipstack/system/stack.go index 16fd37d0..92751d36 100644 --- a/listener/tun/ipstack/system/stack.go +++ b/listener/tun/ipstack/system/stack.go @@ -169,7 +169,7 @@ func New(device device.Device, dnsHijack []netip.AddrPort, tunAddress netip.Pref rAddrPort := netip.AddrPortFrom(nnip.IpToAddr(rAddr.IP), uint16(rAddr.Port)) - if rAddrPort.Addr().IsLoopback() { + if rAddrPort.Addr().IsLoopback() || rAddrPort.Addr() == gateway { _ = pool.Put(buf) continue diff --git a/listener/tun/tun_adapter.go b/listener/tun/tun_adapter.go index 3cd20da2..eed95333 100644 --- a/listener/tun/tun_adapter.go +++ b/listener/tun/tun_adapter.go @@ -67,13 +67,7 @@ func New(tunConf *config.Tun, dnsConf *config.DNS, tcpIn chan<- C.ConnContext, u return nil, fmt.Errorf("can't attach endpoint to tun: %w", err) } - tunStack, err = gvisor.New(tunDevice, - &gvisor.GVHandler{ - DNSAdds: tunConf.DNSHijack, - TCPIn: tcpIn, UDPIn: udpIn, - }, - option.WithDefault(), - ) + tunStack, err = gvisor.New(tunDevice, tunConf.DNSHijack, tunAddress, tcpIn, udpIn, option.WithDefault()) if err != nil { _ = tunDevice.Close()