@push.rocks/smartproxy 26.3.0 → 27.1.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/changelog.md +15 -0
- package/dist_rust/rustproxy_linux_amd64 +0 -0
- package/dist_rust/rustproxy_linux_arm64 +0 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/core/models/wrapped-socket.js +4 -1
- package/dist_ts/core/routing/route-manager.js +9 -7
- package/dist_ts/proxies/smart-proxy/datagram-handler-server.js +7 -5
- package/dist_ts/proxies/smart-proxy/route-preprocessor.js +6 -8
- package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +186 -184
- package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.js +2 -1
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +12 -6
- package/dist_ts/proxies/smart-proxy/socket-handler-server.js +5 -3
- package/dist_ts/proxies/smart-proxy/utils/concurrency-semaphore.js +4 -3
- package/dist_ts/proxies/smart-proxy/utils/index.d.ts +2 -3
- package/dist_ts/proxies/smart-proxy/utils/index.js +4 -6
- package/dist_ts/proxies/smart-proxy/utils/mutex.js +3 -5
- package/dist_ts/proxies/smart-proxy/utils/route-validator.js +7 -7
- package/dist_ts/proxies/smart-proxy/utils/{route-helpers/socket-handlers.d.ts → socket-handlers.d.ts} +2 -10
- package/dist_ts/proxies/smart-proxy/utils/socket-handlers.js +268 -0
- package/dist_ts/routing/models/http-types.js +5 -1
- package/package.json +1 -1
- package/readme.hints.md +42 -20
- package/readme.md +144 -146
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/proxies/smart-proxy/utils/index.ts +3 -11
- package/ts/proxies/smart-proxy/utils/{route-helpers/socket-handlers.ts → socket-handlers.ts} +3 -31
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.d.ts +0 -49
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.js +0 -108
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.d.ts +0 -57
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.js +0 -90
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.d.ts +0 -17
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.js +0 -32
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.d.ts +0 -68
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.js +0 -117
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.d.ts +0 -17
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.js +0 -27
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.d.ts +0 -63
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.js +0 -105
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.d.ts +0 -83
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.js +0 -126
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.d.ts +0 -47
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.js +0 -66
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +0 -286
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.d.ts +0 -46
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.js +0 -67
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +0 -9
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +0 -11
- package/ts/proxies/smart-proxy/utils/route-helpers/api-helpers.ts +0 -144
- package/ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.ts +0 -125
- package/ts/proxies/smart-proxy/utils/route-helpers/http-helpers.ts +0 -40
- package/ts/proxies/smart-proxy/utils/route-helpers/https-helpers.ts +0 -163
- package/ts/proxies/smart-proxy/utils/route-helpers/index.ts +0 -62
- package/ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.ts +0 -154
- package/ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.ts +0 -202
- package/ts/proxies/smart-proxy/utils/route-helpers/security-helpers.ts +0 -96
- package/ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.ts +0 -98
- package/ts/proxies/smart-proxy/utils/route-helpers.ts +0 -11
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NFTables Route Helper Functions
|
|
3
|
-
*
|
|
4
|
-
* This module provides utility functions for creating NFTables-based route configurations
|
|
5
|
-
* for high-performance packet forwarding at the kernel level.
|
|
6
|
-
*/
|
|
7
|
-
import type { IRouteConfig, TPortRange } from '../../models/route-types.js';
|
|
8
|
-
/**
|
|
9
|
-
* Create an NFTables-based route for high-performance packet forwarding
|
|
10
|
-
* @param nameOrDomains Name or domain(s) to match
|
|
11
|
-
* @param target Target host and port
|
|
12
|
-
* @param options Additional route options
|
|
13
|
-
* @returns Route configuration object
|
|
14
|
-
*/
|
|
15
|
-
export declare function createNfTablesRoute(nameOrDomains: string | string[], target: {
|
|
16
|
-
host: string;
|
|
17
|
-
port: number | 'preserve';
|
|
18
|
-
}, options?: {
|
|
19
|
-
ports?: TPortRange;
|
|
20
|
-
protocol?: 'tcp' | 'udp' | 'all';
|
|
21
|
-
preserveSourceIP?: boolean;
|
|
22
|
-
ipAllowList?: string[];
|
|
23
|
-
ipBlockList?: string[];
|
|
24
|
-
maxRate?: string;
|
|
25
|
-
priority?: number;
|
|
26
|
-
useTls?: boolean;
|
|
27
|
-
tableName?: string;
|
|
28
|
-
useIPSets?: boolean;
|
|
29
|
-
useAdvancedNAT?: boolean;
|
|
30
|
-
}): IRouteConfig;
|
|
31
|
-
/**
|
|
32
|
-
* Create an NFTables-based TLS termination route
|
|
33
|
-
* @param nameOrDomains Name or domain(s) to match
|
|
34
|
-
* @param target Target host and port
|
|
35
|
-
* @param options Additional route options
|
|
36
|
-
* @returns Route configuration object
|
|
37
|
-
*/
|
|
38
|
-
export declare function createNfTablesTerminateRoute(nameOrDomains: string | string[], target: {
|
|
39
|
-
host: string;
|
|
40
|
-
port: number | 'preserve';
|
|
41
|
-
}, options?: {
|
|
42
|
-
ports?: TPortRange;
|
|
43
|
-
protocol?: 'tcp' | 'udp' | 'all';
|
|
44
|
-
preserveSourceIP?: boolean;
|
|
45
|
-
ipAllowList?: string[];
|
|
46
|
-
ipBlockList?: string[];
|
|
47
|
-
maxRate?: string;
|
|
48
|
-
priority?: number;
|
|
49
|
-
tableName?: string;
|
|
50
|
-
useIPSets?: boolean;
|
|
51
|
-
useAdvancedNAT?: boolean;
|
|
52
|
-
certificate?: 'auto' | {
|
|
53
|
-
key: string;
|
|
54
|
-
cert: string;
|
|
55
|
-
};
|
|
56
|
-
}): IRouteConfig;
|
|
57
|
-
/**
|
|
58
|
-
* Create a complete NFTables-based HTTPS setup with HTTP redirect
|
|
59
|
-
* @param nameOrDomains Name or domain(s) to match
|
|
60
|
-
* @param target Target host and port
|
|
61
|
-
* @param options Additional route options
|
|
62
|
-
* @returns Array of two route configurations (HTTPS and HTTP redirect)
|
|
63
|
-
*/
|
|
64
|
-
export declare function createCompleteNfTablesHttpsServer(nameOrDomains: string | string[], target: {
|
|
65
|
-
host: string;
|
|
66
|
-
port: number | 'preserve';
|
|
67
|
-
}, options?: {
|
|
68
|
-
httpPort?: TPortRange;
|
|
69
|
-
httpsPort?: TPortRange;
|
|
70
|
-
protocol?: 'tcp' | 'udp' | 'all';
|
|
71
|
-
preserveSourceIP?: boolean;
|
|
72
|
-
ipAllowList?: string[];
|
|
73
|
-
ipBlockList?: string[];
|
|
74
|
-
maxRate?: string;
|
|
75
|
-
priority?: number;
|
|
76
|
-
tableName?: string;
|
|
77
|
-
useIPSets?: boolean;
|
|
78
|
-
useAdvancedNAT?: boolean;
|
|
79
|
-
certificate?: 'auto' | {
|
|
80
|
-
key: string;
|
|
81
|
-
cert: string;
|
|
82
|
-
};
|
|
83
|
-
}): IRouteConfig[];
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NFTables Route Helper Functions
|
|
3
|
-
*
|
|
4
|
-
* This module provides utility functions for creating NFTables-based route configurations
|
|
5
|
-
* for high-performance packet forwarding at the kernel level.
|
|
6
|
-
*/
|
|
7
|
-
import { createHttpToHttpsRedirect } from './https-helpers.js';
|
|
8
|
-
/**
|
|
9
|
-
* Create an NFTables-based route for high-performance packet forwarding
|
|
10
|
-
* @param nameOrDomains Name or domain(s) to match
|
|
11
|
-
* @param target Target host and port
|
|
12
|
-
* @param options Additional route options
|
|
13
|
-
* @returns Route configuration object
|
|
14
|
-
*/
|
|
15
|
-
export function createNfTablesRoute(nameOrDomains, target, options = {}) {
|
|
16
|
-
// Determine if this is a name or domain
|
|
17
|
-
let name;
|
|
18
|
-
let domains;
|
|
19
|
-
if (Array.isArray(nameOrDomains) || (typeof nameOrDomains === 'string' && nameOrDomains.includes('.'))) {
|
|
20
|
-
domains = nameOrDomains;
|
|
21
|
-
name = Array.isArray(nameOrDomains) ? nameOrDomains[0] : nameOrDomains;
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
name = nameOrDomains;
|
|
25
|
-
domains = undefined; // No domains
|
|
26
|
-
}
|
|
27
|
-
// Create route match
|
|
28
|
-
const match = {
|
|
29
|
-
domains,
|
|
30
|
-
ports: options.ports || 80
|
|
31
|
-
};
|
|
32
|
-
// Create route action
|
|
33
|
-
const action = {
|
|
34
|
-
type: 'forward',
|
|
35
|
-
targets: [{
|
|
36
|
-
host: target.host,
|
|
37
|
-
port: target.port
|
|
38
|
-
}],
|
|
39
|
-
forwardingEngine: 'nftables',
|
|
40
|
-
nftables: {
|
|
41
|
-
protocol: options.protocol || 'tcp',
|
|
42
|
-
preserveSourceIP: options.preserveSourceIP,
|
|
43
|
-
maxRate: options.maxRate,
|
|
44
|
-
priority: options.priority,
|
|
45
|
-
tableName: options.tableName,
|
|
46
|
-
useIPSets: options.useIPSets,
|
|
47
|
-
useAdvancedNAT: options.useAdvancedNAT
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
// Add TLS options if needed
|
|
51
|
-
if (options.useTls) {
|
|
52
|
-
action.tls = {
|
|
53
|
-
mode: 'passthrough'
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
// Create the route config
|
|
57
|
-
const routeConfig = {
|
|
58
|
-
name,
|
|
59
|
-
match,
|
|
60
|
-
action
|
|
61
|
-
};
|
|
62
|
-
// Add security if allowed or blocked IPs are specified
|
|
63
|
-
if (options.ipAllowList?.length || options.ipBlockList?.length) {
|
|
64
|
-
routeConfig.security = {
|
|
65
|
-
ipAllowList: options.ipAllowList,
|
|
66
|
-
ipBlockList: options.ipBlockList
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
return routeConfig;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Create an NFTables-based TLS termination route
|
|
73
|
-
* @param nameOrDomains Name or domain(s) to match
|
|
74
|
-
* @param target Target host and port
|
|
75
|
-
* @param options Additional route options
|
|
76
|
-
* @returns Route configuration object
|
|
77
|
-
*/
|
|
78
|
-
export function createNfTablesTerminateRoute(nameOrDomains, target, options = {}) {
|
|
79
|
-
// Create basic NFTables route
|
|
80
|
-
const route = createNfTablesRoute(nameOrDomains, target, {
|
|
81
|
-
...options,
|
|
82
|
-
ports: options.ports || 443,
|
|
83
|
-
useTls: false
|
|
84
|
-
});
|
|
85
|
-
// Set TLS termination
|
|
86
|
-
route.action.tls = {
|
|
87
|
-
mode: 'terminate',
|
|
88
|
-
certificate: options.certificate || 'auto'
|
|
89
|
-
};
|
|
90
|
-
return route;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Create a complete NFTables-based HTTPS setup with HTTP redirect
|
|
94
|
-
* @param nameOrDomains Name or domain(s) to match
|
|
95
|
-
* @param target Target host and port
|
|
96
|
-
* @param options Additional route options
|
|
97
|
-
* @returns Array of two route configurations (HTTPS and HTTP redirect)
|
|
98
|
-
*/
|
|
99
|
-
export function createCompleteNfTablesHttpsServer(nameOrDomains, target, options = {}) {
|
|
100
|
-
// Create the HTTPS route using NFTables
|
|
101
|
-
const httpsRoute = createNfTablesTerminateRoute(nameOrDomains, target, {
|
|
102
|
-
...options,
|
|
103
|
-
ports: options.httpsPort || 443
|
|
104
|
-
});
|
|
105
|
-
// Determine the domain(s) for HTTP redirect
|
|
106
|
-
const domains = typeof nameOrDomains === 'string' && !nameOrDomains.includes('.')
|
|
107
|
-
? undefined
|
|
108
|
-
: nameOrDomains;
|
|
109
|
-
// Extract the HTTPS port for the redirect destination
|
|
110
|
-
const httpsPort = typeof options.httpsPort === 'number'
|
|
111
|
-
? options.httpsPort
|
|
112
|
-
: Array.isArray(options.httpsPort) && typeof options.httpsPort[0] === 'number'
|
|
113
|
-
? options.httpsPort[0]
|
|
114
|
-
: 443;
|
|
115
|
-
// Create the HTTP redirect route (this uses standard forwarding, not NFTables)
|
|
116
|
-
const httpRedirectRoute = createHttpToHttpsRedirect(domains, // Type cast needed since domains can be undefined now
|
|
117
|
-
httpsPort, {
|
|
118
|
-
match: {
|
|
119
|
-
ports: options.httpPort || 80,
|
|
120
|
-
domains: domains // Type cast needed since domains can be undefined now
|
|
121
|
-
},
|
|
122
|
-
name: `HTTP to HTTPS Redirect for ${Array.isArray(domains) ? domains.join(', ') : domains || 'all domains'}`
|
|
123
|
-
});
|
|
124
|
-
return [httpsRoute, httpRedirectRoute];
|
|
125
|
-
}
|
|
126
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmZ0YWJsZXMtaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3RzL3Byb3hpZXMvc21hcnQtcHJveHkvdXRpbHMvcm91dGUtaGVscGVycy9uZnRhYmxlcy1oZWxwZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBR0gsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFL0Q7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUNqQyxhQUFnQyxFQUNoQyxNQUFtRCxFQUNuRCxVQVlJLEVBQUU7SUFFTix3Q0FBd0M7SUFDeEMsSUFBSSxJQUFZLENBQUM7SUFDakIsSUFBSSxPQUFzQyxDQUFDO0lBRTNDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sYUFBYSxLQUFLLFFBQVEsSUFBSSxhQUFhLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN2RyxPQUFPLEdBQUcsYUFBYSxDQUFDO1FBQ3hCLElBQUksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztJQUN6RSxDQUFDO1NBQU0sQ0FBQztRQUNOLElBQUksR0FBRyxhQUFhLENBQUM7UUFDckIsT0FBTyxHQUFHLFNBQVMsQ0FBQyxDQUFDLGFBQWE7SUFDcEMsQ0FBQztJQUVELHFCQUFxQjtJQUNyQixNQUFNLEtBQUssR0FBZ0I7UUFDekIsT0FBTztRQUNQLEtBQUssRUFBRSxPQUFPLENBQUMsS0FBSyxJQUFJLEVBQUU7S0FDM0IsQ0FBQztJQUVGLHNCQUFzQjtJQUN0QixNQUFNLE1BQU0sR0FBaUI7UUFDM0IsSUFBSSxFQUFFLFNBQVM7UUFDZixPQUFPLEVBQUUsQ0FBQztnQkFDUixJQUFJLEVBQUUsTUFB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
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security Route Helper Functions
|
|
3
|
-
*
|
|
4
|
-
* This module provides utility functions for adding security features to routes.
|
|
5
|
-
*/
|
|
6
|
-
import type { IRouteConfig } from '../../models/route-types.js';
|
|
7
|
-
/**
|
|
8
|
-
* Create a rate limiting route pattern
|
|
9
|
-
* @param baseRoute Base route to add rate limiting to
|
|
10
|
-
* @param rateLimit Rate limiting configuration
|
|
11
|
-
* @returns Route with rate limiting
|
|
12
|
-
*/
|
|
13
|
-
export declare function addRateLimiting(baseRoute: IRouteConfig, rateLimit: {
|
|
14
|
-
maxRequests: number;
|
|
15
|
-
window: number;
|
|
16
|
-
keyBy?: 'ip' | 'path' | 'header';
|
|
17
|
-
headerName?: string;
|
|
18
|
-
errorMessage?: string;
|
|
19
|
-
}): IRouteConfig;
|
|
20
|
-
/**
|
|
21
|
-
* Create a basic authentication route pattern
|
|
22
|
-
* @param baseRoute Base route to add authentication to
|
|
23
|
-
* @param auth Authentication configuration
|
|
24
|
-
* @returns Route with basic authentication
|
|
25
|
-
*/
|
|
26
|
-
export declare function addBasicAuth(baseRoute: IRouteConfig, auth: {
|
|
27
|
-
users: Array<{
|
|
28
|
-
username: string;
|
|
29
|
-
password: string;
|
|
30
|
-
}>;
|
|
31
|
-
realm?: string;
|
|
32
|
-
excludePaths?: string[];
|
|
33
|
-
}): IRouteConfig;
|
|
34
|
-
/**
|
|
35
|
-
* Create a JWT authentication route pattern
|
|
36
|
-
* @param baseRoute Base route to add JWT authentication to
|
|
37
|
-
* @param jwt JWT authentication configuration
|
|
38
|
-
* @returns Route with JWT authentication
|
|
39
|
-
*/
|
|
40
|
-
export declare function addJwtAuth(baseRoute: IRouteConfig, jwt: {
|
|
41
|
-
secret: string;
|
|
42
|
-
algorithm?: string;
|
|
43
|
-
issuer?: string;
|
|
44
|
-
audience?: string;
|
|
45
|
-
expiresIn?: number;
|
|
46
|
-
excludePaths?: string[];
|
|
47
|
-
}): IRouteConfig;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security Route Helper Functions
|
|
3
|
-
*
|
|
4
|
-
* This module provides utility functions for adding security features to routes.
|
|
5
|
-
*/
|
|
6
|
-
import { mergeRouteConfigs } from '../route-utils.js';
|
|
7
|
-
/**
|
|
8
|
-
* Create a rate limiting route pattern
|
|
9
|
-
* @param baseRoute Base route to add rate limiting to
|
|
10
|
-
* @param rateLimit Rate limiting configuration
|
|
11
|
-
* @returns Route with rate limiting
|
|
12
|
-
*/
|
|
13
|
-
export function addRateLimiting(baseRoute, rateLimit) {
|
|
14
|
-
return mergeRouteConfigs(baseRoute, {
|
|
15
|
-
security: {
|
|
16
|
-
rateLimit: {
|
|
17
|
-
enabled: true,
|
|
18
|
-
maxRequests: rateLimit.maxRequests,
|
|
19
|
-
window: rateLimit.window,
|
|
20
|
-
keyBy: rateLimit.keyBy || 'ip',
|
|
21
|
-
headerName: rateLimit.headerName,
|
|
22
|
-
errorMessage: rateLimit.errorMessage || 'Rate limit exceeded. Please try again later.'
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Create a basic authentication route pattern
|
|
29
|
-
* @param baseRoute Base route to add authentication to
|
|
30
|
-
* @param auth Authentication configuration
|
|
31
|
-
* @returns Route with basic authentication
|
|
32
|
-
*/
|
|
33
|
-
export function addBasicAuth(baseRoute, auth) {
|
|
34
|
-
return mergeRouteConfigs(baseRoute, {
|
|
35
|
-
security: {
|
|
36
|
-
basicAuth: {
|
|
37
|
-
enabled: true,
|
|
38
|
-
users: auth.users,
|
|
39
|
-
realm: auth.realm || 'Restricted Area',
|
|
40
|
-
excludePaths: auth.excludePaths || []
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Create a JWT authentication route pattern
|
|
47
|
-
* @param baseRoute Base route to add JWT authentication to
|
|
48
|
-
* @param jwt JWT authentication configuration
|
|
49
|
-
* @returns Route with JWT authentication
|
|
50
|
-
*/
|
|
51
|
-
export function addJwtAuth(baseRoute, jwt) {
|
|
52
|
-
return mergeRouteConfigs(baseRoute, {
|
|
53
|
-
security: {
|
|
54
|
-
jwtAuth: {
|
|
55
|
-
enabled: true,
|
|
56
|
-
secret: jwt.secret,
|
|
57
|
-
algorithm: jwt.algorithm || 'HS256',
|
|
58
|
-
issuer: jwt.issuer,
|
|
59
|
-
audience: jwt.audience,
|
|
60
|
-
expiresIn: jwt.expiresIn,
|
|
61
|
-
excludePaths: jwt.excludePaths || []
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VjdXJpdHktaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3RzL3Byb3hpZXMvc21hcnQtcHJveHkvdXRpbHMvcm91dGUtaGVscGVycy9zZWN1cml0eS1oZWxwZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFHSCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUV0RDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQzdCLFNBQXVCLEVBQ3ZCLFNBTUM7SUFFRCxPQUFPLGlCQUFpQixDQUFDLFNBQVMsRUFBRTtRQUNsQyxRQUFRLEVBQUU7WUFDUixTQUFTLEVBQUU7Z0JBQ1QsT0FBTyxFQUFFLElBQUk7Z0JBQ2IsV0FBVyxFQUFFLFNBQVMsQ0FBQyxXQUFXO2dCQUNsQyxNQUFNLEVBQUUsU0FBUyxDQUFDLE1BQU07Z0JBQ3hCLEtBQUssRUFBRSxTQUFTLENBQUMsS0FBSyxJQUFJLElBQUk7Z0JBQzlCLFVBQVUsRUFBRSxTQUFTLENBQUMsVUFBVTtnQkFDaEMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxZQUFZLElBQUksOENBQThDO2FBQ3ZGO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUMxQixTQUF1QixFQUN2QixJQUlDO0lBRUQsT0FBTyxpQkFBaUIsQ0FBQyxTQUFTLEVBQUU7UUFDbEMsUUFBUSxFQUFFO1lBQ1IsU0FBUyxFQUFFO2dCQUNULE9BQU8sRUFBRSxJQUFJO2dCQUNiLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztnQkFDakIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLElBQUksaUJBQWlCO2dCQUN0QyxZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVksSUFBSSxFQUFFO2FBQ3RDO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUN4QixTQUF1QixFQUN2QixHQU9DO0lBRUQsT0FBTyxpQkFBaUIsQ0FBQyxTQUFTLEVBQUU7UUFDbEMsUUFBUSxFQUFFO1lBQ1IsT0FBTyxFQUFFO2dCQUNQLE9BQU8sRUFBRSxJQUFJO2dCQUNiLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTTtnQkFDbEIsU0FBUyxFQUFFLEdBQUcsQ0FBQyxTQUFTLElBQUksT0FBTztnQkFDbkMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNO2dCQUNsQixRQUFRLEVBQUUsR0FBRyxDQUFDLFFBQVE7Z0JBQ3RCLFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUztnQkFDeEIsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZLElBQUksRUFBRTthQUNyQztTQUNGO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyJ9
|
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Socket Handler Functions
|
|
3
|
-
*
|
|
4
|
-
* This module provides pre-built socket handlers for common use cases
|
|
5
|
-
* like echoing, proxying, HTTP responses, and redirects.
|
|
6
|
-
*/
|
|
7
|
-
import * as plugins from '../../../../plugins.js';
|
|
8
|
-
import { createSocketTracker } from '../../../../core/utils/socket-tracker.js';
|
|
9
|
-
/**
|
|
10
|
-
* Minimal HTTP request parser for socket handlers.
|
|
11
|
-
* Parses method, path, and optionally headers from a raw buffer.
|
|
12
|
-
*/
|
|
13
|
-
function parseHttpRequest(data, extractHeaders = false) {
|
|
14
|
-
const str = data.toString('utf8');
|
|
15
|
-
const headerEnd = str.indexOf('\r\n\r\n');
|
|
16
|
-
const isComplete = headerEnd !== -1;
|
|
17
|
-
const headerSection = isComplete ? str.slice(0, headerEnd) : str;
|
|
18
|
-
const lines = headerSection.split('\r\n');
|
|
19
|
-
const requestLine = lines[0];
|
|
20
|
-
if (!requestLine)
|
|
21
|
-
return null;
|
|
22
|
-
const parts = requestLine.split(' ');
|
|
23
|
-
if (parts.length < 2)
|
|
24
|
-
return null;
|
|
25
|
-
const method = parts[0];
|
|
26
|
-
const path = parts[1];
|
|
27
|
-
// Quick check: valid HTTP method
|
|
28
|
-
const validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'];
|
|
29
|
-
if (!validMethods.includes(method))
|
|
30
|
-
return null;
|
|
31
|
-
const headers = {};
|
|
32
|
-
if (extractHeaders) {
|
|
33
|
-
for (let i = 1; i < lines.length; i++) {
|
|
34
|
-
const colonIdx = lines[i].indexOf(':');
|
|
35
|
-
if (colonIdx > 0) {
|
|
36
|
-
const name = lines[i].slice(0, colonIdx).trim().toLowerCase();
|
|
37
|
-
const value = lines[i].slice(colonIdx + 1).trim();
|
|
38
|
-
headers[name] = value;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const body = isComplete ? str.slice(headerEnd + 4) : undefined;
|
|
43
|
-
return { method, path, headers, isComplete, body };
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Pre-built socket handlers for common use cases
|
|
47
|
-
*/
|
|
48
|
-
export const SocketHandlers = {
|
|
49
|
-
/**
|
|
50
|
-
* Simple echo server handler
|
|
51
|
-
*/
|
|
52
|
-
echo: (socket, context) => {
|
|
53
|
-
socket.write('ECHO SERVER READY\n');
|
|
54
|
-
socket.on('data', data => socket.write(data));
|
|
55
|
-
},
|
|
56
|
-
/**
|
|
57
|
-
* TCP proxy handler
|
|
58
|
-
*/
|
|
59
|
-
proxy: (targetHost, targetPort) => (socket, context) => {
|
|
60
|
-
const target = plugins.net.connect(targetPort, targetHost);
|
|
61
|
-
socket.pipe(target);
|
|
62
|
-
target.pipe(socket);
|
|
63
|
-
socket.on('close', () => target.destroy());
|
|
64
|
-
target.on('close', () => socket.destroy());
|
|
65
|
-
target.on('error', (err) => {
|
|
66
|
-
console.error('Proxy target error:', err);
|
|
67
|
-
socket.destroy();
|
|
68
|
-
});
|
|
69
|
-
},
|
|
70
|
-
/**
|
|
71
|
-
* Line-based protocol handler
|
|
72
|
-
*/
|
|
73
|
-
lineProtocol: (handler) => (socket, context) => {
|
|
74
|
-
let buffer = '';
|
|
75
|
-
socket.on('data', (data) => {
|
|
76
|
-
buffer += data.toString();
|
|
77
|
-
const lines = buffer.split('\n');
|
|
78
|
-
buffer = lines.pop() || '';
|
|
79
|
-
lines.forEach(line => {
|
|
80
|
-
if (line.trim()) {
|
|
81
|
-
handler(line.trim(), socket);
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
},
|
|
86
|
-
/**
|
|
87
|
-
* Simple HTTP response handler (for testing)
|
|
88
|
-
*/
|
|
89
|
-
httpResponse: (statusCode, body) => (socket, context) => {
|
|
90
|
-
const response = [
|
|
91
|
-
`HTTP/1.1 ${statusCode} ${statusCode === 200 ? 'OK' : 'Error'}`,
|
|
92
|
-
'Content-Type: text/plain',
|
|
93
|
-
`Content-Length: ${body.length}`,
|
|
94
|
-
'Connection: close',
|
|
95
|
-
'',
|
|
96
|
-
body
|
|
97
|
-
].join('\r\n');
|
|
98
|
-
socket.write(response);
|
|
99
|
-
socket.end();
|
|
100
|
-
},
|
|
101
|
-
/**
|
|
102
|
-
* Block connection immediately
|
|
103
|
-
*/
|
|
104
|
-
block: (message) => (socket, context) => {
|
|
105
|
-
const finalMessage = message || `Connection blocked from ${context.clientIp}`;
|
|
106
|
-
if (finalMessage) {
|
|
107
|
-
socket.write(finalMessage);
|
|
108
|
-
}
|
|
109
|
-
socket.end();
|
|
110
|
-
},
|
|
111
|
-
/**
|
|
112
|
-
* HTTP block response
|
|
113
|
-
*/
|
|
114
|
-
httpBlock: (statusCode = 403, message) => (socket, context) => {
|
|
115
|
-
const defaultMessage = `Access forbidden for ${context.domain || context.clientIp}`;
|
|
116
|
-
const finalMessage = message || defaultMessage;
|
|
117
|
-
const response = [
|
|
118
|
-
`HTTP/1.1 ${statusCode} ${finalMessage}`,
|
|
119
|
-
'Content-Type: text/plain',
|
|
120
|
-
`Content-Length: ${finalMessage.length}`,
|
|
121
|
-
'Connection: close',
|
|
122
|
-
'',
|
|
123
|
-
finalMessage
|
|
124
|
-
].join('\r\n');
|
|
125
|
-
socket.write(response);
|
|
126
|
-
socket.end();
|
|
127
|
-
},
|
|
128
|
-
/**
|
|
129
|
-
* HTTP redirect handler
|
|
130
|
-
*/
|
|
131
|
-
httpRedirect: (locationTemplate, statusCode = 301) => (socket, context) => {
|
|
132
|
-
const tracker = createSocketTracker(socket);
|
|
133
|
-
const handleData = (data) => {
|
|
134
|
-
const parsed = parseHttpRequest(data);
|
|
135
|
-
if (parsed) {
|
|
136
|
-
const path = parsed.path || '/';
|
|
137
|
-
const domain = context.domain || 'localhost';
|
|
138
|
-
const port = context.port;
|
|
139
|
-
const finalLocation = locationTemplate
|
|
140
|
-
.replace('{domain}', domain)
|
|
141
|
-
.replace('{port}', String(port))
|
|
142
|
-
.replace('{path}', path)
|
|
143
|
-
.replace('{clientIp}', context.clientIp);
|
|
144
|
-
const message = `Redirecting to ${finalLocation}`;
|
|
145
|
-
const response = [
|
|
146
|
-
`HTTP/1.1 ${statusCode} ${statusCode === 301 ? 'Moved Permanently' : 'Found'}`,
|
|
147
|
-
`Location: ${finalLocation}`,
|
|
148
|
-
'Content-Type: text/plain',
|
|
149
|
-
`Content-Length: ${message.length}`,
|
|
150
|
-
'Connection: close',
|
|
151
|
-
'',
|
|
152
|
-
message
|
|
153
|
-
].join('\r\n');
|
|
154
|
-
socket.write(response);
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
socket.write('HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n');
|
|
158
|
-
}
|
|
159
|
-
socket.end();
|
|
160
|
-
tracker.cleanup();
|
|
161
|
-
};
|
|
162
|
-
socket.once('data', handleData);
|
|
163
|
-
tracker.addListener('error', (err) => {
|
|
164
|
-
tracker.safeDestroy(err);
|
|
165
|
-
});
|
|
166
|
-
tracker.addListener('close', () => {
|
|
167
|
-
tracker.cleanup();
|
|
168
|
-
});
|
|
169
|
-
},
|
|
170
|
-
/**
|
|
171
|
-
* HTTP server handler for ACME challenges and other HTTP needs
|
|
172
|
-
*/
|
|
173
|
-
httpServer: (handler) => (socket, context) => {
|
|
174
|
-
const tracker = createSocketTracker(socket);
|
|
175
|
-
let requestParsed = false;
|
|
176
|
-
let responseTimer = null;
|
|
177
|
-
const processData = (data) => {
|
|
178
|
-
if (requestParsed)
|
|
179
|
-
return;
|
|
180
|
-
const parsed = parseHttpRequest(data, true);
|
|
181
|
-
if (!parsed || !parsed.isComplete) {
|
|
182
|
-
return; // Not a complete HTTP request yet
|
|
183
|
-
}
|
|
184
|
-
requestParsed = true;
|
|
185
|
-
socket.removeListener('data', processData);
|
|
186
|
-
const req = {
|
|
187
|
-
method: parsed.method,
|
|
188
|
-
url: parsed.path,
|
|
189
|
-
headers: parsed.headers,
|
|
190
|
-
body: parsed.body || ''
|
|
191
|
-
};
|
|
192
|
-
let statusCode = 200;
|
|
193
|
-
const responseHeaders = {};
|
|
194
|
-
let ended = false;
|
|
195
|
-
const res = {
|
|
196
|
-
status: (code) => {
|
|
197
|
-
statusCode = code;
|
|
198
|
-
},
|
|
199
|
-
header: (name, value) => {
|
|
200
|
-
responseHeaders[name] = value;
|
|
201
|
-
},
|
|
202
|
-
send: (data) => {
|
|
203
|
-
if (ended)
|
|
204
|
-
return;
|
|
205
|
-
ended = true;
|
|
206
|
-
if (responseTimer) {
|
|
207
|
-
clearTimeout(responseTimer);
|
|
208
|
-
responseTimer = null;
|
|
209
|
-
}
|
|
210
|
-
if (!responseHeaders['content-type']) {
|
|
211
|
-
responseHeaders['content-type'] = 'text/plain';
|
|
212
|
-
}
|
|
213
|
-
responseHeaders['content-length'] = String(data.length);
|
|
214
|
-
responseHeaders['connection'] = 'close';
|
|
215
|
-
const statusText = statusCode === 200 ? 'OK' :
|
|
216
|
-
statusCode === 404 ? 'Not Found' :
|
|
217
|
-
statusCode === 500 ? 'Internal Server Error' : 'Response';
|
|
218
|
-
let response = `HTTP/1.1 ${statusCode} ${statusText}\r\n`;
|
|
219
|
-
for (const [name, value] of Object.entries(responseHeaders)) {
|
|
220
|
-
response += `${name}: ${value}\r\n`;
|
|
221
|
-
}
|
|
222
|
-
response += '\r\n';
|
|
223
|
-
response += data;
|
|
224
|
-
socket.write(response);
|
|
225
|
-
socket.end();
|
|
226
|
-
},
|
|
227
|
-
end: () => {
|
|
228
|
-
if (ended)
|
|
229
|
-
return;
|
|
230
|
-
ended = true;
|
|
231
|
-
socket.write('HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: close\r\n\r\n');
|
|
232
|
-
socket.end();
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
try {
|
|
236
|
-
handler(req, res);
|
|
237
|
-
responseTimer = setTimeout(() => {
|
|
238
|
-
if (!ended) {
|
|
239
|
-
res.send('');
|
|
240
|
-
}
|
|
241
|
-
responseTimer = null;
|
|
242
|
-
}, 1000);
|
|
243
|
-
tracker.addTimer(responseTimer);
|
|
244
|
-
}
|
|
245
|
-
catch (error) {
|
|
246
|
-
if (!ended) {
|
|
247
|
-
res.status(500);
|
|
248
|
-
res.send('Internal Server Error');
|
|
249
|
-
}
|
|
250
|
-
tracker.safeDestroy(error instanceof Error ? error : new Error('Handler error'));
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
tracker.addListener('data', processData);
|
|
254
|
-
tracker.addListener('error', (err) => {
|
|
255
|
-
if (!requestParsed) {
|
|
256
|
-
tracker.safeDestroy(err);
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
tracker.addListener('close', () => {
|
|
260
|
-
if (responseTimer) {
|
|
261
|
-
clearTimeout(responseTimer);
|
|
262
|
-
responseTimer = null;
|
|
263
|
-
}
|
|
264
|
-
tracker.cleanup();
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
/**
|
|
269
|
-
* Create a socket handler route configuration
|
|
270
|
-
*/
|
|
271
|
-
export function createSocketHandlerRoute(domains, ports, handler, options = {}) {
|
|
272
|
-
return {
|
|
273
|
-
name: options.name || 'socket-handler-route',
|
|
274
|
-
priority: options.priority !== undefined ? options.priority : 50,
|
|
275
|
-
match: {
|
|
276
|
-
domains,
|
|
277
|
-
ports,
|
|
278
|
-
...(options.path && { path: options.path })
|
|
279
|
-
},
|
|
280
|
-
action: {
|
|
281
|
-
type: 'socket-handler',
|
|
282
|
-
socketHandler: handler
|
|
283
|
-
}
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja2V0LWhhbmRsZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdHMvcHJveGllcy9zbWFydC1wcm94eS91dGlscy9yb3V0ZS1oZWxwZXJzL3NvY2tldC1oYW5kbGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFFbEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFFL0U7OztHQUdHO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxJQUFZLEVBQUUsaUJBQTBCLEtBQUs7SUFPckUsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsQyxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzFDLE1BQU0sVUFBVSxHQUFHLFNBQVMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNwQyxNQUFNLGFBQWEsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDakUsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0IsSUFBSSxDQUFDLFdBQVc7UUFBRSxPQUFPLElBQUksQ0FBQztJQUU5QixNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFFbEMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLE1BQU0s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
|