mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-11-16 19:56:51 +08:00
Merge remote-tracking branch 'meta/Alpha' into Alpha
This commit is contained in:
commit
60dd76b7c4
|
@ -99,7 +99,13 @@ func (s *Snell) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
||||||
tcpKeepAlive(c)
|
tcpKeepAlive(c)
|
||||||
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
|
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
|
||||||
|
|
||||||
return s.ListenPacketOnStreamConn(c, metadata)
|
err = snell.WriteUDPHeader(c, s.version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pc := snell.PacketConn(c)
|
||||||
|
return newPacketConn(pc, s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||||
|
|
|
@ -161,7 +161,13 @@ func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.ListenPacketOnStreamConn(c, metadata)
|
err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pc := t.instance.PacketConn(c)
|
||||||
|
return newPacketConn(pc, t), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
var (
|
var (
|
||||||
ErrorUnsupportedSniffer = errors.New("unsupported sniffer")
|
ErrorUnsupportedSniffer = errors.New("unsupported sniffer")
|
||||||
ErrorSniffFailed = errors.New("all sniffer failed")
|
ErrorSniffFailed = errors.New("all sniffer failed")
|
||||||
|
ErrNoClue = errors.New("not enough information for making a decision")
|
||||||
)
|
)
|
||||||
|
|
||||||
var Dispatcher SnifferDispatcher
|
var Dispatcher SnifferDispatcher
|
||||||
|
|
109
component/sniffer/http_sniffer.go
Normal file
109
component/sniffer/http_sniffer.go
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
package sniffer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// refer to https://pkg.go.dev/net/http@master#pkg-constants
|
||||||
|
methods = [...]string{"get", "post", "head", "put", "delete", "options", "connect", "patch", "trace"}
|
||||||
|
errNotHTTPMethod = errors.New("not an HTTP method")
|
||||||
|
)
|
||||||
|
|
||||||
|
type version byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
HTTP1 version = iota
|
||||||
|
HTTP2
|
||||||
|
)
|
||||||
|
|
||||||
|
type HTTPSniffer struct {
|
||||||
|
version version
|
||||||
|
host string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (http *HTTPSniffer) Protocol() string {
|
||||||
|
switch http.version {
|
||||||
|
case HTTP1:
|
||||||
|
return "http1"
|
||||||
|
case HTTP2:
|
||||||
|
return "http2"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (http *HTTPSniffer) SupportNetwork() C.NetWork {
|
||||||
|
return C.TCP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (http *HTTPSniffer) SniffTCP(bytes []byte) (string, error) {
|
||||||
|
domain, err := SniffHTTP(bytes)
|
||||||
|
if err == nil {
|
||||||
|
return *domain, nil
|
||||||
|
} else {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func beginWithHTTPMethod(b []byte) error {
|
||||||
|
for _, m := range &methods {
|
||||||
|
if len(b) >= len(m) && strings.EqualFold(string(b[:len(m)]), m) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b) < len(m) {
|
||||||
|
return ErrNoClue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errNotHTTPMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
func SniffHTTP(b []byte) (*string, error) {
|
||||||
|
if err := beginWithHTTPMethod(b); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = &HTTPSniffer{
|
||||||
|
version: HTTP1,
|
||||||
|
}
|
||||||
|
|
||||||
|
headers := bytes.Split(b, []byte{'\n'})
|
||||||
|
for i := 1; i < len(headers); i++ {
|
||||||
|
header := headers[i]
|
||||||
|
if len(header) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
parts := bytes.SplitN(header, []byte{':'}, 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key := strings.ToLower(string(parts[0]))
|
||||||
|
if key == "host" {
|
||||||
|
port := 80
|
||||||
|
rawHost := strings.ToLower(string(bytes.TrimSpace(parts[1])))
|
||||||
|
host, rawPort, err := net.SplitHostPort(rawHost)
|
||||||
|
if err != nil {
|
||||||
|
if addrError, ok := err.(*net.AddrError); ok && strings.Contains(addrError.Err, "missing port") {
|
||||||
|
host = rawHost
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else if len(rawPort) > 0 {
|
||||||
|
intPort, err := strconv.ParseUint(rawPort, 0, 16)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
port = int(intPort)
|
||||||
|
}
|
||||||
|
host = net.JoinHostPort(host, strconv.Itoa(port))
|
||||||
|
return &host, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, ErrNoClue
|
||||||
|
}
|
3
component/sniffer/quic_sniffer.go
Normal file
3
component/sniffer/quic_sniffer.go
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package sniffer
|
||||||
|
|
||||||
|
//TODO
|
|
@ -11,7 +11,6 @@ import (
|
||||||
var (
|
var (
|
||||||
errNotTLS = errors.New("not TLS header")
|
errNotTLS = errors.New("not TLS header")
|
||||||
errNotClientHello = errors.New("not client hello")
|
errNotClientHello = errors.New("not client hello")
|
||||||
ErrNoClue = errors.New("not enough information for making a decision")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TLSSniffer struct {
|
type TLSSniffer struct {
|
||||||
|
|
|
@ -8,10 +8,11 @@ type Sniffer interface {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TLS SnifferType = iota
|
TLS SnifferType = iota
|
||||||
|
HTTP SnifferType
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
SnifferList = []SnifferType{TLS}
|
SnifferList = []SnifferType{TLS, HTTP}
|
||||||
)
|
)
|
||||||
|
|
||||||
type SnifferType int
|
type SnifferType int
|
||||||
|
@ -20,6 +21,8 @@ func (rt SnifferType) String() string {
|
||||||
switch rt {
|
switch rt {
|
||||||
case TLS:
|
case TLS:
|
||||||
return "TLS"
|
return "TLS"
|
||||||
|
case HTTP:
|
||||||
|
return "HTTP"
|
||||||
default:
|
default:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,8 @@ func (dc *quicClient) openSession() (quic.Connection, error) {
|
||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
ConnectionIDLength: 12,
|
ConnectionIDLength: 12,
|
||||||
HandshakeIdleTimeout: time.Second * 8,
|
HandshakeIdleTimeout: time.Second * 8,
|
||||||
|
MaxIncomingStreams: 4,
|
||||||
|
MaxIdleTimeout: time.Second * 45,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugln("opening session to %s", dc.addr)
|
log.Debugln("opening session to %s", dc.addr)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user