From a6c144038b9eef39d87a1b84e71af2a0a75043a7 Mon Sep 17 00:00:00 2001
From: Dreamacro <8615343+Dreamacro@users.noreply.github.com>
Date: Thu, 22 Dec 2022 12:00:56 +0800
Subject: [PATCH 1/6] Chore: improve redir getorigdst
---
listener/redir/tcp_linux.go | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/listener/redir/tcp_linux.go b/listener/redir/tcp_linux.go
index c4a47d8e..a8b6d967 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,27 +29,22 @@ 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)
})
- 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
}
From d8ac82be36303e5e9e351e0a1281bd9886f54788 Mon Sep 17 00:00:00 2001
From: igoogolx <27353191+igoogolx@users.noreply.github.com>
Date: Thu, 22 Dec 2022 12:09:24 +0800
Subject: [PATCH 2/6] Fix: broken build badge (#2470)
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 6dff747b..0f1a05df 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
-
+
From cdc7d449a606f83b814ee0df3674749b94b285a0 Mon Sep 17 00:00:00 2001
From: wwqgtxx
Date: Thu, 22 Dec 2022 12:42:38 +0800
Subject: [PATCH 3/6] Fix: safeConnClose not working (#2463)
---
adapter/outbound/http.go | 4 +++-
adapter/outbound/shadowsocks.go | 4 +++-
adapter/outbound/shadowsocksr.go | 4 +++-
adapter/outbound/snell.go | 4 +++-
adapter/outbound/socks5.go | 8 ++++++--
adapter/outbound/trojan.go | 12 +++++++++---
adapter/outbound/vmess.go | 16 ++++++++++++----
7 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/adapter/outbound/http.go b/adapter/outbound/http.go
index 480710dc..b7425100 100644
--- a/adapter/outbound/http.go
+++ b/adapter/outbound/http.go
@@ -63,7 +63,9 @@ func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata, opts ...di
}
tcpKeepAlive(c)
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = h.StreamConn(c, metadata)
if err != nil {
diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go
index 6ed78050..e1878dfa 100644
--- a/adapter/outbound/shadowsocks.go
+++ b/adapter/outbound/shadowsocks.go
@@ -81,7 +81,9 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, op
}
tcpKeepAlive(c)
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = ss.StreamConn(c, metadata)
return NewConn(c, ss), err
diff --git a/adapter/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go
index 57ef5604..4542eebc 100644
--- a/adapter/outbound/shadowsocksr.go
+++ b/adapter/outbound/shadowsocksr.go
@@ -66,7 +66,9 @@ func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata,
}
tcpKeepAlive(c)
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = ssr.StreamConn(c, metadata)
return NewConn(c, ssr), err
diff --git a/adapter/outbound/snell.go b/adapter/outbound/snell.go
index 07f3d89d..ab791908 100644
--- a/adapter/outbound/snell.go
+++ b/adapter/outbound/snell.go
@@ -80,7 +80,9 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
}
tcpKeepAlive(c)
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = s.StreamConn(c, metadata)
return NewConn(c, s), err
diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go
index 3269457d..4f816211 100644
--- a/adapter/outbound/socks5.go
+++ b/adapter/outbound/socks5.go
@@ -69,7 +69,9 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ..
}
tcpKeepAlive(c)
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = ss.StreamConn(c, metadata)
if err != nil {
@@ -95,7 +97,9 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
c = cc
}
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
tcpKeepAlive(c)
var user *socks5.User
diff --git a/adapter/outbound/trojan.go b/adapter/outbound/trojan.go
index 064cd3c2..fa549df0 100644
--- a/adapter/outbound/trojan.go
+++ b/adapter/outbound/trojan.go
@@ -109,7 +109,9 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
}
tcpKeepAlive(c)
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = t.StreamConn(c, metadata)
if err != nil {
@@ -129,13 +131,17 @@ func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
if err != nil {
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
}
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
} else {
c, err = dialer.DialContext(ctx, "tcp", t.addr, t.Base.DialOptions(opts...)...)
if err != nil {
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
}
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
tcpKeepAlive(c)
c, err = t.plainStream(c)
if err != nil {
diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go
index aaa9105d..8fa74fbd 100644
--- a/adapter/outbound/vmess.go
+++ b/adapter/outbound/vmess.go
@@ -195,7 +195,9 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
if err != nil {
return nil, err
}
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = v.client.StreamConn(c, parseVmessAddr(metadata))
if err != nil {
@@ -210,7 +212,9 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
}
tcpKeepAlive(c)
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = v.StreamConn(c, metadata)
return NewConn(c, v), err
@@ -234,7 +238,9 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
if err != nil {
return nil, err
}
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = v.client.StreamConn(c, parseVmessAddr(metadata))
} else {
@@ -243,7 +249,9 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
}
tcpKeepAlive(c)
- defer safeConnClose(c, err)
+ defer func(c net.Conn) {
+ safeConnClose(c, err)
+ }(c)
c, err = v.StreamConn(c, metadata)
}
From 4a579177833f6cec6014d8894cf985f6689b5f26 Mon Sep 17 00:00:00 2001
From: ALICE
Date: Thu, 22 Dec 2022 13:30:23 +0800
Subject: [PATCH 4/6] Chore: skip cache acme challenge dns msg (#2469)
---
dns/util.go | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/dns/util.go b/dns/util.go
index df3a3331..05c734e8 100644
--- a/dns/util.go
+++ b/dns/util.go
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net"
+ "strings"
"time"
"github.com/Dreamacro/clash/common/cache"
@@ -16,6 +17,12 @@ import (
)
func putMsgToCache(c *cache.LruCache, 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:
From fbca37c42b444429c4841983306553ffa2109cc0 Mon Sep 17 00:00:00 2001
From: embeddedlove <118641459+embeddedlove@users.noreply.github.com>
Date: Thu, 22 Dec 2022 19:25:30 +0800
Subject: [PATCH 5/6] Feature: REDIRECT support IPv6 (#2473)
---
listener/redir/tcp_linux.go | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/listener/redir/tcp_linux.go b/listener/redir/tcp_linux.go
index a8b6d967..b65c34ee 100644
--- a/listener/redir/tcp_linux.go
+++ b/listener/redir/tcp_linux.go
@@ -32,7 +32,11 @@ func parserPacket(conn net.Conn) (socks5.Addr, error) {
var addr netip.AddrPort
rc.Control(func(fd uintptr) {
- addr, err = getorigdst(fd)
+ if ip4 := c.LocalAddr().(*net.TCPAddr).IP.To4(); ip4 != nil {
+ addr, err = getorigdst(fd)
+ } else {
+ addr, err = getorigdst6(fd)
+ }
})
return socks5.AddrFromStdAddrPort(addr), err
@@ -48,3 +52,13 @@ func getorigdst(fd uintptr) (netip.AddrPort, error) {
port := binary.BigEndian.Uint16((*(*[2]byte)(unsafe.Pointer(&addr.Port)))[:])
return netip.AddrPortFrom(netip.AddrFrom4(addr.Addr), port), nil
}
+
+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
+ }
+ port := binary.BigEndian.Uint16((*(*[2]byte)(unsafe.Pointer(&addr.Port)))[:])
+ return netip.AddrPortFrom(netip.AddrFrom16(addr.Addr), port), nil
+}
From 2301b909d25587f2846f049363af5b9b4769d098 Mon Sep 17 00:00:00 2001
From: Dreamacro <8615343+Dreamacro@users.noreply.github.com>
Date: Sat, 31 Dec 2022 16:30:29 +0800
Subject: [PATCH 6/6] Fix: immediately update provider when modtime too old
---
adapter/provider/fetcher.go | 52 +++++++++++++++++++++++--------------
1 file changed, 32 insertions(+), 20 deletions(-)
diff --git a/adapter/provider/fetcher.go b/adapter/provider/fetcher.go
index 4a7be8b1..297e82f7 100644
--- a/adapter/provider/fetcher.go
+++ b/adapter/provider/fetcher.go
@@ -21,6 +21,7 @@ type parser = func([]byte) (any, error)
type fetcher struct {
name string
vehicle types.Vehicle
+ interval time.Duration
updatedAt *time.Time
ticker *time.Ticker
done chan struct{}
@@ -39,15 +40,17 @@ func (f *fetcher) VehicleType() types.VehicleType {
func (f *fetcher) Initial() (any, error) {
var (
- buf []byte
- err error
- isLocal bool
+ buf []byte
+ err error
+ isLocal bool
+ immediatelyUpdate bool
)
if stat, fErr := os.Stat(f.vehicle.Path()); fErr == nil {
buf, err = os.ReadFile(f.vehicle.Path())
modTime := stat.ModTime()
f.updatedAt = &modTime
isLocal = true
+ immediatelyUpdate = time.Since(modTime) > f.interval
} else {
buf, err = f.vehicle.Read()
}
@@ -86,7 +89,7 @@ func (f *fetcher) Initial() (any, error) {
// pull proxies automatically
if f.ticker != nil {
- go f.pullLoop()
+ go f.pullLoop(immediatelyUpdate)
}
return proxies, nil
@@ -130,25 +133,33 @@ func (f *fetcher) Destroy() error {
return nil
}
-func (f *fetcher) pullLoop() {
+func (f *fetcher) pullLoop(immediately bool) {
+ update := func() {
+ elm, same, err := f.Update()
+ if err != nil {
+ log.Warnln("[Provider] %s pull error: %s", f.Name(), err.Error())
+ return
+ }
+
+ if same {
+ log.Debugln("[Provider] %s's proxies doesn't change", f.Name())
+ return
+ }
+
+ log.Infoln("[Provider] %s's proxies update", f.Name())
+ if f.onUpdate != nil {
+ f.onUpdate(elm)
+ }
+ }
+
+ if immediately {
+ update()
+ }
+
for {
select {
case <-f.ticker.C:
- elm, same, err := f.Update()
- if err != nil {
- log.Warnln("[Provider] %s pull error: %s", f.Name(), err.Error())
- continue
- }
-
- if same {
- log.Debugln("[Provider] %s's proxies doesn't change", f.Name())
- continue
- }
-
- log.Infoln("[Provider] %s's proxies update", f.Name())
- if f.onUpdate != nil {
- f.onUpdate(elm)
- }
+ update()
case <-f.done:
f.ticker.Stop()
return
@@ -178,6 +189,7 @@ func newFetcher(name string, interval time.Duration, vehicle types.Vehicle, pars
name: name,
ticker: ticker,
vehicle: vehicle,
+ interval: interval,
parser: parser,
done: make(chan struct{}, 1),
onUpdate: onUpdate,