0
0
mirror of https://github.com/XTLS/REALITY.git synced 2025-08-22 14:38:35 +00:00

Delay and detect H2 settings frame

Do not send fake H2 settings packet if the upper level (xhttp) will send the real packet
This commit is contained in:
yuhan6665 2025-07-13 21:13:17 -04:00
parent 49f5025763
commit 5eeac447fe
3 changed files with 69 additions and 15 deletions

42
conn.go
View File

@ -29,6 +29,8 @@ type Conn struct {
ClientVer [3]byte
ClientTime time.Time
ClientShortId [8]byte
PostHandshakeRecord []TrafficPacket
PosthandshakeMutex sync.Mutex
// constant
conn net.Conn
@ -1314,10 +1316,50 @@ func (c *Conn) Write(b []byte) (int, error) {
}
}
c.PosthandshakeMutex.Lock()
if c.PostHandshakeRecord != nil {
for _, packet := range c.PostHandshakeRecord {
for i, length := range packet.Lens {
if length <= 100 && i == len(packet.Lens) - 1 && isH2Settings(b) {
fmt.Printf("REALITY skip fake H2 Settings frame len(postHandshakeRecord): %v\n", length)
} else {
plainText := make([]byte, length-16)
plainText[0] = 23
plainText[1] = 3
plainText[2] = 3
plainText[3] = byte((length - 5) >> 8)
plainText[4] = byte((length - 5))
plainText[5] = 23
postHandshakeRecord := c.out.cipher.(aead).Seal(plainText[:5], c.out.seq[:], plainText[5:], plainText[:5])
c.out.incSeq()
c.write(postHandshakeRecord)
fmt.Printf("REALITY Send with data, len(postHandshakeRecord): %v\tlen(buffer):%v\n", length, len(b))
}
}
}
c.PostHandshakeRecord = nil
}
c.PosthandshakeMutex.Unlock()
n, err := c.writeRecordLocked(recordTypeApplicationData, b)
return n + m, c.out.setErrorLocked(err)
}
func isH2Settings(b []byte) bool {
if len(b) < 9 {
return false
}
if b[3] == 0x04 && b[5] == 0x00 && b[6] == 0x00 && b[7] == 0x00 && b[8] == 0x00 {
// H2 settings with stream identifier of zero (0x0) is used for connection control messages
return true
}
if b[3] == 0x08 && b[5] == 0x00 && b[6] == 0x00 && b[7] == 0x00 && b[8] == 0x00 {
// H2 window update, unlikely but put here anyways
return true
}
return false
}
// handleRenegotiation processes a HelloRequest handshake message.
func (c *Conn) handleRenegotiation() error {
if c.vers == VersionTLS13 {

View File

@ -90,13 +90,13 @@ func (c *DetectConn) Read(b []byte) (n int, err error) {
for {
data := make([]byte, 0, 2048)
n, err = c.Conn.Read(data[len(data):cap(data)])
data = data[:len(data)+n]
if err != nil {
return 0, err
}
newPacket := TrafficPacket {
SinceHandshake: time.Since(c.HandshakeDone),
}
c.PostHandshakeRecordsLens[c.Sni] = append(c.PostHandshakeRecordsLens[c.Sni], newPacket)
for len(data) > 0 {
if len(data) >= 5 && bytes.Equal(data[:3], []byte{23, 3, 3}) {
length := int(binary.BigEndian.Uint16(data[3:5])) + 5
@ -106,5 +106,6 @@ func (c *DetectConn) Read(b []byte) (n int, err error) {
break
}
}
c.PostHandshakeRecordsLens[c.Sni] = append(c.PostHandshakeRecordsLens[c.Sni], newPacket)
}
}

39
tls.go
View File

@ -374,21 +374,32 @@ func Server(ctx context.Context, conn net.Conn, config *Config) (*Conn, error) {
if err != nil {
break
}
for _, packet := range postHandshakeRecordsLens[hs.clientHello.serverName] {
for _, length := range packet.Lens {
plainText := make([]byte, length-16)
plainText[0] = 23
plainText[1] = 3
plainText[2] = 3
plainText[3] = byte((length - 5) >> 8)
plainText[4] = byte((length - 5))
plainText[5] = 23
postHandshakeRecord := hs.c.out.cipher.(aead).Seal(plainText[:5], hs.c.out.seq[:], plainText[5:], plainText[:5])
hs.c.out.incSeq()
hs.c.write(postHandshakeRecord)
fmt.Printf("REALITY remoteAddr: %v\tlen(postHandshakeRecord): %v\n", remoteAddr, len(postHandshakeRecord))
hs.c.PostHandshakeRecord = postHandshakeRecordsLens[hs.clientHello.serverName]
go func(){
if hs.c.PostHandshakeRecord != nil {
time.Sleep(hs.c.PostHandshakeRecord[0].SinceHandshake)
}
}
hs.c.PosthandshakeMutex.Lock()
defer hs.c.PosthandshakeMutex.Unlock()
if hs.c.PostHandshakeRecord != nil {
for _, packet := range hs.c.PostHandshakeRecord {
for _, length := range packet.Lens {
plainText := make([]byte, length-16)
plainText[0] = 23
plainText[1] = 3
plainText[2] = 3
plainText[3] = byte((length - 5) >> 8)
plainText[4] = byte((length - 5))
plainText[5] = 23
postHandshakeRecord := hs.c.out.cipher.(aead).Seal(plainText[:5], hs.c.out.seq[:], plainText[5:], plainText[:5])
hs.c.out.incSeq()
hs.c.write(postHandshakeRecord)
fmt.Printf("REALITY remoteAddr: %v\tSend after sleep%s\tlen(postHandshakeRecord): %v\n", remoteAddr, packet.SinceHandshake, len(postHandshakeRecord))
}
}
hs.c.PostHandshakeRecord = nil
}
}()
hs.c.isHandshakeComplete.Store(true)
break
}