mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-18 03:39:43 +07:00
optimize(udp)/fix(quicSniffer): optimize performance of udp and fix a potential panic of quic (#301)
This commit is contained in:
@ -18,6 +18,8 @@ const (
|
||||
HandShakeType_Hello byte = 1
|
||||
TlsExtension_ServerName uint16 = 0
|
||||
TlsExtension_ServerNameType_HostName byte = 0
|
||||
|
||||
AssumedTlsClientHelloMaxLength = 4096
|
||||
)
|
||||
|
||||
var (
|
||||
@ -30,18 +32,18 @@ func (s *Sniffer) SniffTls() (d string, err error) {
|
||||
// The Transport Layer Security (TLS) Protocol Version 1.3
|
||||
// https://www.rfc-editor.org/rfc/rfc8446#page-27
|
||||
boundary := 5
|
||||
if len(s.buf) < boundary {
|
||||
return "", NotApplicableError
|
||||
if s.buf.Len() < boundary {
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
if s.buf[0] != ContentType_HandShake || (!bytes.Equal(s.buf[1:3], Version_Tls1_0) && !bytes.Equal(s.buf[1:3], Version_Tls1_2)) {
|
||||
return "", NotApplicableError
|
||||
if s.buf.Bytes()[0] != ContentType_HandShake || (!bytes.Equal(s.buf.Bytes()[1:3], Version_Tls1_0) && !bytes.Equal(s.buf.Bytes()[1:3], Version_Tls1_2)) {
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
length := int(binary.BigEndian.Uint16(s.buf[3:5]))
|
||||
search := s.buf[5:]
|
||||
length := int(binary.BigEndian.Uint16(s.buf.Bytes()[3:5]))
|
||||
search := s.buf.Bytes()[5:]
|
||||
if len(search) < length {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
return extractSniFromTls(quicutils.BuiltinBytesLocator(search[:length]))
|
||||
}
|
||||
@ -49,88 +51,119 @@ func (s *Sniffer) SniffTls() (d string, err error) {
|
||||
func extractSniFromTls(search quicutils.Locator) (sni string, err error) {
|
||||
boundary := 39
|
||||
if search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
// Transport Layer Security (TLS) Extensions: Extension Definitions
|
||||
// https://www.rfc-editor.org/rfc/rfc6066#page-5
|
||||
b := search.Range(0, 6)
|
||||
b, err := search.Range(0, 6)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if b[0] != HandShakeType_Hello {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
// Three bytes length.
|
||||
length2 := (int(b[1]) << 16) + (int(b[2]) << 8) + int(b[3])
|
||||
if search.Len() > length2+4 {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
if !bytes.Equal(b[4:], Version_Tls1_2) {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
// Skip 32 bytes random.
|
||||
|
||||
sessionIdLength := search.At(boundary - 1)
|
||||
sessionIdLength, err := search.At(boundary - 1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
boundary += int(sessionIdLength) + 2 // +2 because the next field has 2B length
|
||||
if search.Len() < boundary || search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
b = search.Range(boundary-2, boundary)
|
||||
b, err = search.Range(boundary-2, boundary)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cipherSuiteLength := int(binary.BigEndian.Uint16(b))
|
||||
boundary += int(cipherSuiteLength) + 1 // +1 because the next field has 1B length
|
||||
if search.Len() < boundary || search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
compressMethodsLength := search.At(boundary - 1)
|
||||
compressMethodsLength, err := search.At(boundary - 1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
boundary += int(compressMethodsLength) + 2 // +2 because the next field has 2B length
|
||||
if search.Len() < boundary || search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
b = search.Range(boundary-2, boundary)
|
||||
b, err = search.Range(boundary-2, boundary)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
extensionsLength := int(binary.BigEndian.Uint16(b))
|
||||
boundary += extensionsLength + 0 // +0 because our search ends
|
||||
if search.Len() < boundary || search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
// Search SNI
|
||||
return findSniExtension(search.Slice(boundary-extensionsLength, boundary))
|
||||
extensions, err := search.Slice(boundary-extensionsLength, boundary)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return findSniExtension(extensions)
|
||||
}
|
||||
|
||||
func findSniExtension(search quicutils.Locator) (string, error) {
|
||||
func findSniExtension(search quicutils.Locator) (d string, err error) {
|
||||
i := 0
|
||||
var b []byte
|
||||
for {
|
||||
if i+4 >= search.Len() {
|
||||
return "", NotFoundError
|
||||
return "", ErrNotFound
|
||||
}
|
||||
b, err = search.Range(i, i+4)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b = search.Range(i, i+4)
|
||||
typ := binary.BigEndian.Uint16(b)
|
||||
extLength := int(binary.BigEndian.Uint16(b[2:]))
|
||||
|
||||
iNextField := i + 4 + extLength
|
||||
if iNextField > search.Len() {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
if typ == TlsExtension_ServerName {
|
||||
b = search.Range(i+4, i+6)
|
||||
b, err = search.Range(i+4, i+6)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sniLen := int(binary.BigEndian.Uint16(b))
|
||||
if extLength < sniLen+2 {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
// Search HostName type SNI.
|
||||
for j, indicatorLen := i+6, 0; j+3 <= iNextField; j += indicatorLen {
|
||||
b = search.Range(j, j+3)
|
||||
b, err = search.Range(j, j+3)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
indicatorLen = int(binary.BigEndian.Uint16(b[1:]))
|
||||
if b[0] != TlsExtension_ServerNameType_HostName {
|
||||
continue
|
||||
}
|
||||
if j+3+indicatorLen > iNextField {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
b, err = search.Range(j+3, j+3+indicatorLen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b = search.Range(j+3, j+3+indicatorLen)
|
||||
// An SNI value may not include a trailing dot.
|
||||
// https://tools.ietf.org/html/rfc6066#section-3
|
||||
// But we accept it here.
|
||||
|
Reference in New Issue
Block a user