Skip to content

Commit c6afcd5

Browse files
authored
XTLS Vision: Check TLS record isComplete (#5179)
Fixes #5169 (comment)
1 parent ed5f7e7 commit c6afcd5

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

proxy/proxy.go

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,11 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
350350
mb[0] = XtlsPadding(nil, CommandPaddingContinue, &w.writeOnceUserUUID, true, w.ctx) // we do a long padding to hide vless header
351351
return w.Writer.WriteMultiBuffer(mb)
352352
}
353+
isComplete := IsCompleteRecord(mb)
353354
mb = ReshapeMultiBuffer(w.ctx, mb)
354355
longPadding := w.trafficState.IsTLS
355356
for i, b := range mb {
356-
if w.trafficState.IsTLS && b.Len() >= 6 && bytes.Equal(TlsApplicationDataStart, b.BytesTo(3)) {
357+
if w.trafficState.IsTLS && b.Len() >= 6 && bytes.Equal(TlsApplicationDataStart, b.BytesTo(3)) && isComplete {
357358
if w.trafficState.EnableXtls {
358359
*switchToDirectCopy = true
359360
}
@@ -386,6 +387,71 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
386387
return w.Writer.WriteMultiBuffer(mb)
387388
}
388389

390+
// IsCompleteRecord Is complete tls data record
391+
func IsCompleteRecord(buffer buf.MultiBuffer) bool {
392+
mb2 := make(buf.MultiBuffer, 0, len(buffer))
393+
for _, buffer1 := range buffer {
394+
buffer2 := buf.New()
395+
buffer2.Write(buffer1.Bytes())
396+
mb2 = append(mb2, buffer2)
397+
}
398+
isComplete := true
399+
var headerLen int32 = 5
400+
var recordLen int32
401+
for _, buffer2 := range mb2 {
402+
for buffer2.Len() > 0 {
403+
if headerLen > 0 {
404+
data, _ := buffer2.ReadByte()
405+
switch headerLen {
406+
case 5:
407+
if data != 0x17 {
408+
isComplete = false
409+
break
410+
}
411+
case 4:
412+
if data != 0x03 {
413+
isComplete = false
414+
break
415+
}
416+
case 3:
417+
if data != 0x03 {
418+
isComplete = false
419+
break
420+
}
421+
case 2:
422+
recordLen = int32(data) << 8
423+
case 1:
424+
recordLen = recordLen | int32(data)
425+
}
426+
headerLen--
427+
} else if recordLen > 0 {
428+
var len = recordLen
429+
if buffer2.Len() < recordLen{
430+
len = buffer2.Len()
431+
}
432+
buffer2.Advance(len)
433+
recordLen -= len
434+
if recordLen == 0 {
435+
headerLen = 5
436+
}
437+
} else {
438+
isComplete = false
439+
}
440+
}
441+
if !isComplete {
442+
break
443+
}
444+
}
445+
for _, buffer2 := range mb2 {
446+
buffer2.Release()
447+
buffer2 = nil
448+
}
449+
if headerLen == 5 && recordLen == 0 && isComplete {
450+
return true
451+
}
452+
return false
453+
}
454+
389455
// ReshapeMultiBuffer prepare multi buffer for padding structure (max 21 bytes)
390456
func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer {
391457
needReshape := 0

0 commit comments

Comments
 (0)