@push.rocks/smartproxy 3.4.0 → 3.4.3

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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '3.4.0',
6
+ version: '3.4.3',
7
7
  description: 'a proxy for handling high workloads of proxying'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLGlEQUFpRDtDQUMvRCxDQUFBIn0=
@@ -17,24 +17,58 @@ export class PortProxy {
17
17
  from.destroy();
18
18
  to.destroy();
19
19
  };
20
+ const normalizeIP = (ip) => {
21
+ // Handle IPv4-mapped IPv6 addresses
22
+ if (ip.startsWith('::ffff:')) {
23
+ const ipv4 = ip.slice(7); // Remove '::ffff:' prefix
24
+ return [ip, ipv4];
25
+ }
26
+ // Handle IPv4 addresses by adding IPv4-mapped IPv6 variant
27
+ if (ip.match(/^\d{1,3}(\.\d{1,3}){3}$/)) {
28
+ return [ip, `::ffff:${ip}`];
29
+ }
30
+ return [ip];
31
+ };
20
32
  const isAllowed = (value, patterns) => {
21
- return patterns.some(pattern => plugins.minimatch(value, pattern));
33
+ // Expand patterns to include both IPv4 and IPv6 variants
34
+ const expandedPatterns = patterns.flatMap(normalizeIP);
35
+ // Check if any variant of the IP matches any expanded pattern
36
+ return normalizeIP(value).some(ip => expandedPatterns.some(pattern => plugins.minimatch(ip, pattern)));
22
37
  };
23
38
  const findMatchingDomain = (serverName) => {
24
39
  return this.settings.domains.find(config => plugins.minimatch(serverName, config.domain));
25
40
  };
26
41
  const server = this.settings.sniEnabled
27
- ? plugins.tls.createServer(this.settings)
42
+ ? plugins.tls.createServer({
43
+ ...this.settings,
44
+ SNICallback: (serverName, cb) => {
45
+ console.log(`SNI request for domain: ${serverName}`);
46
+ const domainConfig = findMatchingDomain(serverName);
47
+ if (!domainConfig) {
48
+ console.log(`SNI rejected: No matching domain config for ${serverName}`);
49
+ cb(new Error(`No configuration for domain: ${serverName}`));
50
+ return;
51
+ }
52
+ // Create context with the provided TLS settings
53
+ const ctx = plugins.tls.createSecureContext(this.settings);
54
+ cb(null, ctx);
55
+ }
56
+ })
28
57
  : plugins.net.createServer();
