mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 16:24:03 +03:00
Small refactoring
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -20,6 +21,12 @@ const (
|
|||||||
// record_type(1) + version(2) + size(2) + handshake_type(1) + uint24_length(3) + client_version(2)
|
// record_type(1) + version(2) + size(2) + handshake_type(1) + uint24_length(3) + client_version(2)
|
||||||
RandomOffset = 1 + 2 + 2 + 1 + 3 + 2
|
RandomOffset = 1 + 2 + 2 + 1 + 3 + 2
|
||||||
|
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc8701#name-grease-values
|
||||||
|
// https://medium.com/asecuritysite-when-bob-met-alice/in-cybersecurity-what-is-grease-9f8850558dea
|
||||||
|
GreaseMask = 0x0f0f
|
||||||
|
GreaseValueType = 0x0a0a
|
||||||
|
DefaultCipher = tls.TLS_AES_128_GCM_SHA256
|
||||||
|
|
||||||
sniDNSNamesListType = 0
|
sniDNSNamesListType = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -108,7 +115,9 @@ func parseHandshake(r io.Reader) (*ClientHello, error) {
|
|||||||
return nil, fmt.Errorf("cannot read client version: %w", err)
|
return nil, fmt.Errorf("cannot read client version: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hello := &ClientHello{}
|
hello := &ClientHello{
|
||||||
|
CipherSuite: DefaultCipher,
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := io.ReadFull(r, hello.Random[:]); err != nil {
|
if _, err := io.ReadFull(r, hello.Random[:]); err != nil {
|
||||||
return nil, fmt.Errorf("cannot read client random: %w", err)
|
return nil, fmt.Errorf("cannot read client random: %w", err)
|
||||||
@@ -129,26 +138,28 @@ func parseHandshake(r io.Reader) (*ClientHello, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cipherSuiteLen := int64(binary.BigEndian.Uint16(header[:]))
|
cipherSuiteLen := int64(binary.BigEndian.Uint16(header[:]))
|
||||||
|
foundCipher := false
|
||||||
|
|
||||||
// Pick the first non-GREASE cipher suite from the list.
|
// Pick the first non-GREASE cipher suite from the list.
|
||||||
// Real TLS servers never select GREASE values (RFC 8701, pattern 0x?a?a),
|
// Real TLS servers never select GREASE values (RFC 8701, pattern 0x?a?a),
|
||||||
// so echoing them back is a trivial DPI fingerprint.
|
// so echoing them back is a trivial DPI fingerprint.
|
||||||
for remaining := cipherSuiteLen; remaining >= 2; remaining -= 2 {
|
// cipherSuiteLen is in bytes; each cipher suite is 2 bytes.
|
||||||
|
for range cipherSuiteLen / 2 {
|
||||||
if _, err := io.ReadFull(r, header[:]); err != nil {
|
if _, err := io.ReadFull(r, header[:]); err != nil {
|
||||||
return nil, fmt.Errorf("cannot read cipher suite: %w", err)
|
return nil, fmt.Errorf("cannot read cipher suite: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cs := binary.BigEndian.Uint16(header[:])
|
if foundCipher {
|
||||||
if hello.CipherSuite == 0 && cs&0x0f0f != 0x0a0a {
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if cs := binary.BigEndian.Uint16(header[:]); cs&GreaseMask != GreaseValueType {
|
||||||
hello.CipherSuite = cs
|
hello.CipherSuite = cs
|
||||||
|
// do not forget we have to scan until the end
|
||||||
|
foundCipher = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hello.CipherSuite == 0 {
|
|
||||||
hello.CipherSuite = 0x1301 // fallback: TLS_AES_128_GCM_SHA256
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if _, err := io.ReadFull(r, header[:1]); err != nil {
|
if _, err := io.ReadFull(r, header[:1]); err != nil {
|
||||||
return nil, fmt.Errorf("cannot read compression methods length: %w", err)
|
return nil, fmt.Errorf("cannot read compression methods length: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user