@push.rocks/smartproxy 5.1.0 → 6.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.
- package/dist_ts/classes.pp.interfaces.d.ts +23 -0
- package/dist_ts/classes.pp.networkproxybridge.d.ts +15 -1
- package/dist_ts/classes.pp.networkproxybridge.js +116 -21
- package/dist_ts/classes.pp.portproxy.d.ts +20 -4
- package/dist_ts/classes.pp.portproxy.js +321 -22
- package/dist_ts/index.d.ts +6 -6
- package/dist_ts/index.js +7 -7
- package/dist_ts/networkproxy/classes.np.certificatemanager.d.ts +77 -0
- package/dist_ts/networkproxy/classes.np.certificatemanager.js +354 -0
- package/dist_ts/networkproxy/classes.np.connectionpool.d.ts +47 -0
- package/dist_ts/networkproxy/classes.np.connectionpool.js +210 -0
- package/dist_ts/networkproxy/classes.np.networkproxy.d.ts +117 -0
- package/dist_ts/networkproxy/classes.np.networkproxy.js +375 -0
- package/dist_ts/networkproxy/classes.np.requesthandler.d.ts +51 -0
- package/dist_ts/networkproxy/classes.np.requesthandler.js +210 -0
- package/dist_ts/networkproxy/classes.np.types.d.ts +82 -0
- package/dist_ts/networkproxy/classes.np.types.js +35 -0
- package/dist_ts/networkproxy/classes.np.websockethandler.d.ts +38 -0
- package/dist_ts/networkproxy/classes.np.websockethandler.js +188 -0
- package/dist_ts/networkproxy/index.d.ts +6 -0
- package/dist_ts/networkproxy/index.js +8 -0
- package/dist_ts/nfttablesproxy/classes.nftablesproxy.d.ts +219 -0
- package/dist_ts/nfttablesproxy/classes.nftablesproxy.js +1542 -0
- package/dist_ts/port80handler/classes.port80handler.d.ts +260 -0
- package/dist_ts/port80handler/classes.port80handler.js +928 -0
- package/dist_ts/smartproxy/classes.pp.connectionhandler.d.ts +39 -0
- package/dist_ts/smartproxy/classes.pp.connectionhandler.js +754 -0
- package/dist_ts/smartproxy/classes.pp.connectionmanager.d.ts +78 -0
- package/dist_ts/smartproxy/classes.pp.connectionmanager.js +378 -0
- package/dist_ts/smartproxy/classes.pp.domainconfigmanager.d.ts +55 -0
- package/dist_ts/smartproxy/classes.pp.domainconfigmanager.js +103 -0
- package/dist_ts/smartproxy/classes.pp.interfaces.d.ts +133 -0
- package/dist_ts/smartproxy/classes.pp.interfaces.js +2 -0
- package/dist_ts/smartproxy/classes.pp.networkproxybridge.d.ts +57 -0
- package/dist_ts/smartproxy/classes.pp.networkproxybridge.js +306 -0
- package/dist_ts/smartproxy/classes.pp.portrangemanager.d.ts +56 -0
- package/dist_ts/smartproxy/classes.pp.portrangemanager.js +179 -0
- package/dist_ts/smartproxy/classes.pp.securitymanager.d.ts +47 -0
- package/dist_ts/smartproxy/classes.pp.securitymanager.js +126 -0
- package/dist_ts/smartproxy/classes.pp.snihandler.d.ts +153 -0
- package/dist_ts/smartproxy/classes.pp.snihandler.js +1053 -0
- package/dist_ts/smartproxy/classes.pp.timeoutmanager.d.ts +47 -0
- package/dist_ts/smartproxy/classes.pp.timeoutmanager.js +154 -0
- package/dist_ts/smartproxy/classes.pp.tlsalert.d.ts +149 -0
- package/dist_ts/smartproxy/classes.pp.tlsalert.js +225 -0
- package/dist_ts/smartproxy/classes.pp.tlsmanager.d.ts +57 -0
- package/dist_ts/smartproxy/classes.pp.tlsmanager.js +132 -0
- package/dist_ts/smartproxy/classes.smartproxy.d.ts +64 -0
- package/dist_ts/smartproxy/classes.smartproxy.js +567 -0
- package/package.json +1 -1
- package/ts/index.ts +6 -6
- package/ts/networkproxy/classes.np.certificatemanager.ts +398 -0
- package/ts/networkproxy/classes.np.connectionpool.ts +241 -0
- package/ts/networkproxy/classes.np.networkproxy.ts +469 -0
- package/ts/networkproxy/classes.np.requesthandler.ts +278 -0
- package/ts/networkproxy/classes.np.types.ts +123 -0
- package/ts/networkproxy/classes.np.websockethandler.ts +226 -0
- package/ts/networkproxy/index.ts +7 -0
- package/ts/{classes.port80handler.ts → port80handler/classes.port80handler.ts} +249 -1
- package/ts/{classes.pp.connectionhandler.ts → smartproxy/classes.pp.connectionhandler.ts} +1 -1
- package/ts/{classes.pp.connectionmanager.ts → smartproxy/classes.pp.connectionmanager.ts} +1 -1
- package/ts/{classes.pp.domainconfigmanager.ts → smartproxy/classes.pp.domainconfigmanager.ts} +1 -1
- package/ts/{classes.pp.interfaces.ts → smartproxy/classes.pp.interfaces.ts} +31 -5
- package/ts/{classes.pp.networkproxybridge.ts → smartproxy/classes.pp.networkproxybridge.ts} +129 -28
- package/ts/{classes.pp.securitymanager.ts → smartproxy/classes.pp.securitymanager.ts} +1 -1
- package/ts/{classes.pp.tlsmanager.ts → smartproxy/classes.pp.tlsmanager.ts} +1 -1
- package/ts/smartproxy/classes.smartproxy.ts +679 -0
- package/ts/classes.networkproxy.ts +0 -1730
- package/ts/classes.pp.acmemanager.ts +0 -149
- package/ts/classes.pp.portproxy.ts +0 -344
- /package/ts/{classes.nftablesproxy.ts → nfttablesproxy/classes.nftablesproxy.ts} +0 -0
- /package/ts/{classes.pp.portrangemanager.ts → smartproxy/classes.pp.portrangemanager.ts} +0 -0
- /package/ts/{classes.pp.snihandler.ts → smartproxy/classes.pp.snihandler.ts} +0 -0
- /package/ts/{classes.pp.timeoutmanager.ts → smartproxy/classes.pp.timeoutmanager.ts} +0 -0
- /package/ts/{classes.pp.tlsalert.ts → smartproxy/classes.pp.tlsalert.ts} +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import type { IConnectionRecord, IPortProxySettings } from './classes.pp.interfaces.js';
|
|
3
|
+
import { SecurityManager } from './classes.pp.securitymanager.js';
|
|
4
|
+
import { TimeoutManager } from './classes.pp.timeoutmanager.js';
|
|
5
|
+
/**
|
|
6
|
+
* Manages connection lifecycle, tracking, and cleanup
|
|
7
|
+
*/
|
|
8
|
+
export declare class ConnectionManager {
|
|
9
|
+
private settings;
|
|
10
|
+
private securityManager;
|
|
11
|
+
private timeoutManager;
|
|
12
|
+
private connectionRecords;
|
|
13
|
+
private terminationStats;
|
|
14
|
+
constructor(settings: IPortProxySettings, securityManager: SecurityManager, timeoutManager: TimeoutManager);
|
|
15
|
+
/**
|
|
16
|
+
* Generate a unique connection ID
|
|
17
|
+
*/
|
|
18
|
+
generateConnectionId(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Create and track a new connection
|
|
21
|
+
*/
|
|
22
|
+
createConnection(socket: plugins.net.Socket): IConnectionRecord;
|
|
23
|
+
/**
|
|
24
|
+
* Track an existing connection
|
|
25
|
+
*/
|
|
26
|
+
trackConnection(connectionId: string, record: IConnectionRecord): void;
|
|
27
|
+
/**
|
|
28
|
+
* Get a connection by ID
|
|
29
|
+
*/
|
|
30
|
+
getConnection(connectionId: string): IConnectionRecord | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Get all active connections
|
|
33
|
+
*/
|
|
34
|
+
getConnections(): Map<string, IConnectionRecord>;
|
|
35
|
+
/**
|
|
36
|
+
* Get count of active connections
|
|
37
|
+
*/
|
|
38
|
+
getConnectionCount(): number;
|
|
39
|
+
/**
|
|
40
|
+
* Initiates cleanup once for a connection
|
|
41
|
+
*/
|
|
42
|
+
initiateCleanupOnce(record: IConnectionRecord, reason?: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Clean up a connection record
|
|
45
|
+
*/
|
|
46
|
+
cleanupConnection(record: IConnectionRecord, reason?: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* Helper method to clean up a socket
|
|
49
|
+
*/
|
|
50
|
+
private cleanupSocket;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a generic error handler for incoming or outgoing sockets
|
|
53
|
+
*/
|
|
54
|
+
handleError(side: 'incoming' | 'outgoing', record: IConnectionRecord): (err: Error) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Creates a generic close handler for incoming or outgoing sockets
|
|
57
|
+
*/
|
|
58
|
+
handleClose(side: 'incoming' | 'outgoing', record: IConnectionRecord): () => void;
|
|
59
|
+
/**
|
|
60
|
+
* Increment termination statistics
|
|
61
|
+
*/
|
|
62
|
+
incrementTerminationStat(side: 'incoming' | 'outgoing', reason: string): void;
|
|
63
|
+
/**
|
|
64
|
+
* Get termination statistics
|
|
65
|
+
*/
|
|
66
|
+
getTerminationStats(): {
|
|
67
|
+
incoming: Record<string, number>;
|
|
68
|
+
outgoing: Record<string, number>;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Check for stalled/inactive connections
|
|
72
|
+
*/
|
|
73
|
+
performInactivityCheck(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Clear all connections (for shutdown)
|
|
76
|
+
*/
|
|
77
|
+
clearConnections(): void;
|
|
78
|
+
}
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { SecurityManager } from './classes.pp.securitymanager.js';
|
|
3
|
+
import { TimeoutManager } from './classes.pp.timeoutmanager.js';
|
|
4
|
+
/**
|
|
5
|
+
* Manages connection lifecycle, tracking, and cleanup
|
|
6
|
+
*/
|
|
7
|
+
export class ConnectionManager {
|
|
8
|
+
constructor(settings, securityManager, timeoutManager) {
|
|
9
|
+
this.settings = settings;
|
|
10
|
+
this.securityManager = securityManager;
|
|
11
|
+
this.timeoutManager = timeoutManager;
|
|
12
|
+
this.connectionRecords = new Map();
|
|
13
|
+
this.terminationStats = { incoming: {}, outgoing: {} };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Generate a unique connection ID
|
|
17
|
+
*/
|
|
18
|
+
generateConnectionId() {
|
|
19
|
+
return Math.random().toString(36).substring(2, 15) +
|
|
20
|
+
Math.random().toString(36).substring(2, 15);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create and track a new connection
|
|
24
|
+
*/
|
|
25
|
+
createConnection(socket) {
|
|
26
|
+
const connectionId = this.generateConnectionId();
|
|
27
|
+
const remoteIP = socket.remoteAddress || '';
|
|
28
|
+
const localPort = socket.localPort || 0;
|
|
29
|
+
const record = {
|
|
30
|
+
id: connectionId,
|
|
31
|
+
incoming: socket,
|
|
32
|
+
outgoing: null,
|
|
33
|
+
incomingStartTime: Date.now(),
|
|
34
|
+
lastActivity: Date.now(),
|
|
35
|
+
connectionClosed: false,
|
|
36
|
+
pendingData: [],
|
|
37
|
+
pendingDataSize: 0,
|
|
38
|
+
bytesReceived: 0,
|
|
39
|
+
bytesSent: 0,
|
|
40
|
+
remoteIP,
|
|
41
|
+
localPort,
|
|
42
|
+
isTLS: false,
|
|
43
|
+
tlsHandshakeComplete: false,
|
|
44
|
+
hasReceivedInitialData: false,
|
|
45
|
+
hasKeepAlive: false,
|
|
46
|
+
incomingTerminationReason: null,
|
|
47
|
+
outgoingTerminationReason: null,
|
|
48
|
+
usingNetworkProxy: false,
|
|
49
|
+
isBrowserConnection: false,
|
|
50
|
+
domainSwitches: 0
|
|
51
|
+
};
|
|
52
|
+
this.trackConnection(connectionId, record);
|
|
53
|
+
return record;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Track an existing connection
|
|
57
|
+
*/
|
|
58
|
+
trackConnection(connectionId, record) {
|
|
59
|
+
this.connectionRecords.set(connectionId, record);
|
|
60
|
+
this.securityManager.trackConnectionByIP(record.remoteIP, connectionId);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get a connection by ID
|
|
64
|
+
*/
|
|
65
|
+
getConnection(connectionId) {
|
|
66
|
+
return this.connectionRecords.get(connectionId);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get all active connections
|
|
70
|
+
*/
|
|
71
|
+
getConnections() {
|
|
72
|
+
return this.connectionRecords;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get count of active connections
|
|
76
|
+
*/
|
|
77
|
+
getConnectionCount() {
|
|
78
|
+
return this.connectionRecords.size;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Initiates cleanup once for a connection
|
|
82
|
+
*/
|
|
83
|
+
initiateCleanupOnce(record, reason = 'normal') {
|
|
84
|
+
if (this.settings.enableDetailedLogging) {
|
|
85
|
+
console.log(`[${record.id}] Connection cleanup initiated for ${record.remoteIP} (${reason})`);
|
|
86
|
+
}
|
|
87
|
+
if (record.incomingTerminationReason === null ||
|
|
88
|
+
record.incomingTerminationReason === undefined) {
|
|
89
|
+
record.incomingTerminationReason = reason;
|
|
90
|
+
this.incrementTerminationStat('incoming', reason);
|
|
91
|
+
}
|
|
92
|
+
this.cleanupConnection(record, reason);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Clean up a connection record
|
|
96
|
+
*/
|
|
97
|
+
cleanupConnection(record, reason = 'normal') {
|
|
98
|
+
if (!record.connectionClosed) {
|
|
99
|
+
record.connectionClosed = true;
|
|
100
|
+
// Track connection termination
|
|
101
|
+
this.securityManager.removeConnectionByIP(record.remoteIP, record.id);
|
|
102
|
+
if (record.cleanupTimer) {
|
|
103
|
+
clearTimeout(record.cleanupTimer);
|
|
104
|
+
record.cleanupTimer = undefined;
|
|
105
|
+
}
|
|
106
|
+
// Detailed logging data
|
|
107
|
+
const duration = Date.now() - record.incomingStartTime;
|
|
108
|
+
const bytesReceived = record.bytesReceived;
|
|
109
|
+
const bytesSent = record.bytesSent;
|
|
110
|
+
// Remove all data handlers to make sure we clean up properly
|
|
111
|
+
if (record.incoming) {
|
|
112
|
+
try {
|
|
113
|
+
// Remove our safe data handler
|
|
114
|
+
record.incoming.removeAllListeners('data');
|
|
115
|
+
// Reset the handler references
|
|
116
|
+
record.renegotiationHandler = undefined;
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
console.log(`[${record.id}] Error removing data handlers: ${err}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Handle incoming socket
|
|
123
|
+
this.cleanupSocket(record, 'incoming', record.incoming);
|
|
124
|
+
// Handle outgoing socket
|
|
125
|
+
if (record.outgoing) {
|
|
126
|
+
this.cleanupSocket(record, 'outgoing', record.outgoing);
|
|
127
|
+
}
|
|
128
|
+
// Clear pendingData to avoid memory leaks
|
|
129
|
+
record.pendingData = [];
|
|
130
|
+
record.pendingDataSize = 0;
|
|
131
|
+
// Remove the record from the tracking map
|
|
132
|
+
this.connectionRecords.delete(record.id);
|
|
133
|
+
// Log connection details
|
|
134
|
+
if (this.settings.enableDetailedLogging) {
|
|
135
|
+
console.log(`[${record.id}] Connection from ${record.remoteIP} on port ${record.localPort} terminated (${reason}).` +
|
|
136
|
+
` Duration: ${plugins.prettyMs(duration)}, Bytes IN: ${bytesReceived}, OUT: ${bytesSent}, ` +
|
|
137
|
+
`TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${record.hasKeepAlive ? 'Yes' : 'No'}` +
|
|
138
|
+
`${record.usingNetworkProxy ? ', Using NetworkProxy' : ''}` +
|
|
139
|
+
`${record.domainSwitches ? `, Domain switches: ${record.domainSwitches}` : ''}`);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
console.log(`[${record.id}] Connection from ${record.remoteIP} terminated (${reason}). Active connections: ${this.connectionRecords.size}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Helper method to clean up a socket
|
|
148
|
+
*/
|
|
149
|
+
cleanupSocket(record, side, socket) {
|
|
150
|
+
try {
|
|
151
|
+
if (!socket.destroyed) {
|
|
152
|
+
// Try graceful shutdown first, then force destroy after a short timeout
|
|
153
|
+
socket.end();
|
|
154
|
+
const socketTimeout = setTimeout(() => {
|
|
155
|
+
try {
|
|
156
|
+
if (!socket.destroyed) {
|
|
157
|
+
socket.destroy();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
console.log(`[${record.id}] Error destroying ${side} socket: ${err}`);
|
|
162
|
+
}
|
|
163
|
+
}, 1000);
|
|
164
|
+
// Ensure the timeout doesn't block Node from exiting
|
|
165
|
+
if (socketTimeout.unref) {
|
|
166
|
+
socketTimeout.unref();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
console.log(`[${record.id}] Error closing ${side} socket: ${err}`);
|
|
172
|
+
try {
|
|
173
|
+
if (!socket.destroyed) {
|
|
174
|
+
socket.destroy();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (destroyErr) {
|
|
178
|
+
console.log(`[${record.id}] Error destroying ${side} socket: ${destroyErr}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Creates a generic error handler for incoming or outgoing sockets
|
|
184
|
+
*/
|
|
185
|
+
handleError(side, record) {
|
|
186
|
+
return (err) => {
|
|
187
|
+
const code = err.code;
|
|
188
|
+
let reason = 'error';
|
|
189
|
+
const now = Date.now();
|
|
190
|
+
const connectionDuration = now - record.incomingStartTime;
|
|
191
|
+
const lastActivityAge = now - record.lastActivity;
|
|
192
|
+
if (code === 'ECONNRESET') {
|
|
193
|
+
reason = 'econnreset';
|
|
194
|
+
console.log(`[${record.id}] ECONNRESET on ${side} side from ${record.remoteIP}: ${err.message}. ` +
|
|
195
|
+
`Duration: ${plugins.prettyMs(connectionDuration)}, Last activity: ${plugins.prettyMs(lastActivityAge)} ago`);
|
|
196
|
+
}
|
|
197
|
+
else if (code === 'ETIMEDOUT') {
|
|
198
|
+
reason = 'etimedout';
|
|
199
|
+
console.log(`[${record.id}] ETIMEDOUT on ${side} side from ${record.remoteIP}: ${err.message}. ` +
|
|
200
|
+
`Duration: ${plugins.prettyMs(connectionDuration)}, Last activity: ${plugins.prettyMs(lastActivityAge)} ago`);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
console.log(`[${record.id}] Error on ${side} side from ${record.remoteIP}: ${err.message}. ` +
|
|
204
|
+
`Duration: ${plugins.prettyMs(connectionDuration)}, Last activity: ${plugins.prettyMs(lastActivityAge)} ago`);
|
|
205
|
+
}
|
|
206
|
+
if (side === 'incoming' && record.incomingTerminationReason === null) {
|
|
207
|
+
record.incomingTerminationReason = reason;
|
|
208
|
+
this.incrementTerminationStat('incoming', reason);
|
|
209
|
+
}
|
|
210
|
+
else if (side === 'outgoing' && record.outgoingTerminationReason === null) {
|
|
211
|
+
record.outgoingTerminationReason = reason;
|
|
212
|
+
this.incrementTerminationStat('outgoing', reason);
|
|
213
|
+
}
|
|
214
|
+
this.initiateCleanupOnce(record, reason);
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Creates a generic close handler for incoming or outgoing sockets
|
|
219
|
+
*/
|
|
220
|
+
handleClose(side, record) {
|
|
221
|
+
return () => {
|
|
222
|
+
if (this.settings.enableDetailedLogging) {
|
|
223
|
+
console.log(`[${record.id}] Connection closed on ${side} side from ${record.remoteIP}`);
|
|
224
|
+
}
|
|
225
|
+
if (side === 'incoming' && record.incomingTerminationReason === null) {
|
|
226
|
+
record.incomingTerminationReason = 'normal';
|
|
227
|
+
this.incrementTerminationStat('incoming', 'normal');
|
|
228
|
+
}
|
|
229
|
+
else if (side === 'outgoing' && record.outgoingTerminationReason === null) {
|
|
230
|
+
record.outgoingTerminationReason = 'normal';
|
|
231
|
+
this.incrementTerminationStat('outgoing', 'normal');
|
|
232
|
+
// Record the time when outgoing socket closed.
|
|
233
|
+
record.outgoingClosedTime = Date.now();
|
|
234
|
+
}
|
|
235
|
+
this.initiateCleanupOnce(record, 'closed_' + side);
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Increment termination statistics
|
|
240
|
+
*/
|
|
241
|
+
incrementTerminationStat(side, reason) {
|
|
242
|
+
this.terminationStats[side][reason] = (this.terminationStats[side][reason] || 0) + 1;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Get termination statistics
|
|
246
|
+
*/
|
|
247
|
+
getTerminationStats() {
|
|
248
|
+
return this.terminationStats;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Check for stalled/inactive connections
|
|
252
|
+
*/
|
|
253
|
+
performInactivityCheck() {
|
|
254
|
+
const now = Date.now();
|
|
255
|
+
const connectionIds = [...this.connectionRecords.keys()];
|
|
256
|
+
for (const id of connectionIds) {
|
|
257
|
+
const record = this.connectionRecords.get(id);
|
|
258
|
+
if (!record)
|
|
259
|
+
continue;
|
|
260
|
+
// Skip inactivity check if disabled or for immortal keep-alive connections
|
|
261
|
+
if (this.settings.disableInactivityCheck ||
|
|
262
|
+
(record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal')) {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const inactivityTime = now - record.lastActivity;
|
|
266
|
+
// Use extended timeout for extended-treatment keep-alive connections
|
|
267
|
+
let effectiveTimeout = this.settings.inactivityTimeout;
|
|
268
|
+
if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'extended') {
|
|
269
|
+
const multiplier = this.settings.keepAliveInactivityMultiplier || 6;
|
|
270
|
+
effectiveTimeout = effectiveTimeout * multiplier;
|
|
271
|
+
}
|
|
272
|
+
if (inactivityTime > effectiveTimeout && !record.connectionClosed) {
|
|
273
|
+
// For keep-alive connections, issue a warning first
|
|
274
|
+
if (record.hasKeepAlive && !record.inactivityWarningIssued) {
|
|
275
|
+
console.log(`[${id}] Warning: Keep-alive connection from ${record.remoteIP} inactive for ${plugins.prettyMs(inactivityTime)}. Will close in 10 minutes if no activity.`);
|
|
276
|
+
// Set warning flag and add grace period
|
|
277
|
+
record.inactivityWarningIssued = true;
|
|
278
|
+
record.lastActivity = now - (effectiveTimeout - 600000);
|
|
279
|
+
// Try to stimulate activity with a probe packet
|
|
280
|
+
if (record.outgoing && !record.outgoing.destroyed) {
|
|
281
|
+
try {
|
|
282
|
+
record.outgoing.write(Buffer.alloc(0));
|
|
283
|
+
if (this.settings.enableDetailedLogging) {
|
|
284
|
+
console.log(`[${id}] Sent probe packet to test keep-alive connection`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
console.log(`[${id}] Error sending probe packet: ${err}`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
// For non-keep-alive or after warning, close the connection
|
|
294
|
+
console.log(`[${id}] Inactivity check: No activity on connection from ${record.remoteIP} ` +
|
|
295
|
+
`for ${plugins.prettyMs(inactivityTime)}.` +
|
|
296
|
+
(record.hasKeepAlive ? ' Despite keep-alive being enabled.' : ''));
|
|
297
|
+
this.cleanupConnection(record, 'inactivity');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else if (inactivityTime <= effectiveTimeout && record.inactivityWarningIssued) {
|
|
301
|
+
// If activity detected after warning, clear the warning
|
|
302
|
+
if (this.settings.enableDetailedLogging) {
|
|
303
|
+
console.log(`[${id}] Connection activity detected after inactivity warning, resetting warning`);
|
|
304
|
+
}
|
|
305
|
+
record.inactivityWarningIssued = false;
|
|
306
|
+
}
|
|
307
|
+
// Parity check: if outgoing socket closed and incoming remains active
|
|
308
|
+
if (record.outgoingClosedTime &&
|
|
309
|
+
!record.incoming.destroyed &&
|
|
310
|
+
!record.connectionClosed &&
|
|
311
|
+
now - record.outgoingClosedTime > 120000) {
|
|
312
|
+
console.log(`[${id}] Parity check: Incoming socket for ${record.remoteIP} still active ${plugins.prettyMs(now - record.outgoingClosedTime)} after outgoing closed.`);
|
|
313
|
+
this.cleanupConnection(record, 'parity_check');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Clear all connections (for shutdown)
|
|
319
|
+
*/
|
|
320
|
+
clearConnections() {
|
|
321
|
+
// Create a copy of the keys to avoid modification during iteration
|
|
322
|
+
const connectionIds = [...this.connectionRecords.keys()];
|
|
323
|
+
// First pass: End all connections gracefully
|
|
324
|
+
for (const id of connectionIds) {
|
|
325
|
+
const record = this.connectionRecords.get(id);
|
|
326
|
+
if (record) {
|
|
327
|
+
try {
|
|
328
|
+
// Clear any timers
|
|
329
|
+
if (record.cleanupTimer) {
|
|
330
|
+
clearTimeout(record.cleanupTimer);
|
|
331
|
+
record.cleanupTimer = undefined;
|
|
332
|
+
}
|
|
333
|
+
// End sockets gracefully
|
|
334
|
+
if (record.incoming && !record.incoming.destroyed) {
|
|
335
|
+
record.incoming.end();
|
|
336
|
+
}
|
|
337
|
+
if (record.outgoing && !record.outgoing.destroyed) {
|
|
338
|
+
record.outgoing.end();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
catch (err) {
|
|
342
|
+
console.log(`Error during graceful connection end for ${id}: ${err}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
// Short delay to allow graceful ends to process
|
|
347
|
+
setTimeout(() => {
|
|
348
|
+
// Second pass: Force destroy everything
|
|
349
|
+
for (const id of connectionIds) {
|
|
350
|
+
const record = this.connectionRecords.get(id);
|
|
351
|
+
if (record) {
|
|
352
|
+
try {
|
|
353
|
+
// Remove all listeners to prevent memory leaks
|
|
354
|
+
if (record.incoming) {
|
|
355
|
+
record.incoming.removeAllListeners();
|
|
356
|
+
if (!record.incoming.destroyed) {
|
|
357
|
+
record.incoming.destroy();
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (record.outgoing) {
|
|
361
|
+
record.outgoing.removeAllListeners();
|
|
362
|
+
if (!record.outgoing.destroyed) {
|
|
363
|
+
record.outgoing.destroy();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
console.log(`Error during forced connection destruction for ${id}: ${err}`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// Clear all maps
|
|
373
|
+
this.connectionRecords.clear();
|
|
374
|
+
this.terminationStats = { incoming: {}, outgoing: {} };
|
|
375
|
+
}, 100);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wcC5jb25uZWN0aW9ubWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3NtYXJ0cHJveHkvY2xhc3Nlcy5wcC5jb25uZWN0aW9ubWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRWhFOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQU81QixZQUNVLFFBQTRCLEVBQzVCLGVBQWdDLEVBQ2hDLGNBQThCO1FBRjlCLGFBQVEsR0FBUixRQUFRLENBQW9CO1FBQzVCLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUNoQyxtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFUaEMsc0JBQWlCLEdBQW1DLElBQUksR0FBRyxFQUFFLENBQUM7UUFDOUQscUJBQWdCLEdBR3BCLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFNaEMsQ0FBQztJQUVKOztPQUVHO0lBQ0ksb0JBQW9CO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVEOztPQUVHO0lBQ0ksZ0JBQWdCLENBQUMsTUFBMEI7UUFDaEQsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDakQsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLGFBQWEsSUFBSSxFQUFF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
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { IDomainConfig, IPortProxySettings } from './classes.pp.interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* Manages domain configurations and target selection
|
|
4
|
+
*/
|
|
5
|
+
export declare class DomainConfigManager {
|
|
6
|
+
private settings;
|
|
7
|
+
private domainTargetIndices;
|
|
8
|
+
constructor(settings: IPortProxySettings);
|
|
9
|
+
/**
|
|
10
|
+
* Updates the domain configurations
|
|
11
|
+
*/
|
|
12
|
+
updateDomainConfigs(newDomainConfigs: IDomainConfig[]): void;
|
|
13
|
+
/**
|
|
14
|
+
* Get all domain configurations
|
|
15
|
+
*/
|
|
16
|
+
getDomainConfigs(): IDomainConfig[];
|
|
17
|
+
/**
|
|
18
|
+
* Find domain config matching a server name
|
|
19
|
+
*/
|
|
20
|
+
findDomainConfig(serverName: string): IDomainConfig | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Find domain config for a specific port
|
|
23
|
+
*/
|
|
24
|
+
findDomainConfigForPort(port: number): IDomainConfig | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Check if a port is within any of the given ranges
|
|
27
|
+
*/
|
|
28
|
+
isPortInRanges(port: number, ranges: Array<{
|
|
29
|
+
from: number;
|
|
30
|
+
to: number;
|
|
31
|
+
}>): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Get target IP with round-robin support
|
|
34
|
+
*/
|
|
35
|
+
getTargetIP(domainConfig: IDomainConfig): string;
|
|
36
|
+
/**
|
|
37
|
+
* Checks if a domain should use NetworkProxy
|
|
38
|
+
*/
|
|
39
|
+
shouldUseNetworkProxy(domainConfig: IDomainConfig): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Gets the NetworkProxy port for a domain
|
|
42
|
+
*/
|
|
43
|
+
getNetworkProxyPort(domainConfig: IDomainConfig): number | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Get effective allowed and blocked IPs for a domain
|
|
46
|
+
*/
|
|
47
|
+
getEffectiveIPRules(domainConfig: IDomainConfig): {
|
|
48
|
+
allowedIPs: string[];
|
|
49
|
+
blockedIPs: string[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Get connection timeout for a domain
|
|
53
|
+
*/
|
|
54
|
+
getConnectionTimeout(domainConfig?: IDomainConfig): number;
|
|
55
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* Manages domain configurations and target selection
|
|
4
|
+
*/
|
|
5
|
+
export class DomainConfigManager {
|
|
6
|
+
constructor(settings) {
|
|
7
|
+
this.settings = settings;
|
|
8
|
+
// Track round-robin indices for domain configs
|
|
9
|
+
this.domainTargetIndices = new Map();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Updates the domain configurations
|
|
13
|
+
*/
|
|
14
|
+
updateDomainConfigs(newDomainConfigs) {
|
|
15
|
+
this.settings.domainConfigs = newDomainConfigs;
|
|
16
|
+
// Reset target indices for removed configs
|
|
17
|
+
const currentConfigSet = new Set(newDomainConfigs);
|
|
18
|
+
for (const [config] of this.domainTargetIndices) {
|
|
19
|
+
if (!currentConfigSet.has(config)) {
|
|
20
|
+
this.domainTargetIndices.delete(config);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get all domain configurations
|
|
26
|
+
*/
|
|
27
|
+
getDomainConfigs() {
|
|
28
|
+
return this.settings.domainConfigs;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Find domain config matching a server name
|
|
32
|
+
*/
|
|
33
|
+
findDomainConfig(serverName) {
|
|
34
|
+
if (!serverName)
|
|
35
|
+
return undefined;
|
|
36
|
+
return this.settings.domainConfigs.find((config) => config.domains.some((d) => plugins.minimatch(serverName, d)));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Find domain config for a specific port
|
|
40
|
+
*/
|
|
41
|
+
findDomainConfigForPort(port) {
|
|
42
|
+
return this.settings.domainConfigs.find((domain) => domain.portRanges &&
|
|
43
|
+
domain.portRanges.length > 0 &&
|
|
44
|
+
this.isPortInRanges(port, domain.portRanges));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Check if a port is within any of the given ranges
|
|
48
|
+
*/
|
|
49
|
+
isPortInRanges(port, ranges) {
|
|
50
|
+
return ranges.some((range) => port >= range.from && port <= range.to);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get target IP with round-robin support
|
|
54
|
+
*/
|
|
55
|
+
getTargetIP(domainConfig) {
|
|
56
|
+
if (domainConfig.targetIPs && domainConfig.targetIPs.length > 0) {
|
|
57
|
+
const currentIndex = this.domainTargetIndices.get(domainConfig) || 0;
|
|
58
|
+
const ip = domainConfig.targetIPs[currentIndex % domainConfig.targetIPs.length];
|
|
59
|
+
this.domainTargetIndices.set(domainConfig, currentIndex + 1);
|
|
60
|
+
return ip;
|
|
61
|
+
}
|
|
62
|
+
return this.settings.targetIP || 'localhost';
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Checks if a domain should use NetworkProxy
|
|
66
|
+
*/
|
|
67
|
+
shouldUseNetworkProxy(domainConfig) {
|
|
68
|
+
return !!domainConfig.useNetworkProxy;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Gets the NetworkProxy port for a domain
|
|
72
|
+
*/
|
|
73
|
+
getNetworkProxyPort(domainConfig) {
|
|
74
|
+
return domainConfig.useNetworkProxy
|
|
75
|
+
? (domainConfig.networkProxyPort || this.settings.networkProxyPort)
|
|
76
|
+
: undefined;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get effective allowed and blocked IPs for a domain
|
|
80
|
+
*/
|
|
81
|
+
getEffectiveIPRules(domainConfig) {
|
|
82
|
+
return {
|
|
83
|
+
allowedIPs: [
|
|
84
|
+
...domainConfig.allowedIPs,
|
|
85
|
+
...(this.settings.defaultAllowedIPs || [])
|
|
86
|
+
],
|
|
87
|
+
blockedIPs: [
|
|
88
|
+
...(domainConfig.blockedIPs || []),
|
|
89
|
+
...(this.settings.defaultBlockedIPs || [])
|
|
90
|
+
]
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get connection timeout for a domain
|
|
95
|
+
*/
|
|
96
|
+
getConnectionTimeout(domainConfig) {
|
|
97
|
+
if (domainConfig?.connectionTimeout) {
|
|
98
|
+
return domainConfig.connectionTimeout;
|
|
99
|
+
}
|
|
100
|
+
return this.settings.maxConnectionLifetime || 86400000; // 24 hours default
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wcC5kb21haW5jb25maWdtYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc21hcnRwcm94eS9jbGFzc2VzLnBwLmRvbWFpbmNvbmZpZ21hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFHekM7O0dBRUc7QUFDSCxNQUFNLE9BQU8sbUJBQW1CO0lBSTlCLFlBQW9CLFFBQTRCO1FBQTVCLGFBQVEsR0FBUixRQUFRLENBQW9CO1FBSGhELCtDQUErQztRQUN2Qyx3QkFBbUIsR0FBK0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUVqQixDQUFDO0lBRXBEOztPQUVHO0lBQ0ksbUJBQW1CLENBQUMsZ0JBQWlDO1FBQzFELElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxHQUFHLGdCQUFnQixDQUFDO1FBRS9DLDJDQUEyQztRQUMzQyxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDbkQsS0FBSyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7WUFDaEQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO2dCQUNsQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzFDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksZ0JBQWdCO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUM7SUFDckMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksZ0JBQWdCLENBQUMsVUFBa0I7UUFDeEMsSUFBSSxDQUFDLFVBQVU7WUFBRSxPQUFPLFNBQVMsQ0FBQztRQUVsQyxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxD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
|