Chore: move sniffing logic into a single file & code style
This commit is contained in:
@@ -3,12 +3,13 @@ package adapter
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/queue"
|
"github.com/Dreamacro/clash/common/queue"
|
||||||
"github.com/Dreamacro/clash/component/dialer"
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
@@ -17,6 +18,9 @@ import (
|
|||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:linkname errCanceled net.errCanceled
|
||||||
|
var errCanceled error
|
||||||
|
|
||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
C.ProxyAdapter
|
C.ProxyAdapter
|
||||||
history *queue.Queue
|
history *queue.Queue
|
||||||
@@ -38,11 +42,7 @@ func (p *Proxy) Dial(metadata *C.Metadata) (C.Conn, error) {
|
|||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
conn, err := p.ProxyAdapter.DialContext(ctx, metadata, opts...)
|
conn, err := p.ProxyAdapter.DialContext(ctx, metadata, opts...)
|
||||||
wasCancel := false
|
p.alive.Store(err == nil || errors.Is(err, errCanceled))
|
||||||
if err != nil {
|
|
||||||
wasCancel = strings.Contains(err.Error(), "operation was canceled")
|
|
||||||
}
|
|
||||||
p.alive.Store(err == nil || wasCancel)
|
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,23 +50,6 @@ func initMMDB() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//func downloadGeoIP(path string) (err error) {
|
|
||||||
// resp, err := http.Get("https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geoip.dat")
|
|
||||||
// if err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// defer resp.Body.Close()
|
|
||||||
//
|
|
||||||
// f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// defer f.Close()
|
|
||||||
// _, err = io.Copy(f, resp.Body)
|
|
||||||
//
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
|
|
||||||
func downloadGeoSite(path string) (err error) {
|
func downloadGeoSite(path string) (err error) {
|
||||||
resp, err := http.Get("https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat")
|
resp, err := http.Get("https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -84,19 +67,6 @@ func downloadGeoSite(path string) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
//func initGeoIP() error {
|
|
||||||
// if _, err := os.Stat(C.Path.GeoIP()); os.IsNotExist(err) {
|
|
||||||
// log.Infoln("Can't find GeoIP.dat, start download")
|
|
||||||
// if err := downloadGeoIP(C.Path.GeoIP()); err != nil {
|
|
||||||
// return fmt.Errorf("can't download GeoIP.dat: %s", err.Error())
|
|
||||||
// }
|
|
||||||
// log.Infoln("Download GeoIP.dat finish")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
func initGeoSite() error {
|
func initGeoSite() error {
|
||||||
if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) {
|
if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) {
|
||||||
log.Infoln("Can't find GeoSite.dat, start download")
|
log.Infoln("Can't find GeoSite.dat, start download")
|
||||||
@@ -129,11 +99,6 @@ func Init(dir string) error {
|
|||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
//// initial GeoIP
|
|
||||||
//if err := initGeoIP(); err != nil {
|
|
||||||
// return fmt.Errorf("can't initial GeoIP: %w", err)
|
|
||||||
//}
|
|
||||||
|
|
||||||
// initial mmdb
|
// initial mmdb
|
||||||
if err := initMMDB(); err != nil {
|
if err := initMMDB(); err != nil {
|
||||||
return fmt.Errorf("can't initial MMDB: %w", err)
|
return fmt.Errorf("can't initial MMDB: %w", err)
|
||||||
|
|||||||
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
package statistic
|
package statistic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/snifer/tls"
|
|
||||||
"github.com/Dreamacro/clash/component/resolver"
|
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/log"
|
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
@@ -52,20 +48,7 @@ func (tt *tcpTracker) Write(b []byte) (int, error) {
|
|||||||
n, err := tt.Conn.Write(b)
|
n, err := tt.Conn.Write(b)
|
||||||
upload := int64(n)
|
upload := int64(n)
|
||||||
tt.manager.PushUploaded(upload)
|
tt.manager.PushUploaded(upload)
|
||||||
if tt.UploadTotal.Load() < 128 && tt.Metadata.Host == "" && (tt.Metadata.DstPort == "443" || tt.Metadata.DstPort == "8443" || tt.Metadata.DstPort == "993" || tt.Metadata.DstPort == "465" || tt.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(tt.Metadata.DstIP, header.Domain())
|
|
||||||
log.Warnln("use sni update host: %s ip: %s", header.Domain(), tt.Metadata.DstIP.String())
|
|
||||||
tt.manager.Leave(tt)
|
|
||||||
tt.Conn.Close()
|
|
||||||
return n, errors.New("sni update, break current link to avoid leaks")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tt.UploadTotal.Add(upload)
|
tt.UploadTotal.Add(upload)
|
||||||
|
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +57,7 @@ func (tt *tcpTracker) Close() error {
|
|||||||
return tt.Conn.Close()
|
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()
|
uuid, _ := uuid.NewV4()
|
||||||
|
|
||||||
t := &tcpTracker{
|
t := &tcpTracker{
|
||||||
@@ -97,7 +80,8 @@ func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
manager.Join(t)
|
manager.Join(t)
|
||||||
return t
|
conn = NewSniffing(t, metadata)
|
||||||
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type udpTracker struct {
|
type udpTracker struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user