@push.rocks/smartproxy 3.41.7 → 4.0.0

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 (44) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/classes.portproxy.js +83 -69
  3. package/dist_ts/classes.pp.acmemanager.d.ts +34 -0
  4. package/dist_ts/classes.pp.acmemanager.js +123 -0
  5. package/dist_ts/classes.pp.connectionhandler.d.ts +39 -0
  6. package/dist_ts/classes.pp.connectionhandler.js +693 -0
  7. package/dist_ts/classes.pp.connectionmanager.d.ts +78 -0
  8. package/dist_ts/classes.pp.connectionmanager.js +378 -0
  9. package/dist_ts/classes.pp.domainconfigmanager.d.ts +55 -0
  10. package/dist_ts/classes.pp.domainconfigmanager.js +103 -0
  11. package/dist_ts/classes.pp.interfaces.d.ts +109 -0
  12. package/dist_ts/classes.pp.interfaces.js +2 -0
  13. package/dist_ts/classes.pp.networkproxybridge.d.ts +43 -0
  14. package/dist_ts/classes.pp.networkproxybridge.js +211 -0
  15. package/dist_ts/classes.pp.portproxy.d.ts +48 -0
  16. package/dist_ts/classes.pp.portproxy.js +268 -0
  17. package/dist_ts/classes.pp.portrangemanager.d.ts +56 -0
  18. package/dist_ts/classes.pp.portrangemanager.js +179 -0
  19. package/dist_ts/classes.pp.securitymanager.d.ts +47 -0
  20. package/dist_ts/classes.pp.securitymanager.js +126 -0
  21. package/dist_ts/classes.pp.snihandler.d.ts +160 -0
  22. package/dist_ts/classes.pp.snihandler.js +1073 -0
  23. package/dist_ts/classes.pp.timeoutmanager.d.ts +47 -0
  24. package/dist_ts/classes.pp.timeoutmanager.js +154 -0
  25. package/dist_ts/classes.pp.tlsmanager.d.ts +57 -0
  26. package/dist_ts/classes.pp.tlsmanager.js +132 -0
  27. package/dist_ts/index.d.ts +2 -2
  28. package/dist_ts/index.js +3 -3
  29. package/package.json +1 -1
  30. package/ts/00_commitinfo_data.ts +1 -1
  31. package/ts/classes.pp.acmemanager.ts +149 -0
  32. package/ts/classes.pp.connectionhandler.ts +982 -0
  33. package/ts/classes.pp.connectionmanager.ts +446 -0
  34. package/ts/classes.pp.domainconfigmanager.ts +123 -0
  35. package/ts/classes.pp.interfaces.ts +136 -0
  36. package/ts/classes.pp.networkproxybridge.ts +258 -0
  37. package/ts/classes.pp.portproxy.ts +344 -0
  38. package/ts/classes.pp.portrangemanager.ts +214 -0
  39. package/ts/classes.pp.securitymanager.ts +147 -0
  40. package/ts/{classes.snihandler.ts → classes.pp.snihandler.ts} +2 -169
  41. package/ts/classes.pp.timeoutmanager.ts +190 -0
  42. package/ts/classes.pp.tlsmanager.ts +206 -0
  43. package/ts/index.ts +2 -2
  44. package/ts/classes.portproxy.ts +0 -2496
