@push.rocks/smartproxy 11.0.0 → 13.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/certificate/acme/acme-factory.d.ts +17 -0
  3. package/dist_ts/certificate/acme/acme-factory.js +40 -0
  4. package/dist_ts/certificate/acme/challenge-handler.d.ts +44 -0
  5. package/dist_ts/certificate/acme/challenge-handler.js +92 -0
  6. package/dist_ts/certificate/acme/index.d.ts +4 -0
  7. package/dist_ts/certificate/acme/index.js +5 -0
  8. package/dist_ts/certificate/events/certificate-events.d.ts +33 -0
  9. package/dist_ts/certificate/events/certificate-events.js +38 -0
  10. package/dist_ts/certificate/index.d.ts +24 -0
  11. package/dist_ts/certificate/index.js +39 -0
  12. package/dist_ts/certificate/models/certificate-types.d.ts +77 -0
  13. package/dist_ts/certificate/models/certificate-types.js +2 -0
  14. package/dist_ts/certificate/providers/cert-provisioner.d.ts +93 -0
  15. package/dist_ts/certificate/providers/cert-provisioner.js +262 -0
  16. package/dist_ts/certificate/providers/index.d.ts +4 -0
  17. package/dist_ts/certificate/providers/index.js +5 -0
  18. package/dist_ts/certificate/storage/file-storage.d.ts +66 -0
  19. package/dist_ts/certificate/storage/file-storage.js +194 -0
  20. package/dist_ts/certificate/storage/index.d.ts +4 -0
  21. package/dist_ts/certificate/storage/index.js +5 -0
  22. package/dist_ts/certificate/utils/certificate-helpers.d.ts +17 -0
  23. package/dist_ts/certificate/utils/certificate-helpers.js +45 -0
  24. package/dist_ts/common/eventUtils.d.ts +1 -1
  25. package/dist_ts/common/port80-adapter.d.ts +1 -1
  26. package/dist_ts/core/events/index.d.ts +4 -0
  27. package/dist_ts/core/events/index.js +5 -0
  28. package/dist_ts/core/index.d.ts +6 -0
  29. package/dist_ts/core/index.js +8 -0
  30. package/dist_ts/core/models/common-types.d.ts +82 -0
  31. package/dist_ts/core/models/common-types.js +15 -0
  32. package/dist_ts/core/models/index.d.ts +4 -0
  33. package/dist_ts/core/models/index.js +5 -0
  34. package/dist_ts/core/utils/event-utils.d.ts +15 -0
  35. package/dist_ts/core/utils/event-utils.js +19 -0
  36. package/dist_ts/core/utils/index.d.ts +6 -0
  37. package/dist_ts/core/utils/index.js +7 -0
  38. package/dist_ts/core/utils/ip-utils.d.ts +53 -0
  39. package/dist_ts/core/utils/ip-utils.js +153 -0
  40. package/dist_ts/core/utils/validation-utils.d.ts +61 -0
  41. package/dist_ts/core/utils/validation-utils.js +149 -0
  42. package/dist_ts/forwarding/config/domain-config.d.ts +12 -0
  43. package/dist_ts/forwarding/config/domain-config.js +12 -0
  44. package/dist_ts/forwarding/config/domain-manager.d.ts +86 -0
  45. package/dist_ts/forwarding/config/domain-manager.js +242 -0
  46. package/dist_ts/forwarding/config/forwarding-types.d.ts +104 -0
  47. package/dist_ts/forwarding/config/forwarding-types.js +50 -0
  48. package/dist_ts/forwarding/config/index.d.ts +6 -0
  49. package/dist_ts/forwarding/config/index.js +7 -0
  50. package/dist_ts/forwarding/factory/forwarding-factory.d.ts +25 -0
  51. package/dist_ts/forwarding/factory/forwarding-factory.js +138 -0
  52. package/dist_ts/forwarding/factory/index.d.ts +4 -0
  53. package/dist_ts/forwarding/factory/index.js +5 -0
  54. package/dist_ts/forwarding/handlers/base-handler.d.ts +55 -0
  55. package/dist_ts/forwarding/handlers/base-handler.js +94 -0
  56. package/dist_ts/forwarding/handlers/http-handler.d.ts +30 -0
  57. package/dist_ts/forwarding/handlers/http-handler.js +131 -0
  58. package/dist_ts/forwarding/handlers/https-passthrough-handler.d.ts +29 -0
  59. package/dist_ts/forwarding/handlers/https-passthrough-handler.js +162 -0
  60. package/dist_ts/forwarding/handlers/https-terminate-to-http-handler.d.ts +36 -0
  61. package/dist_ts/forwarding/handlers/https-terminate-to-http-handler.js +229 -0
  62. package/dist_ts/forwarding/handlers/https-terminate-to-https-handler.d.ts +35 -0
  63. package/dist_ts/forwarding/handlers/https-terminate-to-https-handler.js +254 -0
  64. package/dist_ts/forwarding/handlers/index.d.ts +8 -0
  65. package/dist_ts/forwarding/handlers/index.js +9 -0
  66. package/dist_ts/forwarding/index.d.ts +19 -0
  67. package/dist_ts/forwarding/index.js +25 -0
  68. package/dist_ts/http/index.d.ts +15 -0
  69. package/dist_ts/http/index.js +20 -0
  70. package/dist_ts/http/models/http-types.d.ts +81 -0
  71. package/dist_ts/http/models/http-types.js +62 -0
  72. package/dist_ts/http/port80/acme-interfaces.d.ts +78 -0
  73. package/dist_ts/http/port80/acme-interfaces.js +6 -0
  74. package/dist_ts/http/port80/challenge-responder.d.ts +53 -0
  75. package/dist_ts/http/port80/challenge-responder.js +203 -0
  76. package/dist_ts/http/port80/index.d.ts +6 -0
  77. package/dist_ts/http/port80/index.js +9 -0
  78. package/dist_ts/http/port80/port80-handler.d.ts +121 -0
  79. package/dist_ts/http/port80/port80-handler.js +554 -0
  80. package/dist_ts/http/redirects/index.d.ts +4 -0
  81. package/dist_ts/http/redirects/index.js +5 -0
  82. package/dist_ts/http/router/index.d.ts +4 -0
  83. package/dist_ts/http/router/index.js +5 -0
  84. package/dist_ts/http/router/proxy-router.d.ts +115 -0
  85. package/dist_ts/http/router/proxy-router.js +325 -0
  86. package/dist_ts/index.d.ts +15 -8
  87. package/dist_ts/index.js +26 -10
  88. package/dist_ts/networkproxy/classes.np.certificatemanager.js +2 -2
  89. package/dist_ts/networkproxy/index.d.ts +1 -6
  90. package/dist_ts/networkproxy/index.js +4 -8
  91. package/dist_ts/plugins.d.ts +2 -1
  92. package/dist_ts/plugins.js +3 -2
  93. package/dist_ts/port80handler/classes.port80handler.d.ts +8 -136
  94. package/dist_ts/port80handler/classes.port80handler.js +14 -567
  95. package/dist_ts/proxies/index.d.ts +6 -0
  96. package/dist_ts/proxies/index.js +8 -0
  97. package/dist_ts/proxies/network-proxy/certificate-manager.d.ts +77 -0
  98. package/dist_ts/proxies/network-proxy/certificate-manager.js +373 -0
  99. package/dist_ts/proxies/network-proxy/connection-pool.d.ts +47 -0
  100. package/dist_ts/proxies/network-proxy/connection-pool.js +210 -0
  101. package/dist_ts/proxies/network-proxy/index.d.ts +10 -0
  102. package/dist_ts/proxies/network-proxy/index.js +12 -0
  103. package/dist_ts/proxies/network-proxy/models/index.d.ts +4 -0
  104. package/dist_ts/proxies/network-proxy/models/index.js +5 -0
  105. package/dist_ts/proxies/network-proxy/models/types.d.ts +80 -0
  106. package/dist_ts/proxies/network-proxy/models/types.js +35 -0
  107. package/dist_ts/proxies/network-proxy/network-proxy.d.ts +118 -0
  108. package/dist_ts/proxies/network-proxy/network-proxy.js +387 -0
  109. package/dist_ts/proxies/network-proxy/request-handler.d.ts +57 -0
  110. package/dist_ts/proxies/network-proxy/request-handler.js +394 -0
  111. package/dist_ts/proxies/network-proxy/websocket-handler.d.ts +38 -0
  112. package/dist_ts/proxies/network-proxy/websocket-handler.js +188 -0
  113. package/dist_ts/proxies/nftables-proxy/index.d.ts +5 -0
  114. package/dist_ts/proxies/nftables-proxy/index.js +6 -0
  115. package/dist_ts/proxies/nftables-proxy/models/errors.d.ts +15 -0
  116. package/dist_ts/proxies/nftables-proxy/models/errors.js +28 -0
  117. package/dist_ts/proxies/nftables-proxy/models/index.d.ts +5 -0
  118. package/dist_ts/proxies/nftables-proxy/models/index.js +6 -0
  119. package/dist_ts/proxies/nftables-proxy/models/interfaces.d.ts +75 -0
  120. package/dist_ts/proxies/nftables-proxy/models/interfaces.js +5 -0
  121. package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +136 -0
  122. package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +1516 -0
  123. package/dist_ts/proxies/smart-proxy/connection-handler.d.ts +39 -0
  124. package/dist_ts/proxies/smart-proxy/connection-handler.js +894 -0
  125. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +78 -0
  126. package/dist_ts/proxies/smart-proxy/connection-manager.js +378 -0
  127. package/dist_ts/proxies/smart-proxy/domain-config-manager.d.ts +95 -0
  128. package/dist_ts/proxies/smart-proxy/domain-config-manager.js +255 -0
  129. package/dist_ts/proxies/smart-proxy/index.d.ts +13 -0
  130. package/dist_ts/proxies/smart-proxy/index.js +17 -0
  131. package/dist_ts/proxies/smart-proxy/models/index.d.ts +4 -0
  132. package/dist_ts/proxies/smart-proxy/models/index.js +5 -0
  133. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +107 -0
  134. package/dist_ts/proxies/smart-proxy/models/interfaces.js +2 -0
  135. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +62 -0
  136. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +316 -0
  137. package/dist_ts/proxies/smart-proxy/port-range-manager.d.ts +56 -0
  138. package/dist_ts/proxies/smart-proxy/port-range-manager.js +176 -0
  139. package/dist_ts/proxies/smart-proxy/security-manager.d.ts +64 -0
  140. package/dist_ts/proxies/smart-proxy/security-manager.js +149 -0
  141. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +63 -0
  142. package/dist_ts/proxies/smart-proxy/smart-proxy.js +523 -0
  143. package/dist_ts/proxies/smart-proxy/timeout-manager.d.ts +47 -0
  144. package/dist_ts/proxies/smart-proxy/timeout-manager.js +154 -0
  145. package/dist_ts/proxies/smart-proxy/tls-manager.d.ts +57 -0
  146. package/dist_ts/proxies/smart-proxy/tls-manager.js +132 -0
  147. package/dist_ts/smartproxy/classes.pp.networkproxybridge.d.ts +2 -2
  148. package/dist_ts/smartproxy/classes.pp.networkproxybridge.js +1 -1
  149. package/dist_ts/smartproxy/classes.pp.tlsmanager.js +2 -2
  150. package/dist_ts/smartproxy/classes.smartproxy.js +3 -3
  151. package/dist_ts/smartproxy/forwarding/index.d.ts +1 -1
  152. package/dist_ts/smartproxy/forwarding/index.js +2 -2
  153. package/dist_ts/tls/alerts/index.d.ts +4 -0
  154. package/dist_ts/tls/alerts/index.js +5 -0
  155. package/dist_ts/tls/alerts/tls-alert.d.ts +150 -0
  156. package/dist_ts/tls/alerts/tls-alert.js +226 -0
  157. package/dist_ts/tls/index.d.ts +18 -0
  158. package/dist_ts/tls/index.js +27 -0
  159. package/dist_ts/tls/sni/client-hello-parser.d.ts +100 -0
  160. package/dist_ts/tls/sni/client-hello-parser.js +463 -0
  161. package/dist_ts/tls/sni/index.d.ts +4 -0
  162. package/dist_ts/tls/sni/index.js +5 -0
  163. package/dist_ts/tls/sni/sni-extraction.d.ts +58 -0
  164. package/dist_ts/tls/sni/sni-extraction.js +275 -0
  165. package/dist_ts/tls/sni/sni-handler.d.ts +154 -0
  166. package/dist_ts/tls/sni/sni-handler.js +191 -0
  167. package/dist_ts/tls/utils/index.d.ts +4 -0
  168. package/dist_ts/tls/utils/index.js +5 -0
  169. package/dist_ts/tls/utils/tls-utils.d.ts +158 -0
  170. package/dist_ts/tls/utils/tls-utils.js +187 -0
  171. package/package.json +1 -1
  172. package/readme.md +89 -21
  173. package/readme.plan.md +253 -469
  174. package/ts/00_commitinfo_data.ts +1 -1
  175. package/ts/certificate/acme/acme-factory.ts +48 -0
  176. package/ts/certificate/acme/challenge-handler.ts +110 -0
  177. package/ts/certificate/acme/index.ts +3 -0
  178. package/ts/certificate/events/certificate-events.ts +36 -0
  179. package/ts/certificate/index.ts +67 -0
  180. package/ts/certificate/models/certificate-types.ts +88 -0
  181. package/ts/certificate/providers/cert-provisioner.ts +326 -0
  182. package/ts/certificate/providers/index.ts +3 -0
  183. package/ts/certificate/storage/file-storage.ts +234 -0
  184. package/ts/certificate/storage/index.ts +3 -0
  185. package/ts/certificate/utils/certificate-helpers.ts +50 -0
  186. package/ts/common/eventUtils.ts +1 -1
  187. package/ts/common/port80-adapter.ts +1 -1
  188. package/ts/core/events/index.ts +3 -0
  189. package/ts/core/index.ts +8 -0
  190. package/ts/core/models/common-types.ts +91 -0
  191. package/ts/core/models/index.ts +5 -0
  192. package/ts/core/utils/event-utils.ts +34 -0
  193. package/ts/core/utils/index.ts +7 -0
  194. package/ts/core/utils/ip-utils.ts +175 -0
  195. package/ts/core/utils/validation-utils.ts +177 -0
  196. package/ts/{smartproxy/forwarding → forwarding/config}/domain-config.ts +1 -1
  197. package/ts/{smartproxy/forwarding → forwarding/config}/domain-manager.ts +8 -8
  198. package/ts/{smartproxy/types/forwarding.types.ts → forwarding/config/forwarding-types.ts} +6 -6
  199. package/ts/forwarding/config/index.ts +7 -0
  200. package/ts/{smartproxy/forwarding/forwarding.factory.ts → forwarding/factory/forwarding-factory.ts} +12 -11
  201. package/ts/forwarding/factory/index.ts +5 -0
  202. package/ts/{smartproxy/forwarding/forwarding.handler.ts → forwarding/handlers/base-handler.ts} +2 -2
  203. package/ts/{smartproxy/forwarding/http.handler.ts → forwarding/handlers/http-handler.ts} +13 -4
  204. package/ts/{smartproxy/forwarding/https-passthrough.handler.ts → forwarding/handlers/https-passthrough-handler.ts} +13 -4
  205. package/ts/{smartproxy/forwarding/https-terminate-to-http.handler.ts → forwarding/handlers/https-terminate-to-http-handler.ts} +3 -3
  206. package/ts/{smartproxy/forwarding/https-terminate-to-https.handler.ts → forwarding/handlers/https-terminate-to-https-handler.ts} +3 -3
  207. package/ts/forwarding/handlers/index.ts +9 -0
  208. package/ts/forwarding/index.ts +34 -0
  209. package/ts/http/index.ts +23 -0
  210. package/ts/http/models/http-types.ts +105 -0
  211. package/ts/http/port80/acme-interfaces.ts +85 -0
  212. package/ts/http/port80/challenge-responder.ts +246 -0
  213. package/ts/http/port80/index.ts +13 -0
  214. package/ts/{port80handler/classes.port80handler.ts → http/port80/port80-handler.ts} +164 -161
  215. package/ts/http/redirects/index.ts +3 -0
  216. package/ts/http/router/index.ts +5 -0
  217. package/ts/{classes.router.ts → http/router/proxy-router.ts} +27 -20
  218. package/ts/index.ts +32 -9
  219. package/ts/plugins.ts +2 -1
  220. package/ts/proxies/index.ts +8 -0
  221. package/ts/{networkproxy/classes.np.certificatemanager.ts → proxies/network-proxy/certificate-manager.ts} +17 -16
  222. package/ts/{networkproxy/classes.np.connectionpool.ts → proxies/network-proxy/connection-pool.ts} +3 -3
  223. package/ts/proxies/network-proxy/index.ts +13 -0
  224. package/ts/proxies/network-proxy/models/index.ts +4 -0
  225. package/ts/{networkproxy/classes.np.types.ts → proxies/network-proxy/models/types.ts} +7 -11
  226. package/ts/{networkproxy/classes.np.networkproxy.ts → proxies/network-proxy/network-proxy.ts} +31 -24
  227. package/ts/{networkproxy/classes.np.requesthandler.ts → proxies/network-proxy/request-handler.ts} +12 -7
  228. package/ts/{networkproxy/classes.np.websockethandler.ts → proxies/network-proxy/websocket-handler.ts} +6 -6
  229. package/ts/proxies/nftables-proxy/index.ts +5 -0
  230. package/ts/proxies/nftables-proxy/models/errors.ts +30 -0
  231. package/ts/proxies/nftables-proxy/models/index.ts +5 -0
  232. package/ts/proxies/nftables-proxy/models/interfaces.ts +94 -0
  233. package/ts/{nfttablesproxy/classes.nftablesproxy.ts → proxies/nftables-proxy/nftables-proxy.ts} +24 -126
  234. package/ts/{smartproxy/classes.pp.connectionhandler.ts → proxies/smart-proxy/connection-handler.ts} +12 -12
  235. package/ts/{smartproxy/classes.pp.connectionmanager.ts → proxies/smart-proxy/connection-manager.ts} +8 -8
  236. package/ts/{smartproxy/classes.pp.domainconfigmanager.ts → proxies/smart-proxy/domain-config-manager.ts} +15 -14
  237. package/ts/proxies/smart-proxy/index.ts +18 -0
  238. package/ts/proxies/smart-proxy/models/index.ts +4 -0
  239. package/ts/{smartproxy/classes.pp.interfaces.ts → proxies/smart-proxy/models/interfaces.ts} +12 -8
  240. package/ts/{smartproxy/classes.pp.networkproxybridge.ts → proxies/smart-proxy/network-proxy-bridge.ts} +14 -14
  241. package/ts/{smartproxy/classes.pp.portrangemanager.ts → proxies/smart-proxy/port-range-manager.ts} +1 -1
  242. package/ts/{smartproxy/classes.pp.securitymanager.ts → proxies/smart-proxy/security-manager.ts} +3 -3
  243. package/ts/{smartproxy/classes.smartproxy.ts → proxies/smart-proxy/smart-proxy.ts} +29 -24
  244. package/ts/{smartproxy/classes.pp.timeoutmanager.ts → proxies/smart-proxy/timeout-manager.ts} +3 -3
  245. package/ts/{smartproxy/classes.pp.tlsmanager.ts → proxies/smart-proxy/tls-manager.ts} +3 -3
  246. package/ts/tls/alerts/index.ts +3 -0
  247. package/ts/{smartproxy/classes.pp.tlsalert.ts → tls/alerts/tls-alert.ts} +44 -43
  248. package/ts/tls/index.ts +33 -0
  249. package/ts/tls/sni/client-hello-parser.ts +629 -0
  250. package/ts/tls/sni/index.ts +3 -0
  251. package/ts/tls/sni/sni-extraction.ts +353 -0
  252. package/ts/tls/sni/sni-handler.ts +264 -0
  253. package/ts/tls/utils/index.ts +3 -0
  254. package/ts/tls/utils/tls-utils.ts +201 -0
  255. package/ts/common/acmeFactory.ts +0 -23
  256. package/ts/examples/forwarding-example.ts +0 -128
  257. package/ts/helpers.certificates.ts +0 -30
  258. package/ts/networkproxy/index.ts +0 -7
  259. package/ts/smartproxy/classes.pp.certprovisioner.ts +0 -200
  260. package/ts/smartproxy/classes.pp.snihandler.ts +0 -1281
  261. package/ts/smartproxy/forwarding/index.ts +0 -52
