Просмотр исходного кода

Small refactoring

tags/v2.2.8^2^2
9seconds 1 месяц назад
Родитель
Сommit
39ab5570a8
1 измененных файлов: 20 добавлений и 9 удалений
  1. 20
    9
      mtglib/internal/tls/fake/client_side.go

+ 20
- 9
mtglib/internal/tls/fake/client_side.go Просмотреть файл

@@ -5,6 +5,7 @@ import (
5 5
 	"crypto/hmac"
6 6
 	"crypto/sha256"
7 7
 	"crypto/subtle"
8
+	"crypto/tls"
8 9
 	"encoding/binary"
9 10
 	"fmt"
10 11
 	"io"
@@ -20,6 +21,12 @@ const (
20 21
 	// record_type(1) + version(2) + size(2) + handshake_type(1) + uint24_length(3) + client_version(2)
21 22
 	RandomOffset = 1 + 2 + 2 + 1 + 3 + 2
22 23
 
24
+	// https://datatracker.ietf.org/doc/html/rfc8701#name-grease-values
25
+	// https://medium.com/asecuritysite-when-bob-met-alice/in-cybersecurity-what-is-grease-9f8850558dea
26
+	GreaseMask      = 0x0f0f
27
+	GreaseValueType = 0x0a0a
28
+	DefaultCipher   = tls.TLS_AES_128_GCM_SHA256
29
+
23 30
 	sniDNSNamesListType = 0
24 31
 )
25 32
 
@@ -108,7 +115,9 @@ func parseHandshake(r io.Reader) (*ClientHello, error) {
108 115
 		return nil, fmt.Errorf("cannot read client version: %w", err)
109 116
 	}
110 117
 
111
-	hello := &ClientHello{}
118
+	hello := &ClientHello{
119
+		CipherSuite: DefaultCipher,
120
+	}
112 121
 
113 122
 	if _, err := io.ReadFull(r, hello.Random[:]); err != nil {
114 123
 		return nil, fmt.Errorf("cannot read client random: %w", err)
@@ -129,26 +138,28 @@ func parseHandshake(r io.Reader) (*ClientHello, error) {
129 138
 	}
130 139
 
131 140
 	cipherSuiteLen := int64(binary.BigEndian.Uint16(header[:]))
141
+	foundCipher := false
132 142
 
133 143
 	// Pick the first non-GREASE cipher suite from the list.
134 144
 	// Real TLS servers never select GREASE values (RFC 8701, pattern 0x?a?a),
135 145
 	// so echoing them back is a trivial DPI fingerprint.
136
-	for remaining := cipherSuiteLen; remaining >= 2; remaining -= 2 {
146
+	// cipherSuiteLen is in bytes; each cipher suite is 2 bytes.
147
+	for range cipherSuiteLen / 2 {
137 148
 		if _, err := io.ReadFull(r, header[:]); err != nil {
138 149
 			return nil, fmt.Errorf("cannot read cipher suite: %w", err)
139 150
 		}
140 151
 
141
-		cs := binary.BigEndian.Uint16(header[:])
142
-		if hello.CipherSuite == 0 && cs&0x0f0f != 0x0a0a {
143
-			hello.CipherSuite = cs
152
+		if foundCipher {
153
+			continue
144 154
 		}
145
-	}
146 155
 
147
-	if hello.CipherSuite == 0 {
148
-		hello.CipherSuite = 0x1301 // fallback: TLS_AES_128_GCM_SHA256
156
+		if cs := binary.BigEndian.Uint16(header[:]); cs&GreaseMask != GreaseValueType {
157
+			hello.CipherSuite = cs
158
+			// do not forget we have to scan until the end
159
+			foundCipher = true
160
+		}
149 161
 	}
150 162
 
151
-
152 163
 	if _, err := io.ReadFull(r, header[:1]); err != nil {
153 164
 		return nil, fmt.Errorf("cannot read compression methods length: %w", err)
154 165
 	}

Загрузка…
Отмена
Сохранить