@@ -0,0 +1,214 @@
1
+ import type{ IPortProxySettings } from './classes.pp.interfaces.js';
2
+
3
+ /**
4
+ * Manages port ranges and port-based configuration
5
+ */
6
+ export class PortRangeManager {
7
+ constructor(private settings: IPortProxySettings) {}
8
+
9
+ /**
10
+ * Get all ports that should be listened on
11
+ */
12
+ public getListeningPorts(): Set<number> {
13
+ const listeningPorts = new Set<number>();
14
+
15
+ // Always include the main fromPort
16
+ listeningPorts.add(this.settings.fromPort);
17
+
18
+ // Add ports from global port ranges if defined
19
+ if (this.settings.globalPortRanges && this.settings.globalPortRanges.length > 0) {
20
+ for (const range of this.settings.globalPortRanges) {
21
+ for (let port = range.from; port <= range.to; port++) {
22
+ listeningPorts.add(port);
23
+ }
24
+ }
25
+ }
26
+
27
+ return listeningPorts;
28
+ }
29
+
30
+ /**
31
+ * Check if a port should use NetworkProxy for forwarding
32
+ */
33
+ public shouldUseNetworkProxy(port: number): boolean {
34
+ return !!this.settings.useNetworkProxy && this.settings.useNetworkProxy.includes(port);
35
+ }
36
+
37
+ /**
38
+ * Check if port should use global forwarding
39
+ */
40
+ public shouldUseGlobalForwarding(port: number): boolean {
41
+ return (
42
+ !!this.settings.forwardAllGlobalRanges &&
43
+ this.isPortInGlobalRanges(port)
44
+ );
45
+ }
46
+
47
+ /**
48
+ * Check if a port is in global ranges
49
+ */
50
+ public isPortInGlobalRanges(port: number): boolean {
51
+ return (
52
+ this.settings.globalPortRanges &&
53
+ this.isPortInRanges(port, this.settings.globalPortRanges)
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Check if a port falls within the specified ranges
59
+ */
60
+ public isPortInRanges(port: number, ranges: Array<{ from: number; to: number }>): boolean {
61
+ return ranges.some((range) => port >= range.from && port <= range.to);
62
+ }
63
+
64
+ /**
65
+ * Get forwarding port for a specific listening port
66
+ * This determines what port to connect to on the target
67
+ */
68
+ public getForwardingPort(listeningPort: number): number {
69
+ // If using global forwarding, forward to the original port
70
+ if (this.settings.forwardAllGlobalRanges && this.isPortInGlobalRanges(listeningPort)) {
71
+ return listeningPort;
72
+ }
73
+
74
+ // Otherwise use the configured toPort
75
+ return this.settings.toPort;
76
+ }
77
+
78
+ /**
79
+ * Find domain-specific port ranges that include a given port
80
+ */
81
+ public findDomainPortRange(port: number): {
82
+ domainIndex: number,
83
+ range: { from: number, to: number }
84
+ } | undefined {
85
+ for (let i = 0; i < this.settings.domainConfigs.length; i++) {
86
+ const domain = this.settings.domainConfigs[i];
87
+ if (domain.portRanges) {
88
+ for (const range of domain.portRanges) {
89
+ if (port >= range.from && port <= range.to) {
90
+ return { domainIndex: i, range };
91
+ }
92
+ }
93
+ }
94
+ }
95
+ return undefined;
96
+ }
97
+
98
+ /**
99
+ * Get a list of all configured ports
100
+ * This includes the fromPort, NetworkProxy ports, and ports from all ranges
101
+ */
102
+ public getAllConfiguredPorts(): number[] {
103
+ const ports = new Set<number>();
104
+
105
+ // Add main listening port
106
+ ports.add(this.settings.fromPort);
107
+
108
+ // Add NetworkProxy port if configured
109
+ if (this.settings.networkProxyPort) {
110
+ ports.add(this.settings.networkProxyPort);
111
+ }
112
+
113
+ // Add NetworkProxy ports
114
+ if (this.settings.useNetworkProxy) {
115
+ for (const port of this.settings.useNetworkProxy) {
116
+ ports.add(port);
117
+ }
118
+ }
119
+
120
+ // Add ACME HTTP challenge port if enabled
121
+ if (this.settings.acme?.enabled && this.settings.acme.port) {
122
+ ports.add(this.settings.acme.port);
123
+ }
124
+
125
+ // Add global port ranges
126
+ if (this.settings.globalPortRanges) {
127
+ for (const range of this.settings.globalPortRanges) {
128
+ for (let port = range.from; port <= range.to; port++) {
129
+ ports.add(port);
130
+ }
131
+ }
132
+ }
133
+
134
+ // Add domain-specific port ranges
135
+ for (const domain of this.settings.domainConfigs) {
136
+ if (domain.portRanges) {
137
+ for (const range of domain.portRanges) {
138
+ for (let port = range.from; port <= range.to; port++) {
139
+ ports.add(port);
140
+ }
141
+ }
142
+ }
143
+
144
+ // Add domain-specific NetworkProxy port if configured
145
+ if (domain.useNetworkProxy && domain.networkProxyPort) {
146
+ ports.add(domain.networkProxyPort);
147
+ }
148
+ }
149
+
150
+ return Array.from(ports);
151
+ }
152
+
153
+ /**
154
+ * Validate port configuration
155
+ * Returns array of warning messages
156
+ */
157
+ public validateConfiguration(): string[] {
158
+ const warnings: string[] = [];
159
+
160
+ // Check for overlapping port ranges
161
+ const portMappings = new Map<number, string[]>();
162
+
163
+ // Track global port ranges
164
+ if (this.settings.globalPortRanges) {
165
+ for (const range of this.settings.globalPortRanges) {
166
+ for (let port = range.from; port <= range.to; port++) {
167
+ if (!portMappings.has(port)) {
168
+ portMappings.set(port, []);
169
+ }
170
+ portMappings.get(port)!.push('Global Port Range');
171
+ }
172
+ }
173
+ }
174
+
175
+ // Track domain-specific port ranges
176
+ for (const domain of this.settings.domainConfigs) {
177
+ if (domain.portRanges) {
178
+ for (const range of domain.portRanges) {
179
+ for (let port = range.from; port <= range.to; port++) {
180
+ if (!portMappings.has(port)) {
181
+ portMappings.set(port, []);
182
+ }
183
+ portMappings.get(port)!.push(`Domain: ${domain.domains.join(', ')}`);
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ // Check for ports with multiple mappings
190
+ for (const [port, mappings] of portMappings.entries()) {
191
+ if (mappings.length > 1) {
192
+ warnings.push(`Port ${port} has multiple mappings: ${mappings.join(', ')}`);
193
+ }
194
+ }
195
+
196
+ // Check if main ports are used elsewhere
197
+ if (portMappings.has(this.settings.fromPort) && portMappings.get(this.settings.fromPort)!.length > 0) {
198
+ warnings.push(`Main listening port ${this.settings.fromPort} is also used in port ranges`);
199
+ }
200
+
201
+ if (this.settings.networkProxyPort && portMappings.has(this.settings.networkProxyPort)) {
202
+ warnings.push(`NetworkProxy port ${this.settings.networkProxyPort} is also used in port ranges`);
203
+ }
204
+
205
+ // Check ACME port
206
+ if (this.settings.acme?.enabled && this.settings.acme.port) {
207
+ if (portMappings.has(this.settings.acme.port)) {
208
+ warnings.push(`ACME HTTP challenge port ${this.settings.acme.port} is also used in port ranges`);
209
+ }
210
+ }
211
+
212
+ return warnings;
213
+ }
214
+ }
@@ -0,0 +1,147 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { IPortProxySettings } from './classes.pp.interfaces.js';
3
+
4
+ /**
5
+ * Handles security aspects like IP tracking, rate limiting, and authorization
6
+ */
7
+ export class SecurityManager {
8
+ private connectionsByIP: Map<string, Set<string>> = new Map();
9
+ private connectionRateByIP: Map<string, number[]> = new Map();
10
+
11
+ constructor(private settings: IPortProxySettings) {}
12
+
13
+ /**
14
+ * Get connections count by IP
15
+ */
16
+ public getConnectionCountByIP(ip: string): number {
17
+ return this.connectionsByIP.get(ip)?.size || 0;
18
+ }
19
+
20
+ /**
21
+ * Check and update connection rate for an IP
22
+ * @returns true if within rate limit, false if exceeding limit
23
+ */
24
+ public checkConnectionRate(ip: string): boolean {
25
+ const now = Date.now();
26
+ const minute = 60 * 1000;
27
+
28
+ if (!this.connectionRateByIP.has(ip)) {
29
+ this.connectionRateByIP.set(ip, [now]);
30
+ return true;
31
+ }
32
+
33
+ // Get timestamps and filter out entries older than 1 minute
34
+ const timestamps = this.connectionRateByIP.get(ip)!.filter((time) => now - time < minute);
35
+ timestamps.push(now);
36
+ this.connectionRateByIP.set(ip, timestamps);
37
+
38
+ // Check if rate exceeds limit
39
+ return timestamps.length <= this.settings.connectionRateLimitPerMinute!;
40
+ }
41
+
42
+ /**
43
+ * Track connection by IP
44
+ */
45
+ public trackConnectionByIP(ip: string, connectionId: string): void {
46
+ if (!this.connectionsByIP.has(ip)) {
47
+ this.connectionsByIP.set(ip, new Set());
48
+ }
49
+ this.connectionsByIP.get(ip)!.add(connectionId);
50
+ }
51
+
52
+ /**
53
+ * Remove connection tracking for an IP
54
+ */
55
+ public removeConnectionByIP(ip: string, connectionId: string): void {
56
+ if (this.connectionsByIP.has(ip)) {
57
+ const connections = this.connectionsByIP.get(ip)!;
58
+ connections.delete(connectionId);
59
+ if (connections.size === 0) {
60
+ this.connectionsByIP.delete(ip);
61
+ }
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Check if an IP is allowed using glob patterns
67
+ */
68
+ public isIPAuthorized(ip: string, allowedIPs: string[], blockedIPs: string[] = []): boolean {
69
+ // Skip IP validation if allowedIPs is empty
70
+ if (!ip || (allowedIPs.length === 0 && blockedIPs.length === 0)) {
71
+ return true;
72
+ }
73
+
74
+ // First check if IP is blocked
75
+ if (blockedIPs.length > 0 && this.isGlobIPMatch(ip, blockedIPs)) {
76
+ return false;
77
+ }
78
+
79
+ // Then check if IP is allowed
80
+ return this.isGlobIPMatch(ip, allowedIPs);
81
+ }
82
+
83
+ /**
84
+ * Check if the IP matches any of the glob patterns
85
+ */
86
+ private isGlobIPMatch(ip: string, patterns: string[]): boolean {
87
+ if (!ip || !patterns || patterns.length === 0) return false;
88
+
89
+ const normalizeIP = (ip: string): string[] => {
90
+ if (!ip) return [];
91
+ if (ip.startsWith('::ffff:')) {
92
+ const ipv4 = ip.slice(7);
93
+ return [ip, ipv4];
94
+ }
95
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
96
+ return [ip, `::ffff:${ip}`];
97
+ }
98
+ return [ip];
99
+ };
100
+
101
+ const normalizedIPVariants = normalizeIP(ip);
102
+ if (normalizedIPVariants.length === 0) return false;
103
+
104
+ const expandedPatterns = patterns.flatMap(normalizeIP);
105
+ return normalizedIPVariants.some((ipVariant) =>
106
+ expandedPatterns.some((pattern) => plugins.minimatch(ipVariant, pattern))
107
+ );
108
+ }
109
+
110
+ /**
111
+ * Check if IP should be allowed considering connection rate and max connections
112
+ * @returns Object with result and reason
113
+ */
114
+ public validateIP(ip: string): { allowed: boolean; reason?: string } {
115
+ // Check connection count limit
116
+ if (
117
+ this.settings.maxConnectionsPerIP &&
118
+ this.getConnectionCountByIP(ip) >= this.settings.maxConnectionsPerIP
119
+ ) {
120
+ return {
121
+ allowed: false,
122
+ reason: `Maximum connections per IP (${this.settings.maxConnectionsPerIP}) exceeded`
123
+ };
124
+ }
125
+
126
+ // Check connection rate limit
127
+ if (
128
+ this.settings.connectionRateLimitPerMinute &&
129
+ !this.checkConnectionRate(ip)
130
+ ) {
131
+ return {
132
+ allowed: false,
133
+ reason: `Connection rate limit (${this.settings.connectionRateLimitPerMinute}/min) exceeded`
134
+ };
135
+ }
136
+
137
+ return { allowed: true };
138
+ }
139
+
140
+ /**
141
+ * Clears all IP tracking data (for shutdown)
142
+ */
143
+ public clearIPTracking(): void {
144
+ this.connectionsByIP.clear();
145
+ this.connectionRateByIP.clear();
146
+ }
147
+ }
@@ -22,114 +22,6 @@ export class SniHandler {
22
22
  private static fragmentedBuffers: Map<string, Buffer> = new Map();
23
23
  private static fragmentTimeout: number = 1000; // ms to wait for fragments before cleanup
24
24
 
25
- // Session tracking for tab reactivation scenarios
26
- private static sessionCache: Map<
27
- string,
28
- {
29
- sni: string;
30
- timestamp: number;
31
- clientRandom?: Buffer;
32
- }
33
- > = new Map();
34
-
35
- // Longer timeout for session cache (24 hours by default)
36
- private static sessionCacheTimeout: number = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
37
-
38
- // Cleanup interval for session cache (run every hour)
39
- private static sessionCleanupInterval: NodeJS.Timeout | null = null;
40
-
41
- /**
42
- * Initialize the session cache cleanup mechanism.
43
- * This should be called during application startup.
44
- */
45
- public static initSessionCacheCleanup(): void {
46
- if (this.sessionCleanupInterval === null) {
47
- this.sessionCleanupInterval = setInterval(() => {
48
- this.cleanupSessionCache();
49
- }, 60 * 60 * 1000); // Run every hour
50
- }
51
- }
52
-
53
- /**
54
- * Clean up expired entries from the session cache
55
- */
56
- private static cleanupSessionCache(): void {
57
- const now = Date.now();
58
- const expiredKeys: string[] = [];
59
-
60
- this.sessionCache.forEach((session, key) => {
61
- if (now - session.timestamp > this.sessionCacheTimeout) {
62
- expiredKeys.push(key);
63
- }
64
- });
65
-
66
- expiredKeys.forEach((key) => {
67
- this.sessionCache.delete(key);
68
- });
69
- }
70
-
71
- /**
72
- * Create a client identity key for session tracking
73
- * Uses source IP and optional client random for uniqueness
74
- *
75
- * @param sourceIp - Client IP address
76
- * @param clientRandom - Optional TLS client random value
77
- * @returns A string key for the session cache
78
- */
79
- private static createClientKey(sourceIp: string, clientRandom?: Buffer): string {
80
- if (clientRandom) {
81
- // If we have the client random, use it for more precise tracking
82
- return `${sourceIp}:${clientRandom.toString('hex')}`;
83
- }
84
- // Fall back to just IP-based tracking
85
- return sourceIp;
86
- }
87
-
88
- /**
89
- * Store SNI information in the session cache
90
- *
91
- * @param sourceIp - Client IP address
92
- * @param sni - The extracted SNI value
93
- * @param clientRandom - Optional TLS client random value
94
- */
95
- private static cacheSession(sourceIp: string, sni: string, clientRandom?: Buffer): void {
96
- const key = this.createClientKey(sourceIp, clientRandom);
97
- this.sessionCache.set(key, {
98
- sni,
99
- timestamp: Date.now(),
100
- clientRandom,
101
- });
102
- }
103
-
104
- /**
105
- * Retrieve SNI information from the session cache
106
- *
107
- * @param sourceIp - Client IP address
108
- * @param clientRandom - Optional TLS client random value
109
- * @returns The cached SNI or undefined if not found
110
- */
111
- private static getCachedSession(sourceIp: string, clientRandom?: Buffer): string | undefined {
112
- // Try with client random first for precision
113
- if (clientRandom) {
114
- const preciseKey = this.createClientKey(sourceIp, clientRandom);
115
- const preciseSession = this.sessionCache.get(preciseKey);
116
- if (preciseSession) {
117
- return preciseSession.sni;
118
- }
119
- }
120
-
121
- // Fall back to IP-only lookup
122
- const ipKey = this.createClientKey(sourceIp);
123
- const session = this.sessionCache.get(ipKey);
124
- if (session) {
125
- // Update the timestamp to keep the session alive
126
- session.timestamp = Date.now();
127
- return session.sni;
128
- }
129
-
130
- return undefined;
131
- }
132
-
133
25
  /**
134
26
  * Extract the client random value from a ClientHello message
135
27
  *
@@ -1172,7 +1064,6 @@ export class SniHandler {
1172
1064
  * 4. Fragmented ClientHello messages
1173
1065
  * 5. TLS 1.3 Early Data (0-RTT)
1174
1066
  * 6. Chrome's connection racing behaviors
1175
- * 7. Tab reactivation patterns with session cache
1176
1067
  *
1177
1068
  * @param buffer - The buffer containing the TLS ClientHello message
1178
1069
  * @param connectionInfo - Optional connection information for fragment handling
@@ -1235,19 +1126,10 @@ export class SniHandler {
1235
1126
  const standardSni = this.extractSNI(processBuffer, enableLogging);
1236
1127
  if (standardSni) {
1237
1128
  log(`Found standard SNI: ${standardSni}`);
1238
-
1239
- // If we extracted a standard SNI, cache it for future use
1240
- if (connectionInfo?.sourceIp) {
1241
- const clientRandom = this.extractClientRandom(processBuffer);
1242
- this.cacheSession(connectionInfo.sourceIp, standardSni, clientRandom);
1243
- log(`Cached SNI for future reference: ${standardSni}`);
1244
- }
1245
-
1246
1129
  return standardSni;
1247
1130
  }
1248
1131
 
1249
1132
  // Check for session resumption when standard SNI extraction fails
1250
- // This may help in chained proxy scenarios
1251
1133
  if (this.isClientHello(processBuffer)) {
1252
1134
  const resumptionInfo = this.hasSessionResumption(processBuffer, enableLogging);
1253
1135
 
@@ -1258,31 +1140,11 @@ export class SniHandler {
1258
1140
  const pskSni = this.extractSNIFromPSKExtension(processBuffer, enableLogging);
1259
1141
  if (pskSni) {
1260
1142
  log(`Extracted SNI from PSK extension: ${pskSni}`);
1261
-
1262
- // Cache this SNI
1263
- if (connectionInfo?.sourceIp) {
1264
- const clientRandom = this.extractClientRandom(processBuffer);
1265
- this.cacheSession(connectionInfo.sourceIp, pskSni, clientRandom);
1266
- }
1267
-
1268
1143
  return pskSni;
1269
1144
  }
1270
-
1271
- // If session resumption has SNI in a non-standard location,
1272
- // we need to apply heuristics
1273
- if (connectionInfo?.sourceIp) {
1274
- const cachedSni = this.getCachedSession(connectionInfo.sourceIp);
1275
- if (cachedSni) {
1276
- log(`Using cached SNI for session resumption: ${cachedSni}`);
1277
- return cachedSni;
1278
- }
1279
- }
1280
1145
  }
1281
1146
  }
1282
1147
 
1283
- // Try tab reactivation and other recovery methods...
1284
- // (existing code remains unchanged)
1285
-
1286
1148
  // Log detailed info about the ClientHello when SNI extraction fails
1287
1149
  if (this.isClientHello(processBuffer) && enableLogging) {
1288
1150
  log(`SNI extraction failed for ClientHello. Buffer details:`);
@@ -1303,7 +1165,6 @@ export class SniHandler {
1303
1165
  }
1304
1166
  }
1305
1167
 
1306
- // Existing code for fallback methods continues...
1307
1168
  return undefined;
1308
1169
  }
1309
1170
 
@@ -1313,7 +1174,7 @@ export class SniHandler {
1313
1174
  *
1314
1175
  * The method uses connection tracking to handle fragmented ClientHello
1315
1176
  * messages and various TLS 1.3 behaviors, including Chrome's connection
1316
- * racing patterns and tab reactivation behaviors.
1177
+ * racing patterns.
1317
1178
  *
1318
1179
  * @param buffer - The buffer containing TLS data
1319
1180
  * @param connectionInfo - Connection metadata (IPs and ports)
@@ -1321,7 +1182,6 @@ export class SniHandler {
1321
1182
  * @param cachedSni - Optional cached SNI from previous connections (for racing detection)
1322
1183
  * @returns The extracted server name or undefined if not found or more data needed
1323
1184
  */
1324
-
1325
1185
  public static processTlsPacket(
1326
1186
  buffer: Buffer,
1327
1187
  connectionInfo: {
@@ -1363,13 +1223,6 @@ export class SniHandler {
1363
1223
  return cachedSni;
1364
1224
  }
1365
1225
 
1366
- // Otherwise check our session cache
1367
- const sessionCachedSni = this.getCachedSession(connectionInfo.sourceIp);
1368
- if (sessionCachedSni) {
1369
- log(`Using session-cached SNI for application data: ${sessionCachedSni}`);
1370
- return sessionCachedSni;
1371
- }
1372
-
1373
1226
  log('Application data packet without cached SNI, cannot determine hostname');
1374
1227
  return undefined;
1375
1228
  }
@@ -1385,9 +1238,6 @@ export class SniHandler {
1385
1238
  const standardSni = this.extractSNI(buffer, enableLogging);
1386
1239
  if (standardSni) {
1387
1240
  log(`Found standard SNI in session resumption: ${standardSni}`);
1388
-
1389
- // Cache this SNI
1390
- this.cacheSession(connectionInfo.sourceIp, standardSni);
1391
1241
  return standardSni;
1392
1242
  }
1393
1243
 
@@ -1396,7 +1246,6 @@ export class SniHandler {
1396
1246
  const pskSni = this.extractSNIFromPSKExtension(buffer, enableLogging);
1397
1247
  if (pskSni) {
1398
1248
  log(`Extracted SNI from PSK extension: ${pskSni}`);
1399
- this.cacheSession(connectionInfo.sourceIp, pskSni);
1400
1249
  return pskSni;
1401
1250
  }
1402
1251
 
@@ -1430,13 +1279,6 @@ export class SniHandler {
1430
1279
  }
1431
1280
  }
1432
1281
 
1433
- // If we still don't have SNI, check for cached sessions
1434
- const cachedSni = this.getCachedSession(connectionInfo.sourceIp);
1435
- if (cachedSni) {
1436
- log(`Using cached SNI for session resumption: ${cachedSni}`);
1437
- return cachedSni;
1438
- }
1439
-
1440
1282
  log(`Session resumption without extractable SNI`);
1441
1283
  // If allowSessionTicket=false, should be rejected by caller
1442
1284
  }
@@ -1451,19 +1293,10 @@ export class SniHandler {
1451
1293
  }
1452
1294
 
1453
1295
  // If we couldn't extract an SNI, check if this is a valid ClientHello
1454
- // If it is, but we couldn't get an SNI, it might be a fragment or
1455
- // a connection race situation
1456
1296
  if (this.isClientHello(buffer)) {
1457
- // Check if we have a cached session for this IP
1458
- const sessionCachedSni = this.getCachedSession(connectionInfo.sourceIp);
1459
- if (sessionCachedSni) {
1460
- log(`Using session cache for ClientHello without SNI: ${sessionCachedSni}`);
1461
- return sessionCachedSni;
1462
- }
1463
-
1464
1297
  log('Valid ClientHello detected, but no SNI extracted - might need more data');
1465
1298
  }
1466
1299
 
1467
1300
  return undefined;
1468
1301
  }
1469
- }
1302
+ }