From 7c1cc2cde479f062ca61e065c91964ca583da6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A3=8E=E6=89=87=E6=BB=91=E7=BF=94=E7=BF=BC?= Date: Wed, 4 Jun 2025 15:52:12 +0000 Subject: [PATCH] Add record detect --- record_detect.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 record_detect.go diff --git a/record_detect.go b/record_detect.go new file mode 100644 index 0000000..e3f4236 --- /dev/null +++ b/record_detect.go @@ -0,0 +1,80 @@ +package reality + +import ( + "bytes" + "crypto/tls" + "encoding/binary" + "io" + "net" + "time" +) + +func DetectRecordFingerprint(target string) ([]int, error) { + NetConn, err := net.Dial("tcp", target) + if err != nil { + return nil, err + } + conn := &detectConn{ + Conn: NetConn, + resultChan: make(chan []int, 1), + } + host, _, err := net.SplitHostPort(target) + if err != nil { + return nil, err + } + tlsConfig := &tls.Config{ + ServerName: host, + } + tlsConn := tls.Client(conn, tlsConfig) + if err != nil { + return nil, err + } + go func() { + io.Copy(io.Discard, tlsConn) + }() + select { + case result := <-conn.resultChan: + return result, nil + case <-time.After(2 * time.Second): + return nil, nil + } +} + +type detectConn struct { + net.Conn + ccsSent bool + done bool + resultChan chan ([]int) +} + +func (c *detectConn) Write(b []byte) (n int, err error) { + if len(b) >= 3 && bytes.Equal(b[:3], []byte{20, 3, 3}) { + c.ccsSent = true + } + return c.Conn.Write(b) +} + +func (c *detectConn) Read(b []byte) (n int, err error) { + n, err = c.Conn.Read(b) + if c.ccsSent && !c.done { + data := make([]byte, len(b)) + copy(data, b) + var result []int + for { + if len(data) > 3 && bytes.Equal(data[:3], []byte{23, 3, 3}) { + length := int(binary.BigEndian.Uint16(data[3:5])) + if len(data) > length+5 { + result = append(result, int(length)) + data = data[length+5:] + } + } else { + break + } + } + if len(result) != 1 { + c.done = true + c.resultChan <- result + } + } + return n, err +}