mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-12-22 15:47:59 +08:00
fix: the TLS Sniffer fails when the length of the ClientHello packet exceeds the TCP MSS (#1711)
Some checks failed
Trigger CMFA Update / trigger-CMFA-update (push) Has been cancelled
Some checks failed
Trigger CMFA Update / trigger-CMFA-update (push) Has been cancelled
* chore: add uniformly formatted debug info to sniffDomain * fix: when data is not enough, attempt to peek more data and retry * chore: reduce debug info of sniffDomain
This commit is contained in:
parent
5d9d8f4d3b
commit
c7fc93df37
@ -145,6 +145,10 @@ func (sd *Dispatcher) Enable() bool {
|
||||
}
|
||||
|
||||
func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (string, error) {
|
||||
//defer func(start time.Time) {
|
||||
// log.Debugln("[Sniffer] [%s] Sniffing took %s", metadata.DstIP, time.Since(start))
|
||||
//}(time.Now())
|
||||
|
||||
for s := range sd.sniffers {
|
||||
if s.SupportNetwork() == C.TCP && s.SupportPort(metadata.DstPort) {
|
||||
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
@ -154,7 +158,7 @@ func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (s
|
||||
_, ok := err.(*net.OpError)
|
||||
if ok {
|
||||
sd.cacheSniffFailed(metadata)
|
||||
log.Errorln("[Sniffer] [%s] may not have any sent data, Consider adding skip", metadata.DstIP.String())
|
||||
log.Errorln("[Sniffer] [%s] [%s] may not have any sent data, Consider adding skip", metadata.DstIP, s.Protocol())
|
||||
_ = conn.Close()
|
||||
}
|
||||
|
||||
@ -164,22 +168,36 @@ func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (s
|
||||
bufferedLen := conn.Buffered()
|
||||
bytes, err := conn.Peek(bufferedLen)
|
||||
if err != nil {
|
||||
log.Debugln("[Sniffer] the data length not enough")
|
||||
log.Debugln("[Sniffer] [%s] [%s] the data length not enough, error: %v", metadata.DstIP, s.Protocol(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
host, err := s.SniffData(bytes)
|
||||
var e *errNeedAtLeastData
|
||||
if errors.As(err, &e) {
|
||||
//log.Debugln("[Sniffer] [%s] [%s] %v, got length: %d", metadata.DstIP, s.Protocol(), e, len(bytes))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
bytes, err = conn.Peek(e.length)
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
//log.Debugln("[Sniffer] [%s] [%s] try again, got length: %d", metadata.DstIP, s.Protocol(), len(bytes))
|
||||
if err != nil {
|
||||
//log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP)
|
||||
log.Debugln("[Sniffer] [%s] [%s] the data length not enough, error: %v", metadata.DstIP, s.Protocol(), err)
|
||||
continue
|
||||
}
|
||||
host, err = s.SniffData(bytes)
|
||||
}
|
||||
if err != nil {
|
||||
//log.Debugln("[Sniffer] [%s] [%s] Sniff data failed, error: %v", metadata.DstIP, s.Protocol(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = netip.ParseAddr(host)
|
||||
if err == nil {
|
||||
//log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP)
|
||||
//log.Debugln("[Sniffer] [%s] [%s] Sniff data failed, got host [%s]", metadata.DstIP, s.Protocol(), host)
|
||||
continue
|
||||
}
|
||||
|
||||
//log.Debugln("[Sniffer] [%s] [%s] Sniffed [%s]", metadata.DstIP, s.Protocol(), host)
|
||||
return host, nil
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package sniffer
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
@ -15,6 +16,19 @@ var (
|
||||
errNotClientHello = errors.New("not client hello")
|
||||
)
|
||||
|
||||
type errNeedAtLeastData struct {
|
||||
length int
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *errNeedAtLeastData) Error() string {
|
||||
return fmt.Sprintf("%v, need at least length: %d", e.err, e.length)
|
||||
}
|
||||
|
||||
func (e *errNeedAtLeastData) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
var _ sniffer.Sniffer = (*TLSSniffer)(nil)
|
||||
|
||||
type TLSSniffer struct {
|
||||
@ -160,7 +174,10 @@ func SniffTLS(b []byte) (*string, error) {
|
||||
}
|
||||
headerLen := int(binary.BigEndian.Uint16(b[3:5]))
|
||||
if 5+headerLen > len(b) {
|
||||
return nil, ErrNoClue
|
||||
return nil, &errNeedAtLeastData{
|
||||
length: 5 + headerLen,
|
||||
err: ErrNoClue,
|
||||
}
|
||||
}
|
||||
|
||||
domain, err := ReadClientHello(b[5 : 5+headerLen])
|
||||
|
Loading…
Reference in New Issue
Block a user