@@ -0,0 +1,275 @@
1
+ import { Buffer } from 'buffer';
2
+ import { TlsExtensionType, TlsUtils } from '../utils/tls-utils.js';
3
+ import { ClientHelloParser } from './client-hello-parser.js';
4
+ /**
5
+ * Utilities for extracting SNI information from TLS handshakes
6
+ */
7
+ export class SniExtraction {
8
+ /**
9
+ * Extracts the SNI (Server Name Indication) from a TLS ClientHello message.
10
+ *
11
+ * @param buffer The buffer containing the TLS ClientHello message
12
+ * @param logger Optional logging function
13
+ * @returns The extracted server name or undefined if not found
14
+ */
15
+ static extractSNI(buffer, logger) {
16
+ const log = logger || (() => { });
17
+ try {
18
+ // Parse the ClientHello
19
+ const parseResult = ClientHelloParser.parseClientHello(buffer, logger);
20
+ if (!parseResult.isValid) {
21
+ log(`Failed to parse ClientHello: ${parseResult.error}`);
22
+ return undefined;
23
+ }
24
+ // Check if ServerName extension was found
25
+ if (parseResult.serverNameList && parseResult.serverNameList.length > 0) {
26
+ // Use the first hostname (most common case)
27
+ const serverName = parseResult.serverNameList[0];
28
+ log(`Found SNI: ${serverName}`);
29
+ return serverName;
30
+ }
31
+ log('No SNI extension found in ClientHello');
32
+ return undefined;
33
+ }
34
+ catch (error) {
35
+ log(`Error extracting SNI: ${error instanceof Error ? error.message : String(error)}`);
36
+ return undefined;
37
+ }
38
+ }
39
+ /**
40
+ * Attempts to extract SNI from the PSK extension in a TLS 1.3 ClientHello.
41
+ *
42
+ * In TLS 1.3, when a client attempts to resume a session, it may include
43
+ * the server name in the PSK identity hint rather than in the SNI extension.
44
+ *
45
+ * @param buffer The buffer containing the TLS ClientHello message
46
+ * @param logger Optional logging function
47
+ * @returns The extracted server name or undefined if not found
48
+ */
49
+ static extractSNIFromPSKExtension(buffer, logger) {
50
+ const log = logger || (() => { });
51
+ try {
52
+ // Ensure this is a ClientHello
53
+ if (!TlsUtils.isClientHello(buffer)) {
54
+ log('Not a ClientHello message');
55
+ return undefined;
56
+ }
57
+ // Parse the ClientHello to find PSK extension
58
+ const parseResult = ClientHelloParser.parseClientHello(buffer, logger);
59
+ if (!parseResult.isValid || !parseResult.extensions) {
60
+ return undefined;
61
+ }
62
+ // Find the PSK extension
63
+ const pskExtension = parseResult.extensions.find(ext => ext.type === TlsExtensionType.PRE_SHARED_KEY);
64
+ if (!pskExtension) {
65
+ log('No PSK extension found');
66
+ return undefined;
67
+ }
68
+ // Parse the PSK extension data
69
+ const data = pskExtension.data;
70
+ // PSK extension structure:
71
+ // 2 bytes: identities list length
72
+ if (data.length < 2)
73
+ return undefined;
74
+ const identitiesLength = (data[0] << 8) + data[1];
75
+ let pos = 2;
76
+ // End of identities list
77
+ const identitiesEnd = pos + identitiesLength;
78
+ if (identitiesEnd > data.length)
79
+ return undefined;
80
+ // Process each PSK identity
81
+ while (pos + 2 <= identitiesEnd) {
82
+ // Identity length (2 bytes)
83
+ if (pos + 2 > identitiesEnd)
84
+ break;
85
+ const identityLength = (data[pos] << 8) + data[pos + 1];
86
+ pos += 2;
87
+ if (pos + identityLength > identitiesEnd)
88
+ break;
89
+ // Try to extract hostname from identity
90
+ // Chrome often embeds the hostname in the PSK identity
91
+ // This is a heuristic as there's no standard format
92
+ if (identityLength > 0) {
93
+ const identity = data.slice(pos, pos + identityLength);
94
+ // Skip identity bytes
95
+ pos += identityLength;
96
+ // Skip obfuscated ticket age (4 bytes)
97
+ if (pos + 4 <= identitiesEnd) {
98
+ pos += 4;
99
+ }
100
+ else {
101
+ break;
102
+ }
103
+ // Try to parse the identity as UTF-8
104
+ try {
105
+ const identityStr = identity.toString('utf8');
106
+ log(`PSK identity: ${identityStr}`);
107
+ // Check if the identity contains hostname hints
108
+ // Chrome often embeds the hostname in a known format
109
+ // Try to extract using common patterns
110
+ // Pattern 1: Look for domain name pattern
111
+ const domainPattern = /([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?/i;
112
+ const domainMatch = identityStr.match(domainPattern);
113
+ if (domainMatch && domainMatch[0]) {
114
+ log(`Found domain in PSK identity: ${domainMatch[0]}`);
115
+ return domainMatch[0];
116
+ }
117
+ // Pattern 2: Chrome sometimes uses a specific format with delimiters
118
+ // This is a heuristic approach since the format isn't standardized
119
+ const parts = identityStr.split('|');
120
+ if (parts.length > 1) {
121
+ for (const part of parts) {
122
+ if (part.includes('.') && !part.includes('/')) {
123
+ const possibleDomain = part.trim();
124
+ if (/^[a-z0-9.-]+$/i.test(possibleDomain)) {
125
+ log(`Found possible domain in PSK delimiter format: ${possibleDomain}`);
126
+ return possibleDomain;
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ catch (e) {
133
+ log('Failed to parse PSK identity as UTF-8');
134
+ }
135
+ }
136
+ }
137
+ log('No hostname found in PSK extension');
138
+ return undefined;
139
+ }
140
+ catch (error) {
141
+ log(`Error parsing PSK: ${error instanceof Error ? error.message : String(error)}`);
142
+ return undefined;
143
+ }
144
+ }
145
+ /**
146
+ * Main entry point for SNI extraction with support for fragmented messages
147
+ * and session resumption edge cases.
148
+ *
149
+ * @param buffer The buffer containing TLS data
150
+ * @param connectionInfo Connection tracking information
151
+ * @param logger Optional logging function
152
+ * @param cachedSni Optional previously cached SNI value
153
+ * @returns The extracted server name or undefined
154
+ */
155
+ static extractSNIWithResumptionSupport(buffer, connectionInfo, logger, cachedSni) {
156
+ const log = logger || (() => { });
157
+ // Log buffer details for debugging
158
+ if (logger) {
159
+ log(`Buffer size: ${buffer.length} bytes`);
160
+ log(`Buffer starts with: ${buffer.slice(0, Math.min(10, buffer.length)).toString('hex')}`);
161
+ if (buffer.length >= 5) {
162
+ const recordType = buffer[0];
163
+ const majorVersion = buffer[1];
164
+ const minorVersion = buffer[2];
165
+ const recordLength = (buffer[3] << 8) + buffer[4];
166
+ log(`TLS Record: type=${recordType}, version=${majorVersion}.${minorVersion}, length=${recordLength}`);
167
+ }
168
+ }
169
+ // Check if we need to handle fragmented packets
170
+ let processBuffer = buffer;
171
+ if (connectionInfo) {
172
+ const connectionId = TlsUtils.createConnectionId(connectionInfo);
173
+ const reassembledBuffer = ClientHelloParser.handleFragmentedClientHello(buffer, connectionId, logger);
174
+ if (!reassembledBuffer) {
175
+ log(`Waiting for more fragments on connection ${connectionId}`);
176
+ return undefined; // Need more fragments to complete ClientHello
177
+ }
178
+ processBuffer = reassembledBuffer;
179
+ log(`Using reassembled buffer of length ${processBuffer.length}`);
180
+ }
181
+ // First try the standard SNI extraction
182
+ const standardSni = this.extractSNI(processBuffer, logger);
183
+ if (standardSni) {
184
+ log(`Found standard SNI: ${standardSni}`);
185
+ return standardSni;
186
+ }
187
+ // Check for session resumption when standard SNI extraction fails
188
+ if (TlsUtils.isClientHello(processBuffer)) {
189
+ const resumptionInfo = ClientHelloParser.hasSessionResumption(processBuffer, logger);
190
+ if (resumptionInfo.isResumption) {
191
+ log(`Detected session resumption in ClientHello without standard SNI`);
192
+ // Try to extract SNI from PSK extension
193
+ const pskSni = this.extractSNIFromPSKExtension(processBuffer, logger);
194
+ if (pskSni) {
195
+ log(`Extracted SNI from PSK extension: ${pskSni}`);
196
+ return pskSni;
197
+ }
198
+ }
199
+ }
200
+ // If cached SNI was provided, use it for application data packets
201
+ if (cachedSni && TlsUtils.isTlsApplicationData(buffer)) {
202
+ log(`Using provided cached SNI for application data: ${cachedSni}`);
203
+ return cachedSni;
204
+ }
205
+ return undefined;
206
+ }
207
+ /**
208
+ * Unified method for processing a TLS packet and extracting SNI.
209
+ * Main entry point for SNI extraction that handles all edge cases.
210
+ *
211
+ * @param buffer The buffer containing TLS data
212
+ * @param connectionInfo Connection tracking information
213
+ * @param logger Optional logging function
214
+ * @param cachedSni Optional previously cached SNI value
215
+ * @returns The extracted server name or undefined
216
+ */
217
+ static processTlsPacket(buffer, connectionInfo, logger, cachedSni) {
218
+ const log = logger || (() => { });
219
+ // Add timestamp if not provided
220
+ if (!connectionInfo.timestamp) {
221
+ connectionInfo.timestamp = Date.now();
222
+ }
223
+ // Check if this is a TLS handshake or application data
224
+ if (!TlsUtils.isTlsHandshake(buffer) && !TlsUtils.isTlsApplicationData(buffer)) {
225
+ log('Not a TLS handshake or application data packet');
226
+ return undefined;
227
+ }
228
+ // Create connection ID for tracking
229
+ const connectionId = TlsUtils.createConnectionId(connectionInfo);
230
+ log(`Processing TLS packet for connection ${connectionId}, buffer length: ${buffer.length}`);
231
+ // Handle application data with cached SNI (for connection racing)
232
+ if (TlsUtils.isTlsApplicationData(buffer)) {
233
+ // If explicit cachedSni was provided, use it
234
+ if (cachedSni) {
235
+ log(`Using provided cached SNI for application data: ${cachedSni}`);
236
+ return cachedSni;
237
+ }
238
+ log('Application data packet without cached SNI, cannot determine hostname');
239
+ return undefined;
240
+ }
241
+ // Enhanced session resumption detection
242
+ if (TlsUtils.isClientHello(buffer)) {
243
+ const resumptionInfo = ClientHelloParser.hasSessionResumption(buffer, logger);
244
+ if (resumptionInfo.isResumption) {
245
+ log(`Session resumption detected in TLS packet`);
246
+ // Always try standard SNI extraction first
247
+ const standardSni = this.extractSNI(buffer, logger);
248
+ if (standardSni) {
249
+ log(`Found standard SNI in session resumption: ${standardSni}`);
250
+ return standardSni;
251
+ }
252
+ // Enhanced session resumption SNI extraction
253
+ // Try extracting from PSK identity
254
+ const pskSni = this.extractSNIFromPSKExtension(buffer, logger);
255
+ if (pskSni) {
256
+ log(`Extracted SNI from PSK extension: ${pskSni}`);
257
+ return pskSni;
258
+ }
259
+ log(`Session resumption without extractable SNI`);
260
+ }
261
+ }
262
+ // For handshake messages, try the full extraction process
263
+ const sni = this.extractSNIWithResumptionSupport(buffer, connectionInfo, logger);
264
+ if (sni) {
265
+ log(`Successfully extracted SNI: ${sni}`);
266
+ return sni;
267
+ }
268
+ // If we couldn't extract an SNI, check if this is a valid ClientHello
269
+ if (TlsUtils.isClientHello(buffer)) {
270
+ log('Valid ClientHello detected, but no SNI extracted - might need more data');
271
+ }
272
+ return undefined;
273
+ }
274
+ }
275
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25pLWV4dHJhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90bHMvc25pL3NuaS1leHRyYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDaEMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ25FLE9BQU8sRUFDTCxpQkFBaUIsRUFFbEIsTUFBTSwwQkFBMEIsQ0FBQztBQWFsQzs7R0FFRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBQ3hCOzs7Ozs7T0FNRztJQUNJLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBYyxFQUFFLE1BQXVCO1FBQzlELE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO1FBRWpDLElBQUksQ0FBQztZQUNILHdCQUF3QjtZQUN4QixNQUFNLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDdkUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDekIsR0FBRyxDQUFDLGdDQUFnQyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDekQsT0FBTyxTQUFTLENBQUM7WUFDbkIsQ0FBQztZQUVELDBDQUEwQztZQUMxQyxJQUFJLFdBQVcsQ0FBQyxjQUFjLElBQUksV0FBVyxDQUFDLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3hFLDRDQUE0QztnQkFDNUMsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDakQsR0FBRyxDQUFDLGNBQWMsVUFBVSxFQUFFLENBQUMsQ0FBQztnQkFDaEMsT0FBTyxVQUFVLENBQUM7WUFDcEIsQ0FBQztZQUVELEdBQUcsQ0FB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
@@ -0,0 +1,154 @@
1
+ import { Buffer } from 'buffer';
2
+ /**
3
+ * SNI (Server Name Indication) handler for TLS connections.
4
+ * Provides robust extraction of SNI values from TLS ClientHello messages
5
+ * with support for fragmented packets, TLS 1.3 resumption, Chrome-specific
6
+ * connection behaviors, and tab hibernation/reactivation scenarios.
7
+ *
8
+ * This class retains the original API but leverages the new modular implementation
9
+ * for better maintainability and testability.
10
+ */
11
+ export declare class SniHandler {
12
+ private static readonly TLS_HANDSHAKE_RECORD_TYPE;
13
+ private static readonly TLS_APPLICATION_DATA_TYPE;
14
+ private static readonly TLS_CLIENT_HELLO_HANDSHAKE_TYPE;
15
+ private static readonly TLS_SNI_EXTENSION_TYPE;
16
+ private static readonly TLS_SESSION_TICKET_EXTENSION_TYPE;
17
+ private static readonly TLS_SNI_HOST_NAME_TYPE;
18
+ private static readonly TLS_PSK_EXTENSION_TYPE;
19
+ private static readonly TLS_PSK_KE_MODES_EXTENSION_TYPE;
20
+ private static readonly TLS_EARLY_DATA_EXTENSION_TYPE;
21
+ /**
22
+ * Checks if a buffer contains a TLS handshake message (record type 22)
23
+ * @param buffer - The buffer to check
24
+ * @returns true if the buffer starts with a TLS handshake record type
25
+ */
26
+ static isTlsHandshake(buffer: Buffer): boolean;
27
+ /**
28
+ * Checks if a buffer contains TLS application data (record type 23)
29
+ * @param buffer - The buffer to check
30
+ * @returns true if the buffer starts with a TLS application data record type
31
+ */
32
+ static isTlsApplicationData(buffer: Buffer): boolean;
33
+ /**
34
+ * Creates a connection ID based on source/destination information
35
+ * Used to track fragmented ClientHello messages across multiple packets
36
+ *
37
+ * @param connectionInfo - Object containing connection identifiers (IP/port)
38
+ * @returns A string ID for the connection
39
+ */
40
+ static createConnectionId(connectionInfo: {
41
+ sourceIp?: string;
42
+ sourcePort?: number;
43
+ destIp?: string;
44
+ destPort?: number;
45
+ }): string;
46
+ /**
47
+ * Handles potential fragmented ClientHello messages by buffering and reassembling
48
+ * TLS record fragments that might span multiple TCP packets.
49
+ *
50
+ * @param buffer - The current buffer fragment
51
+ * @param connectionId - Unique identifier for the connection
52
+ * @param enableLogging - Whether to enable logging
53
+ * @returns A complete buffer if reassembly is successful, or undefined if more fragments are needed
54
+ */
55
+ static handleFragmentedClientHello(buffer: Buffer, connectionId: string, enableLogging?: boolean): Buffer | undefined;
56
+ /**
57
+ * Checks if a buffer contains a TLS ClientHello message
58
+ * @param buffer - The buffer to check
59
+ * @returns true if the buffer appears to be a ClientHello message
60
+ */
61
+ static isClientHello(buffer: Buffer): boolean;
62
+ /**
63
+ * Checks if a ClientHello message contains session resumption indicators
64
+ * such as session tickets or PSK (Pre-Shared Key) extensions.
65
+ *
66
+ * @param buffer - The buffer containing a ClientHello message
67
+ * @param enableLogging - Whether to enable logging
68
+ * @returns Object containing details about session resumption and SNI presence
69
+ */
70
+ static hasSessionResumption(buffer: Buffer, enableLogging?: boolean): {
71
+ isResumption: boolean;
72
+ hasSNI: boolean;
73
+ };
74
+ /**
75
+ * Detects characteristics of a tab reactivation TLS handshake
76
+ * These often have specific patterns in Chrome and other browsers
77
+ *
78
+ * @param buffer - The buffer containing a ClientHello message
79
+ * @param enableLogging - Whether to enable logging
80
+ * @returns true if this appears to be a tab reactivation handshake
81
+ */
82
+ static isTabReactivationHandshake(buffer: Buffer, enableLogging?: boolean): boolean;
83
+ /**
84
+ * Extracts the SNI (Server Name Indication) from a TLS ClientHello message.
85
+ * Implements robust parsing with support for session resumption edge cases.
86
+ *
87
+ * @param buffer - The buffer containing the TLS ClientHello message
88
+ * @param enableLogging - Whether to enable detailed debug logging
89
+ * @returns The extracted server name or undefined if not found
90
+ */
91
+ static extractSNI(buffer: Buffer, enableLogging?: boolean): string | undefined;
92
+ /**
93
+ * Attempts to extract SNI from the PSK extension in a TLS 1.3 ClientHello.
94
+ *
95
+ * In TLS 1.3, when a client attempts to resume a session, it may include
96
+ * the server name in the PSK identity hint rather than in the SNI extension.
97
+ *
98
+ * @param buffer - The buffer containing the TLS ClientHello message
99
+ * @param enableLogging - Whether to enable detailed debug logging
100
+ * @returns The extracted server name or undefined if not found
101
+ */
102
+ static extractSNIFromPSKExtension(buffer: Buffer, enableLogging?: boolean): string | undefined;
103
+ /**
104
+ * Checks if the buffer contains TLS 1.3 early data (0-RTT)
105
+ * @param buffer - The buffer to check
106
+ * @param enableLogging - Whether to enable logging
107
+ * @returns true if early data is detected
108
+ */
109
+ static hasEarlyData(buffer: Buffer, enableLogging?: boolean): boolean;
110
+ /**
111
+ * Attempts to extract SNI from an initial ClientHello packet and handles
112
+ * session resumption edge cases more robustly than the standard extraction.
113
+ *
114
+ * This method handles:
115
+ * 1. Standard SNI extraction
116
+ * 2. TLS 1.3 PSK-based resumption (Chrome, Firefox, etc.)
117
+ * 3. Session ticket-based resumption
118
+ * 4. Fragmented ClientHello messages
119
+ * 5. TLS 1.3 Early Data (0-RTT)
120
+ * 6. Chrome's connection racing behaviors
121
+ *
122
+ * @param buffer - The buffer containing the TLS ClientHello message
123
+ * @param connectionInfo - Optional connection information for fragment handling
124
+ * @param enableLogging - Whether to enable detailed debug logging
125
+ * @returns The extracted server name or undefined if not found or more data needed
126
+ */
127
+ static extractSNIWithResumptionSupport(buffer: Buffer, connectionInfo?: {
128
+ sourceIp?: string;
129
+ sourcePort?: number;
130
+ destIp?: string;
131
+ destPort?: number;
132
+ }, enableLogging?: boolean): string | undefined;
133
+ /**
134
+ * Main entry point for SNI extraction that handles all edge cases.
135
+ * This should be called for each TLS packet received from a client.
136
+ *
137
+ * The method uses connection tracking to handle fragmented ClientHello
138
+ * messages and various TLS 1.3 behaviors, including Chrome's connection
139
+ * racing patterns and tab reactivation behaviors.
140
+ *
141
+ * @param buffer - The buffer containing TLS data
142
+ * @param connectionInfo - Connection metadata (IPs and ports)
143
+ * @param enableLogging - Whether to enable detailed debug logging
144
+ * @param cachedSni - Optional cached SNI from previous connections (for racing detection)
145
+ * @returns The extracted server name or undefined if not found or more data needed
146
+ */
147
+ static processTlsPacket(buffer: Buffer, connectionInfo: {
148
+ sourceIp: string;
149
+ sourcePort: number;
150
+ destIp: string;
151
+ destPort: number;
152
+ timestamp?: number;
153
+ }, enableLogging?: boolean, cachedSni?: string): string | undefined;
154
+ }
@@ -0,0 +1,191 @@
1
+ import { Buffer } from 'buffer';
2
+ import { TlsRecordType, TlsHandshakeType, TlsExtensionType, TlsUtils } from '../utils/tls-utils.js';
3
+ import { ClientHelloParser } from './client-hello-parser.js';
4
+ import { SniExtraction } from './sni-extraction.js';
5
+ /**
6
+ * SNI (Server Name Indication) handler for TLS connections.
7
+ * Provides robust extraction of SNI values from TLS ClientHello messages
8
+ * with support for fragmented packets, TLS 1.3 resumption, Chrome-specific
9
+ * connection behaviors, and tab hibernation/reactivation scenarios.
10
+ *
11
+ * This class retains the original API but leverages the new modular implementation
12
+ * for better maintainability and testability.
13
+ */
14
+ export class SniHandler {
15
+ // Re-export constants for backward compatibility
16
+ static { this.TLS_HANDSHAKE_RECORD_TYPE = TlsRecordType.HANDSHAKE; }
17
+ static { this.TLS_APPLICATION_DATA_TYPE = TlsRecordType.APPLICATION_DATA; }
18
+ static { this.TLS_CLIENT_HELLO_HANDSHAKE_TYPE = TlsHandshakeType.CLIENT_HELLO; }
19
+ static { this.TLS_SNI_EXTENSION_TYPE = TlsExtensionType.SERVER_NAME; }
20
+ static { this.TLS_SESSION_TICKET_EXTENSION_TYPE = TlsExtensionType.SESSION_TICKET; }
21
+ static { this.TLS_SNI_HOST_NAME_TYPE = 0; } // NameType.HOST_NAME in RFC 6066
22
+ static { this.TLS_PSK_EXTENSION_TYPE = TlsExtensionType.PRE_SHARED_KEY; }
23
+ static { this.TLS_PSK_KE_MODES_EXTENSION_TYPE = TlsExtensionType.PSK_KEY_EXCHANGE_MODES; }
24
+ static { this.TLS_EARLY_DATA_EXTENSION_TYPE = TlsExtensionType.EARLY_DATA; }
25
+ /**
26
+ * Checks if a buffer contains a TLS handshake message (record type 22)
27
+ * @param buffer - The buffer to check
28
+ * @returns true if the buffer starts with a TLS handshake record type
29
+ */
30
+ static isTlsHandshake(buffer) {
31
+ return TlsUtils.isTlsHandshake(buffer);
32
+ }
33
+ /**
34
+ * Checks if a buffer contains TLS application data (record type 23)
35
+ * @param buffer - The buffer to check
36
+ * @returns true if the buffer starts with a TLS application data record type
37
+ */
38
+ static isTlsApplicationData(buffer) {
39
+ return TlsUtils.isTlsApplicationData(buffer);
40
+ }
41
+ /**
42
+ * Creates a connection ID based on source/destination information
43
+ * Used to track fragmented ClientHello messages across multiple packets
44
+ *
45
+ * @param connectionInfo - Object containing connection identifiers (IP/port)
46
+ * @returns A string ID for the connection
47
+ */
48
+ static createConnectionId(connectionInfo) {
49
+ return TlsUtils.createConnectionId(connectionInfo);
50
+ }
51
+ /**
52
+ * Handles potential fragmented ClientHello messages by buffering and reassembling
53
+ * TLS record fragments that might span multiple TCP packets.
54
+ *
55
+ * @param buffer - The current buffer fragment
56
+ * @param connectionId - Unique identifier for the connection
57
+ * @param enableLogging - Whether to enable logging
58
+ * @returns A complete buffer if reassembly is successful, or undefined if more fragments are needed
59
+ */
60
+ static handleFragmentedClientHello(buffer, connectionId, enableLogging = false) {
61
+ const logger = enableLogging ?
62
+ (message) => console.log(`[SNI Fragment] ${message}`) :
63
+ undefined;
64
+ return ClientHelloParser.handleFragmentedClientHello(buffer, connectionId, logger);
65
+ }
66
+ /**
67
+ * Checks if a buffer contains a TLS ClientHello message
68
+ * @param buffer - The buffer to check
69
+ * @returns true if the buffer appears to be a ClientHello message
70
+ */
71
+ static isClientHello(buffer) {
72
+ return TlsUtils.isClientHello(buffer);
73
+ }
74
+ /**
75
+ * Checks if a ClientHello message contains session resumption indicators
76
+ * such as session tickets or PSK (Pre-Shared Key) extensions.
77
+ *
78
+ * @param buffer - The buffer containing a ClientHello message
79
+ * @param enableLogging - Whether to enable logging
80
+ * @returns Object containing details about session resumption and SNI presence
81
+ */
82
+ static hasSessionResumption(buffer, enableLogging = false) {
83
+ const logger = enableLogging ?
84
+ (message) => console.log(`[Session Resumption] ${message}`) :
85
+ undefined;
86
+ return ClientHelloParser.hasSessionResumption(buffer, logger);
87
+ }
88
+ /**
89
+ * Detects characteristics of a tab reactivation TLS handshake
90
+ * These often have specific patterns in Chrome and other browsers
91
+ *
92
+ * @param buffer - The buffer containing a ClientHello message
93
+ * @param enableLogging - Whether to enable logging
94
+ * @returns true if this appears to be a tab reactivation handshake
95
+ */
96
+ static isTabReactivationHandshake(buffer, enableLogging = false) {
97
+ const logger = enableLogging ?
98
+ (message) => console.log(`[Tab Reactivation] ${message}`) :
99
+ undefined;
100
+ return ClientHelloParser.isTabReactivationHandshake(buffer, logger);
101
+ }
102
+ /**
103
+ * Extracts the SNI (Server Name Indication) from a TLS ClientHello message.
104
+ * Implements robust parsing with support for session resumption edge cases.
105
+ *
106
+ * @param buffer - The buffer containing the TLS ClientHello message
107
+ * @param enableLogging - Whether to enable detailed debug logging
108
+ * @returns The extracted server name or undefined if not found
109
+ */
110
+ static extractSNI(buffer, enableLogging = false) {
111
+ const logger = enableLogging ?
112
+ (message) => console.log(`[SNI Extraction] ${message}`) :
113
+ undefined;
114
+ return SniExtraction.extractSNI(buffer, logger);
115
+ }
116
+ /**
117
+ * Attempts to extract SNI from the PSK extension in a TLS 1.3 ClientHello.
118
+ *
119
+ * In TLS 1.3, when a client attempts to resume a session, it may include
120
+ * the server name in the PSK identity hint rather than in the SNI extension.
121
+ *
122
+ * @param buffer - The buffer containing the TLS ClientHello message
123
+ * @param enableLogging - Whether to enable detailed debug logging
124
+ * @returns The extracted server name or undefined if not found
125
+ */
126
+ static extractSNIFromPSKExtension(buffer, enableLogging = false) {
127
+ const logger = enableLogging ?
128
+ (message) => console.log(`[PSK-SNI Extraction] ${message}`) :
129
+ undefined;
130
+ return SniExtraction.extractSNIFromPSKExtension(buffer, logger);
131
+ }
132
+ /**
133
+ * Checks if the buffer contains TLS 1.3 early data (0-RTT)
134
+ * @param buffer - The buffer to check
135
+ * @param enableLogging - Whether to enable logging
136
+ * @returns true if early data is detected
137
+ */
138
+ static hasEarlyData(buffer, enableLogging = false) {
139
+ // This functionality has been moved to ClientHelloParser
140
+ // We can implement it in terms of the parse result if needed
141
+ const logger = enableLogging ?
142
+ (message) => console.log(`[Early Data] ${message}`) :
143
+ undefined;
144
+ const parseResult = ClientHelloParser.parseClientHello(buffer, logger);
145
+ return parseResult.isValid && parseResult.hasEarlyData;
146
+ }
147
+ /**
148
+ * Attempts to extract SNI from an initial ClientHello packet and handles
149
+ * session resumption edge cases more robustly than the standard extraction.
150
+ *
151
+ * This method handles:
152
+ * 1. Standard SNI extraction
153
+ * 2. TLS 1.3 PSK-based resumption (Chrome, Firefox, etc.)
154
+ * 3. Session ticket-based resumption
155
+ * 4. Fragmented ClientHello messages
156
+ * 5. TLS 1.3 Early Data (0-RTT)
157
+ * 6. Chrome's connection racing behaviors
158
+ *
159
+ * @param buffer - The buffer containing the TLS ClientHello message
160
+ * @param connectionInfo - Optional connection information for fragment handling
161
+ * @param enableLogging - Whether to enable detailed debug logging
162
+ * @returns The extracted server name or undefined if not found or more data needed
163
+ */
164
+ static extractSNIWithResumptionSupport(buffer, connectionInfo, enableLogging = false) {
165
+ const logger = enableLogging ?
166
+ (message) => console.log(`[SNI Extraction] ${message}`) :
167
+ undefined;
168
+ return SniExtraction.extractSNIWithResumptionSupport(buffer, connectionInfo, logger);
169
+ }
170
+ /**
171
+ * Main entry point for SNI extraction that handles all edge cases.
172
+ * This should be called for each TLS packet received from a client.
173
+ *
174
+ * The method uses connection tracking to handle fragmented ClientHello
175
+ * messages and various TLS 1.3 behaviors, including Chrome's connection
176
+ * racing patterns and tab reactivation behaviors.
177
+ *
178
+ * @param buffer - The buffer containing TLS data
179
+ * @param connectionInfo - Connection metadata (IPs and ports)
180
+ * @param enableLogging - Whether to enable detailed debug logging
181
+ * @param cachedSni - Optional cached SNI from previous connections (for racing detection)
182
+ * @returns The extracted server name or undefined if not found or more data needed
183
+ */
184
+ static processTlsPacket(buffer, connectionInfo, enableLogging = false, cachedSni) {
185
+ const logger = enableLogging ?
186
+ (message) => console.log(`[TLS Packet] ${message}`) :
187
+ undefined;
188
+ return SniExtraction.processTlsPacket(buffer, connectionInfo, logger, cachedSni);
189
+ }
190
+ }
191
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25pLWhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90bHMvc25pL3NuaS1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDaEMsT0FBTyxFQUNMLGFBQWEsRUFDYixnQkFBZ0IsRUFDaEIsZ0JBQWdCLEVBQ2hCLFFBQVEsRUFDVCxNQUFNLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sRUFDTCxpQkFBaUIsRUFFbEIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQ0wsYUFBYSxFQUVkLE1BQU0scUJBQXFCLENBQUM7QUFFN0I7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQUNyQixpREFBaUQ7YUFDekIsOEJBQXlCLEdBQUcsYUFBYSxDQUFDLFNBQVMsQ0FBQzthQUNwRCw4QkFBeUIsR0FBRyxhQUFhLENBQUMsZ0JBQWdCLENBQUM7YUFDM0Qsb0NBQStCLEdBQUcsZ0JBQWdCLENBQUMsWUFBWSxDQUFDO2FBQ2hFLDJCQUFzQixHQUFHLGdCQUFnQixDQUFDLFdBQVcsQ0FBQzthQUN0RCxzQ0FBaUMsR0FBRyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUM7YUFDcEUsMkJBQXNCLEdBQUcsQ0FBQyxDQUFDLEdBQUMsaUNBQWlDO2FBQzdELDJCQUFzQixHQUFHLGdCQUFnQixDQUFDLGNBQWMsQ0FBQzthQUN6RCxvQ0FBK0IsR0FBRyxnQkFBZ0IsQ0FBQyxzQkFBc0IsQ0FBQzthQUMxRSxrQ0FBNkIsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUM7SUFFcEY7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBYztRQUN6QyxPQUFPLFFBQVEsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsb0JBQW9CLENBQUMsTUFBYztRQUMvQyxPQUFP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
@@ -0,0 +1,4 @@
1
+ export {};
2
+ /**
3
+ * TLS utilities
4
+ */
@@ -0,0 +1,5 @@
1
+ export {};
2
+ /**
3
+ * TLS utilities
4
+ */
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90bHMvdXRpbHMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHIn0=