diff --git a/dns/util.go b/dns/util.go index 3f7700ea..8259f22e 100644 --- a/dns/util.go +++ b/dns/util.go @@ -28,6 +28,11 @@ const ( ) func putMsgToCache(c *cache.LruCache[string, *D.Msg], key string, msg *D.Msg) { + // skip dns cache for acme challenge + if q := msg.Question[0]; q.Qtype == D.TypeTXT && strings.HasPrefix(q.Name, "_acme-challenge") { + log.Debugln("[DNS] dns cache ignored because of acme challenge for: %s", q.Name) + return + } var ttl uint32 switch { case len(msg.Answer) != 0: diff --git a/listener/redir/tcp_linux.go b/listener/redir/tcp_linux.go index 949ca717..b65c34ee 100644 --- a/listener/redir/tcp_linux.go +++ b/listener/redir/tcp_linux.go @@ -1,12 +1,16 @@ package redir import ( + "encoding/binary" "errors" "net" + "net/netip" "syscall" "unsafe" "github.com/Dreamacro/clash/transport/socks5" + + "golang.org/x/sys/unix" ) const ( @@ -25,44 +29,36 @@ func parserPacket(conn net.Conn) (socks5.Addr, error) { return nil, err } - var addr socks5.Addr + var addr netip.AddrPort rc.Control(func(fd uintptr) { - addr, err = getorigdst(fd) - if err != nil { + if ip4 := c.LocalAddr().(*net.TCPAddr).IP.To4(); ip4 != nil { + addr, err = getorigdst(fd) + } else { addr, err = getorigdst6(fd) } }) - return addr, err + return socks5.AddrFromStdAddrPort(addr), err } // Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c -func getorigdst(fd uintptr) (socks5.Addr, error) { - raw := syscall.RawSockaddrInet4{} - siz := uint32(unsafe.Sizeof(raw)) - if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil { - return nil, err +func getorigdst(fd uintptr) (netip.AddrPort, error) { + addr := unix.RawSockaddrInet4{} + size := uint32(unsafe.Sizeof(addr)) + if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(&size)), 0); err != nil { + return netip.AddrPort{}, err } - - addr := make([]byte, 1+net.IPv4len+2) - addr[0] = socks5.AtypIPv4 - copy(addr[1:1+net.IPv4len], raw.Addr[:]) - port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // big-endian - addr[1+net.IPv4len], addr[1+net.IPv4len+1] = port[0], port[1] - return addr, nil + port := binary.BigEndian.Uint16((*(*[2]byte)(unsafe.Pointer(&addr.Port)))[:]) + return netip.AddrPortFrom(netip.AddrFrom4(addr.Addr), port), nil } -func getorigdst6(fd uintptr) (socks5.Addr, error) { - raw := syscall.RawSockaddrInet6{} - siz := uint32(unsafe.Sizeof(raw)) - if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil { - return nil, err +func getorigdst6(fd uintptr) (netip.AddrPort, error) { + addr := unix.RawSockaddrInet6{} + size := uint32(unsafe.Sizeof(addr)) + if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(&size)), 0); err != nil { + return netip.AddrPort{}, err } - addr := make([]byte, 1+net.IPv6len+2) - addr[0] = socks5.AtypIPv6 - copy(addr[1:1+net.IPv6len], raw.Addr[:]) - port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // big-endian - addr[1+net.IPv6len], addr[1+net.IPv6len+1] = port[0], port[1] - return addr, nil + port := binary.BigEndian.Uint16((*(*[2]byte)(unsafe.Pointer(&addr.Port)))[:]) + return netip.AddrPortFrom(netip.AddrFrom16(addr.Addr), port), nil }