29
- this.netServer = server.on('connection', (from) => {
58
+ const handleConnection = (from) => {
30
59
  const remoteIP = from.remoteAddress || '';
60
+ let serverName = '';
31
61
  if (this.settings.sniEnabled && from instanceof plugins.tls.TLSSocket) {
32
- const serverName = from.servername || '';
33
- const domainConfig = findMatchingDomain(serverName);
62
+ serverName = from.servername || '';
63
+ console.log(`TLS Connection from ${remoteIP} for domain: ${serverName}`);
64
+ }
65
+ // For TLS connections, we've already validated the domain in SNICallback
66
+ if (!this.settings.sniEnabled || from instanceof plugins.tls.TLSSocket) {
67
+ const domainConfig = serverName ? findMatchingDomain(serverName) : undefined;
34
68
  if (!domainConfig) {
35
69
  // If no matching domain config found, check default IPs if available
36
70
  if (!this.settings.defaultAllowedIPs || !isAllowed(remoteIP, this.settings.defaultAllowedIPs)) {
37
- console.log(`Connection rejected: No matching domain config for ${serverName} from IP ${remoteIP}`);
71
+ console.log(`Connection rejected: No matching domain config for ${serverName || 'non-SNI'} from IP ${remoteIP}`);
38
72
  from.end();
39
73
  return;
40
74
  }
@@ -57,6 +91,7 @@ export class PortProxy {
57
91
  host: this.settings.toHost,
58
92
  port: this.settings.toPort,
59
93
  });
94
+ console.log(`Connection established: ${remoteIP} -> ${this.settings.toHost}:${this.settings.toPort}${serverName ? ` (SNI: ${serverName})` : ''}`);
60
95
  from.setTimeout(120000);
61
96
  from.pipe(to);
62
97
  to.pipe(from);
@@ -84,9 +119,18 @@ export class PortProxy {
84
119
  to.on('end', () => {
85
120
  cleanUpSockets(from, to);
86
121
  });
122
+ };
123
+ this.netServer = server
124
+ .on('connection', handleConnection)
125
+ .on('secureConnection', handleConnection)
126
+ .on('tlsClientError', (err, tlsSocket) => {
127
+ console.log(`TLS Client Error: ${err.message}`);
128
+ })
129
+ .on('error', (err) => {
130
+ console.log(`Server Error: ${err.message}`);
87
131
  })
88
132
  .listen(this.settings.fromPort);
89
- console.log(`PortProxy -> OK: Now listening on port ${this.settings.fromPort}`);
133
+ console.log(`PortProxy -> OK: Now listening on port ${this.settings.fromPort}${this.settings.sniEnabled ? ' (SNI enabled)' : ''}`);
90
134
  }
91
135
  async stop() {
92
136
  const done = plugins.smartpromise.defer();
@@ -96,4 +140,4 @@ export class PortProxy {
96
140
  await done.promise;
97
141
  }
98
142
  }
99
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRwcm94eS5wb3J0cHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHByb3h5LnBvcnRwcm94eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHlCQUF5QixDQUFDO0FBb0JuRCxNQUFNLE9BQU8sU0FBUztJQUlwQixZQUFZLFFBQXVCO1FBQ2pDLElBQUksQ0FBQyxRQUFRLEdBQUc7WUFDZCxHQUFHLFFBQVE7WUFDWCxNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU0sSUFBSSxXQUFXO1NBQ3ZDLENBQUM7SUFDSixDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUs7UUFDaEIsTUFBTSxjQUFjLEdBQUcsQ0FBQyxJQUF3QixFQUFFLEVBQXNCLEVBQUUsRUFBRTtZQUMxRSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDWCxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDVCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUMxQixFQUFFLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDZCxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDZixFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDZixDQUFDLENBQUM7UUFDRixNQUFNLFNBQVMsR0FBRyxDQUFDLEtBQWEsRUFBRSxRQUFrQixFQUFXLEVBQUU7WUFDL0QsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNyRSxDQUFDLENBQUM7UUFFRixNQUFNLGtCQUFrQixHQUFHLENBQUMsVUFBa0IsRUFBNEIsRUFBRTtZQUMxRSxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUks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
143
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRwcm94eS5wb3J0cHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHByb3h5LnBvcnRwcm94eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHlCQUF5QixDQUFDO0FBb0JuRCxNQUFNLE9BQU8sU0FBUztJQUlwQixZQUFZLFFBQXVCO1FBQ2pDLElBQUksQ0FBQyxRQUFRLEdBQUc7WUFDZCxHQUFHLFFBQVE7WUFDWCxNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU0sSUFBSSxXQUFXO1NBQ3ZDLENBQUM7SUFDSixDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUs7UUFDaEIsTUFBTSxjQUFjLEdBQUcsQ0FBQyxJQUF3QixFQUFFLEVBQXNCLEVBQUUsRUFBRTtZQUMxRSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDWCxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDVCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUMxQixFQUFFLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDZCxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDZixFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDZixDQUFDLENBQUM7UUFDRixNQUFNLFdBQVcsR0FBRyxDQUFDLEVBQVUsRUFBWSxFQUFFO1lBQzNDLG9DQUFvQztZQUNwQyxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztnQkFDN0IsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLDBCQUEwQjtnQkFDcEQsT0FBTyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNwQixDQUFDO1lBQ0QsMkRBQTJEO1lBQzNELElBQUksRUFBRSxDQUFD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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartproxy",
3
- "version": "3.4.0",
3
+ "version": "3.4.3",
4
4
  "private": false,
5
5
  "description": "a proxy for handling high workloads of proxying",
6
6
  "main": "dist_ts/index.js",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '3.4.0',
6
+ version: '3.4.3',
7
7
  description: 'a proxy for handling high workloads of proxying'
8
8
  }
@@ -40,8 +40,26 @@ export class PortProxy {
40
40
  from.destroy();
41
41
  to.destroy();
42
42
  };
43
+ const normalizeIP = (ip: string): string[] => {
44
+ // Handle IPv4-mapped IPv6 addresses
45
+ if (ip.startsWith('::ffff:')) {
46
+ const ipv4 = ip.slice(7); // Remove '::ffff:' prefix
47
+ return [ip, ipv4];
48
+ }
49
+ // Handle IPv4 addresses by adding IPv4-mapped IPv6 variant
50
+ if (ip.match(/^\d{1,3}(\.\d{1,3}){3}$/)) {
51
+ return [ip, `::ffff:${ip}`];
52
+ }
53
+ return [ip];
54
+ };
55
+
43
56
  const isAllowed = (value: string, patterns: string[]): boolean => {
44
- return patterns.some(pattern => plugins.minimatch(value, pattern));
57
+ // Expand patterns to include both IPv4 and IPv6 variants
58
+ const expandedPatterns = patterns.flatMap(normalizeIP);
59
+ // Check if any variant of the IP matches any expanded pattern
60
+ return normalizeIP(value).some(ip =>
61
+ expandedPatterns.some(pattern => plugins.minimatch(ip, pattern))
62
+ );
45
63
  };
46
64
 
47
65
  const findMatchingDomain = (serverName: string): DomainConfig | undefined => {
@@ -49,70 +67,102 @@ export class PortProxy {
49
67
  };
50
68
 
51
69
  const server = this.settings.sniEnabled
52
- ? plugins.tls.createServer(this.settings)
70
+ ? plugins.tls.createServer({
71
+ ...this.settings,
72
+ SNICallback: (serverName: string, cb: (err: Error | null, ctx?: plugins.tls.SecureContext) => void) => {
73
+ console.log(`SNI request for domain: ${serverName}`);
74
+ const domainConfig = findMatchingDomain(serverName);
75
+ if (!domainConfig) {
76
+ console.log(`SNI rejected: No matching domain config for ${serverName}`);
77
+ cb(new Error(`No configuration for domain: ${serverName}`));
78
+ return;
79
+ }
80
+ // Create context with the provided TLS settings
81
+ const ctx = plugins.tls.createSecureContext(this.settings);
82
+ cb(null, ctx);
83
+ }
84
+ })
53
85
  : plugins.net.createServer();
54
86
 
55
- this.netServer = server.on('connection', (from: plugins.net.Socket) => {
87
+ const handleConnection = (from: plugins.net.Socket | plugins.tls.TLSSocket) => {
56
88
  const remoteIP = from.remoteAddress || '';
57
- if (this.settings.sniEnabled && from instanceof plugins.tls.TLSSocket) {
58
- const serverName = (from as any).servername || '';
59
- const domainConfig = findMatchingDomain(serverName);
60
-
61
- if (!domainConfig) {
62
- // If no matching domain config found, check default IPs if available
63
- if (!this.settings.defaultAllowedIPs || !isAllowed(remoteIP, this.settings.defaultAllowedIPs)) {
64
- console.log(`Connection rejected: No matching domain config for ${serverName} from IP ${remoteIP}`);
65
- from.end();
66
- return;
67
- }
68
- } else {
69
- // Check if IP is allowed for this domain
70
- if (!isAllowed(remoteIP, domainConfig.allowedIPs)) {
71
- console.log(`Connection rejected: IP ${remoteIP} not allowed for domain ${serverName}`);
72
- from.end();
73
- return;
74
- }
89
+ let serverName = '';
90
+
91
+ if (this.settings.sniEnabled && from instanceof plugins.tls.TLSSocket) {
92
+ serverName = (from as any).servername || '';
93
+ console.log(`TLS Connection from ${remoteIP} for domain: ${serverName}`);
94
+ }
95
+
96
+ // For TLS connections, we've already validated the domain in SNICallback
97
+ if (!this.settings.sniEnabled || from instanceof plugins.tls.TLSSocket) {
98
+ const domainConfig = serverName ? findMatchingDomain(serverName) : undefined;
99
+
100
+ if (!domainConfig) {
101
+ // If no matching domain config found, check default IPs if available
102
+ if (!this.settings.defaultAllowedIPs || !isAllowed(remoteIP, this.settings.defaultAllowedIPs)) {
103
+ console.log(`Connection rejected: No matching domain config for ${serverName || 'non-SNI'} from IP ${remoteIP}`);
104
+ from.end();
105
+ return;
106
+ }
107
+ } else {
108
+ // Check if IP is allowed for this domain
109
+ if (!isAllowed(remoteIP, domainConfig.allowedIPs)) {
110
+ console.log(`Connection rejected: IP ${remoteIP} not allowed for domain ${serverName}`);
111
+ from.end();
112
+ return;
75
113
  }
76
- } else if (!this.settings.defaultAllowedIPs || !isAllowed(remoteIP, this.settings.defaultAllowedIPs)) {
77
- console.log(`Connection rejected: IP ${remoteIP} not allowed for non-SNI connection`);
78
- from.end();
79
- return;
80
114
  }
115
+ } else if (!this.settings.defaultAllowedIPs || !isAllowed(remoteIP, this.settings.defaultAllowedIPs)) {
116
+ console.log(`Connection rejected: IP ${remoteIP} not allowed for non-SNI connection`);
117
+ from.end();
118
+ return;
119
+ }
120
+
121
+ const to = plugins.net.createConnection({
122
+ host: this.settings.toHost!,
123
+ port: this.settings.toPort,
124
+ });
125
+ console.log(`Connection established: ${remoteIP} -> ${this.settings.toHost}:${this.settings.toPort}${serverName ? ` (SNI: ${serverName})` : ''}`);
126
+ from.setTimeout(120000);
127
+ from.pipe(to);
128
+ to.pipe(from);
129
+ from.on('error', () => {
130
+ cleanUpSockets(from, to);
131
+ });
132
+ to.on('error', () => {
133
+ cleanUpSockets(from, to);
134
+ });
135
+ from.on('close', () => {
136
+ cleanUpSockets(from, to);
137
+ });
138
+ to.on('close', () => {
139
+ cleanUpSockets(from, to);
140
+ });
141
+ from.on('timeout', () => {
142
+ cleanUpSockets(from, to);
143
+ });
144
+ to.on('timeout', () => {
145
+ cleanUpSockets(from, to);
146
+ });
147
+ from.on('end', () => {
148
+ cleanUpSockets(from, to);
149
+ });
150
+ to.on('end', () => {
151
+ cleanUpSockets(from, to);
152
+ });
153
+ };
81
154
 
82
- const to = plugins.net.createConnection({
83
- host: this.settings.toHost!,
84
- port: this.settings.toPort,
85
- });
86
- from.setTimeout(120000);
87
- from.pipe(to);
88
- to.pipe(from);
89
- from.on('error', () => {
90
- cleanUpSockets(from, to);
91
- });
92
- to.on('error', () => {
93
- cleanUpSockets(from, to);
94
- });
95
- from.on('close', () => {
96
- cleanUpSockets(from, to);
97
- });
98
- to.on('close', () => {
99
- cleanUpSockets(from, to);
100
- });
101
- from.on('timeout', () => {
102
- cleanUpSockets(from, to);
103
- });
104
- to.on('timeout', () => {
105
- cleanUpSockets(from, to);
106
- });
107
- from.on('end', () => {
108
- cleanUpSockets(from, to);
109
- });
110
- to.on('end', () => {
111
- cleanUpSockets(from, to);
112
- });
155
+ this.netServer = server
156
+ .on('connection', handleConnection)
157
+ .on('secureConnection', handleConnection)
158
+ .on('tlsClientError', (err, tlsSocket) => {
159
+ console.log(`TLS Client Error: ${err.message}`);
160
+ })
161
+ .on('error', (err) => {
162
+ console.log(`Server Error: ${err.message}`);
113
163
  })
114
164
  .listen(this.settings.fromPort);
115
- console.log(`PortProxy -> OK: Now listening on port ${this.settings.fromPort}`);
165
+ console.log(`PortProxy -> OK: Now listening on port ${this.settings.fromPort}${this.settings.sniEnabled ? ' (SNI enabled)' : ''}`);
116
166
  }
117
167
 
118
168
  public async stop() {