Fix quic sniff irl

This commit is contained in:
世界 2022-07-10 07:52:33 +08:00
parent 730144cc26
commit 4432cc2253
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
2 changed files with 43 additions and 13 deletions

View File

@ -12,6 +12,7 @@ import (
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/sniff/internal/qtls" "github.com/sagernet/sing-box/common/sniff/internal/qtls"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
E "github.com/sagernet/sing/common/exceptions"
"golang.org/x/crypto/hkdf" "golang.org/x/crypto/hkdf"
) )
@ -25,7 +26,7 @@ func QUICClientHello(ctx context.Context, packet []byte) (*adapter.InboundContex
} }
if typeByte&0x80 == 0 || typeByte&0x40 == 0 { if typeByte&0x80 == 0 || typeByte&0x40 == 0 {
return nil, os.ErrInvalid return nil, E.New("bad type byte")
} }
var versionNumber uint32 var versionNumber uint32
err = binary.Read(reader, binary.BigEndian, &versionNumber) err = binary.Read(reader, binary.BigEndian, &versionNumber)
@ -33,13 +34,22 @@ func QUICClientHello(ctx context.Context, packet []byte) (*adapter.InboundContex
return nil, err return nil, err
} }
if versionNumber != qtls.VersionDraft29 && versionNumber != qtls.Version1 && versionNumber != qtls.Version2 { if versionNumber != qtls.VersionDraft29 && versionNumber != qtls.Version1 && versionNumber != qtls.Version2 {
return nil, os.ErrInvalid return nil, E.New("bad version")
} }
if (typeByte&0x30)>>4 == 0x0 { if versionNumber == qtls.Version2 {
} else if (typeByte&0x30)>>4 != 0x01 { if (typeByte&0x30)>>4 == 0b01 {
// 0-rtt } else if (typeByte&0x30)>>4 != 0b10 {
// 0-rtt
} else {
return nil, E.New("bad packet type")
}
} else { } else {
return nil, os.ErrInvalid if (typeByte&0x30)>>4 == 0x0 {
} else if (typeByte&0x30)>>4 != 0x01 {
// 0-rtt
} else {
return nil, E.New("bad packet type")
}
} }
destConnIDLen, err := reader.ReadByte() destConnIDLen, err := reader.ReadByte()
@ -47,6 +57,10 @@ func QUICClientHello(ctx context.Context, packet []byte) (*adapter.InboundContex
return nil, err return nil, err
} }
if destConnIDLen == 0 || destConnIDLen > 20 {
return nil, E.New("bad destination connection id length")
}
destConnID := make([]byte, destConnIDLen) destConnID := make([]byte, destConnIDLen)
_, err = io.ReadFull(reader, destConnID) _, err = io.ReadFull(reader, destConnID)
if err != nil { if err != nil {
@ -79,7 +93,7 @@ func QUICClientHello(ctx context.Context, packet []byte) (*adapter.InboundContex
} }
hdrLen := int(reader.Size()) - reader.Len() hdrLen := int(reader.Size()) - reader.Len()
if hdrLen != len(packet)-int(packetLen) { if hdrLen+int(packetLen) > len(packet) {
return nil, os.ErrInvalid return nil, os.ErrInvalid
} }
@ -126,17 +140,25 @@ func QUICClientHello(ctx context.Context, packet []byte) (*adapter.InboundContex
newPacket[hdrLen+i] ^= mask[i+1] newPacket[hdrLen+i] ^= mask[i+1]
} }
packetNumberLength := newPacket[0]&0x3 + 1 packetNumberLength := newPacket[0]&0x3 + 1
if packetNumberLength != 1 { if hdrLen+int(packetNumberLength) > int(packetLen)+hdrLen {
return nil, os.ErrInvalid return nil, os.ErrInvalid
} }
packetNumber := newPacket[hdrLen] var packetNumber uint32
if err != nil { switch packetNumberLength {
return nil, err case 1:
packetNumber = uint32(newPacket[hdrLen])
case 2:
packetNumber = uint32(binary.BigEndian.Uint16(newPacket[hdrLen:]))
case 3:
packetNumber = uint32(newPacket[hdrLen+2]) | uint32(newPacket[hdrLen+1])<<8 | uint32(newPacket[hdrLen])<<16
case 4:
packetNumber = binary.BigEndian.Uint32(newPacket[hdrLen:])
default:
return nil, E.New("bad packet number length")
} }
if packetNumber != 0 { if packetNumber != 0 {
return nil, os.ErrInvalid return nil, E.New("bad packet number: ", packetNumber)
} }
extHdrLen := hdrLen + int(packetNumberLength) extHdrLen := hdrLen + int(packetNumberLength)
copy(newPacket[extHdrLen:hdrLen+4], packet[extHdrLen:]) copy(newPacket[extHdrLen:hdrLen+4], packet[extHdrLen:])
data := newPacket[extHdrLen : int(packetLen)+hdrLen] data := newPacket[extHdrLen : int(packetLen)+hdrLen]
@ -166,6 +188,13 @@ func QUICClientHello(ctx context.Context, packet []byte) (*adapter.InboundContex
if err != nil { if err != nil {
return nil, err return nil, err
} }
for frameType == 0x0 {
// skip padding
frameType, err = decryptedReader.ReadByte()
if err != nil {
return nil, err
}
}
if frameType != 0x6 { if frameType != 0x6 {
// not crypto frame // not crypto frame
return &adapter.InboundContext{Protocol: C.ProtocolQUIC}, nil return &adapter.InboundContext{Protocol: C.ProtocolQUIC}, nil

View File

@ -28,6 +28,7 @@ func PeekPacket(ctx context.Context, packet []byte, sniffers ...PacketSniffer) (
for _, sniffer := range sniffers { for _, sniffer := range sniffers {
sniffMetadata, err := sniffer(ctx, packet) sniffMetadata, err := sniffer(ctx, packet)
if err != nil { if err != nil {
println(err.Error())
return nil, err return nil, err
} }
return sniffMetadata, nil return sniffMetadata, nil