Chore: merge branch 'with-tun' into plus-pro
This commit is contained in:
54
tunnel/statistic/sniffing.go
Normal file
54
tunnel/statistic/sniffing.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package statistic
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Dreamacro/clash/common/snifer/tls"
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
|
||||
"go.uber.org/atomic"
|
||||
)
|
||||
|
||||
type sniffing struct {
|
||||
C.Conn
|
||||
|
||||
metadata *C.Metadata
|
||||
totalWrite *atomic.Uint64
|
||||
}
|
||||
|
||||
func (r *sniffing) Read(b []byte) (int, error) {
|
||||
return r.Conn.Read(b)
|
||||
}
|
||||
|
||||
func (r *sniffing) Write(b []byte) (int, error) {
|
||||
if r.totalWrite.Load() < 128 && r.metadata.Host == "" && (r.metadata.DstPort == "443" || r.metadata.DstPort == "8443" || r.metadata.DstPort == "993" || r.metadata.DstPort == "465" || r.metadata.DstPort == "995") {
|
||||
header, err := tls.SniffTLS(b)
|
||||
if err != nil {
|
||||
// log.Errorln("Expect no error but actually %s %s:%s:%s", err.Error(), tt.Metadata.Host, tt.Metadata.DstIP.String(), tt.Metadata.DstPort)
|
||||
} else {
|
||||
resolver.InsertHostByIP(r.metadata.DstIP, header.Domain())
|
||||
log.Warnln("use sni update host: %s ip: %s", header.Domain(), r.metadata.DstIP.String())
|
||||
r.Conn.Close()
|
||||
return 0, errors.New("sni update, break current link to avoid leaks")
|
||||
}
|
||||
}
|
||||
|
||||
n, err := r.Conn.Write(b)
|
||||
r.totalWrite.Add(uint64(n))
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (r *sniffing) Close() error {
|
||||
return r.Conn.Close()
|
||||
}
|
||||
|
||||
func NewSniffing(conn C.Conn, metadata *C.Metadata) C.Conn {
|
||||
return &sniffing{
|
||||
Conn: conn,
|
||||
metadata: metadata,
|
||||
totalWrite: atomic.NewUint64(0),
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func (tt *tcpTracker) Close() error {
|
||||
return tt.Conn.Close()
|
||||
}
|
||||
|
||||
func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.Rule) *tcpTracker {
|
||||
func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.Rule) C.Conn {
|
||||
uuid, _ := uuid.NewV4()
|
||||
|
||||
t := &tcpTracker{
|
||||
@@ -80,7 +80,7 @@ func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.R
|
||||
}
|
||||
|
||||
manager.Join(t)
|
||||
return t
|
||||
return NewSniffing(t, metadata)
|
||||
}
|
||||
|
||||
type udpTracker struct {
|
||||
|
||||
@@ -27,6 +27,7 @@ var (
|
||||
udpQueue = make(chan *inbound.PacketAdapter, 200)
|
||||
natTable = nat.New()
|
||||
rules []C.Rule
|
||||
rewrites C.RewriteRule
|
||||
proxies = make(map[string]C.Proxy)
|
||||
providers map[string]provider.ProxyProvider
|
||||
configMux sync.RWMutex
|
||||
@@ -36,6 +37,9 @@ var (
|
||||
|
||||
// default timeout for UDP session
|
||||
udpTimeout = 60 * time.Second
|
||||
|
||||
// MitmOutbound mitm proxy adapter
|
||||
MitmOutbound C.ProxyAdapter
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -92,6 +96,18 @@ func SetMode(m TunnelMode) {
|
||||
mode = m
|
||||
}
|
||||
|
||||
// Rewrites return all rewrites
|
||||
func Rewrites() C.RewriteRule {
|
||||
return rewrites
|
||||
}
|
||||
|
||||
// UpdateRewrites handle update rewrites
|
||||
func UpdateRewrites(newRewrites C.RewriteRule) {
|
||||
configMux.Lock()
|
||||
rewrites = newRewrites
|
||||
configMux.Unlock()
|
||||
}
|
||||
|
||||
// processUDP starts a loop to handle udp packet
|
||||
func processUDP() {
|
||||
queue := udpQueue
|
||||
@@ -143,7 +159,7 @@ func preHandleMetadata(metadata *C.Metadata) error {
|
||||
metadata.DNSMode = C.DNSFakeIP
|
||||
} else if node := resolver.DefaultHosts.Search(host); node != nil {
|
||||
// redir-host should lookup the hosts
|
||||
metadata.DstIP = node.Data.(net.IP)
|
||||
metadata.DstIP = node.Data.AsSlice()
|
||||
}
|
||||
} else if resolver.IsFakeIP(metadata.DstIP) {
|
||||
return fmt.Errorf("fake DNS record %s missing", metadata.DstIP)
|
||||
@@ -286,14 +302,24 @@ func handleTCPConn(connCtx C.ConnContext) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
|
||||
defer cancel()
|
||||
if MitmOutbound != nil && metadata.Type != C.MITM {
|
||||
if remoteConn, err1 := MitmOutbound.DialContext(ctx, metadata); err1 == nil {
|
||||
remoteConn = statistic.NewSniffing(remoteConn, metadata)
|
||||
defer remoteConn.Close()
|
||||
|
||||
handleSocket(connCtx, remoteConn)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
proxy, rule, err := resolveMetadata(connCtx, metadata)
|
||||
if err != nil {
|
||||
log.Warnln("[Metadata] parse failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
|
||||
defer cancel()
|
||||
remoteConn, err := proxy.DialContext(ctx, metadata.Pure())
|
||||
if err != nil {
|
||||
if rule == nil {
|
||||
@@ -333,8 +359,7 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
|
||||
var resolved bool
|
||||
|
||||
if node := resolver.DefaultHosts.Search(metadata.Host); node != nil {
|
||||
ip := node.Data.(net.IP)
|
||||
metadata.DstIP = ip
|
||||
metadata.DstIP = node.Data.AsSlice()
|
||||
resolved = true
|
||||
}
|
||||
|
||||
@@ -388,8 +413,7 @@ func matchScript(metadata *C.Metadata) (C.Proxy, error) {
|
||||
defer configMux.RUnlock()
|
||||
|
||||
if node := resolver.DefaultHosts.Search(metadata.Host); node != nil {
|
||||
ip := node.Data.(net.IP)
|
||||
metadata.DstIP = ip
|
||||
metadata.DstIP = node.Data.AsSlice()
|
||||
}
|
||||
|
||||
adapter, err := S.CallPyMainFunction(metadata)
|
||||
|
||||
Reference in New Issue
Block a user