@push.rocks/smartproxy 21.1.7 → 22.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/changelog.md +81 -0
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/core/utils/shared-security-manager.d.ts +17 -0
  4. package/dist_ts/core/utils/shared-security-manager.js +66 -1
  5. package/dist_ts/proxies/http-proxy/default-certificates.d.ts +54 -0
  6. package/dist_ts/proxies/http-proxy/default-certificates.js +127 -0
  7. package/dist_ts/proxies/http-proxy/http-proxy.d.ts +1 -1
  8. package/dist_ts/proxies/http-proxy/http-proxy.js +9 -14
  9. package/dist_ts/proxies/http-proxy/index.d.ts +5 -1
  10. package/dist_ts/proxies/http-proxy/index.js +6 -2
  11. package/dist_ts/proxies/http-proxy/security-manager.d.ts +4 -12
  12. package/dist_ts/proxies/http-proxy/security-manager.js +66 -99
  13. package/dist_ts/proxies/nftables-proxy/index.d.ts +1 -0
  14. package/dist_ts/proxies/nftables-proxy/index.js +2 -1
  15. package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +4 -26
  16. package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +84 -236
  17. package/dist_ts/proxies/nftables-proxy/utils/index.d.ts +9 -0
  18. package/dist_ts/proxies/nftables-proxy/utils/index.js +12 -0
  19. package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.d.ts +66 -0
  20. package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.js +131 -0
  21. package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.d.ts +39 -0
  22. package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.js +112 -0
  23. package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.d.ts +59 -0
  24. package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.js +130 -0
  25. package/dist_ts/proxies/smart-proxy/certificate-manager.js +4 -3
  26. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +13 -2
  27. package/dist_ts/proxies/smart-proxy/connection-manager.js +16 -6
  28. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +35 -10
  29. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +0 -1
  30. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +17 -0
  31. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +72 -9
  32. package/dist_ts/proxies/smart-proxy/security-manager.d.ts +14 -12
  33. package/dist_ts/proxies/smart-proxy/security-manager.js +80 -74
  34. package/dist_ts/proxies/smart-proxy/smart-proxy.js +1 -2
  35. package/dist_ts/proxies/smart-proxy/tls-manager.d.ts +2 -9
  36. package/dist_ts/proxies/smart-proxy/tls-manager.js +3 -26
  37. package/dist_ts/proxies/smart-proxy/utils/index.d.ts +1 -1
  38. package/dist_ts/proxies/smart-proxy/utils/index.js +3 -4
  39. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.d.ts +49 -0
  40. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.js +108 -0
  41. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.d.ts +57 -0
  42. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.js +89 -0
  43. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.d.ts +17 -0
  44. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.js +32 -0
  45. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.d.ts +68 -0
  46. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.js +117 -0
  47. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.d.ts +17 -0
  48. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.js +27 -0
  49. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.d.ts +63 -0
  50. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.js +105 -0
  51. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.d.ts +83 -0
  52. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.js +126 -0
  53. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.d.ts +47 -0
  54. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.js +66 -0
  55. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +70 -0
  56. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +287 -0
  57. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.d.ts +46 -0
  58. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.js +67 -0
  59. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +4 -457
  60. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +6 -950
  61. package/dist_ts/proxies/smart-proxy/utils/route-utils.js +2 -2
  62. package/dist_ts/proxies/smart-proxy/utils/route-validator.d.ts +67 -1
  63. package/dist_ts/proxies/smart-proxy/utils/route-validator.js +251 -3
  64. package/npmextra.json +12 -6
  65. package/package.json +34 -24
  66. package/readme.hints.md +184 -1
  67. package/readme.md +235 -172
  68. package/ts/00_commitinfo_data.ts +1 -1
  69. package/ts/core/utils/shared-security-manager.ts +98 -13
  70. package/ts/proxies/http-proxy/default-certificates.ts +150 -0
  71. package/ts/proxies/http-proxy/http-proxy.ts +9 -15
  72. package/ts/proxies/http-proxy/index.ts +6 -1
  73. package/ts/proxies/http-proxy/security-manager.ts +141 -161
  74. package/ts/proxies/nftables-proxy/index.ts +1 -0
  75. package/ts/proxies/nftables-proxy/nftables-proxy.ts +116 -290
  76. package/ts/proxies/nftables-proxy/utils/index.ts +38 -0
  77. package/ts/proxies/nftables-proxy/utils/nft-command-executor.ts +162 -0
  78. package/ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.ts +125 -0
  79. package/ts/proxies/nftables-proxy/utils/nft-rule-validator.ts +156 -0
  80. package/ts/proxies/smart-proxy/certificate-manager.ts +3 -2
  81. package/ts/proxies/smart-proxy/connection-manager.ts +21 -8
  82. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +39 -13
  83. package/ts/proxies/smart-proxy/models/interfaces.ts +0 -1
  84. package/ts/proxies/smart-proxy/route-connection-handler.ts +88 -16
  85. package/ts/proxies/smart-proxy/security-manager.ts +98 -86
  86. package/ts/proxies/smart-proxy/smart-proxy.ts +0 -2
  87. package/ts/proxies/smart-proxy/tls-manager.ts +1 -37
  88. package/ts/proxies/smart-proxy/utils/index.ts +3 -5
  89. package/ts/proxies/smart-proxy/utils/route-helpers/api-helpers.ts +144 -0
  90. package/ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.ts +124 -0
  91. package/ts/proxies/smart-proxy/utils/route-helpers/http-helpers.ts +40 -0
  92. package/ts/proxies/smart-proxy/utils/route-helpers/https-helpers.ts +163 -0
  93. package/ts/proxies/smart-proxy/utils/route-helpers/index.ts +62 -0
  94. package/ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.ts +154 -0
  95. package/ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.ts +202 -0
  96. package/ts/proxies/smart-proxy/utils/route-helpers/security-helpers.ts +96 -0
  97. package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +337 -0
  98. package/ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.ts +98 -0
  99. package/ts/proxies/smart-proxy/utils/route-helpers.ts +5 -1302
  100. package/ts/proxies/smart-proxy/utils/route-utils.ts +1 -1
  101. package/ts/proxies/smart-proxy/utils/route-validator.ts +274 -4
  102. package/ts/proxies/http-proxy/certificate-manager.ts +0 -244
  103. package/ts/proxies/smart-proxy/utils/route-validators.ts +0 -283
@@ -0,0 +1,9 @@
1
+ /**
2
+ * NFTables Proxy Utilities
3
+ *
4
+ * This module exports utility functions and classes for NFTables operations.
5
+ */
6
+ export { NftCommandExecutor } from './nft-command-executor.js';
7
+ export type { INftLoggerFn, INftExecutorOptions } from './nft-command-executor.js';
8
+ export { normalizePortSpec, validatePorts, formatPortRange, portSpecToNftExpr, rangesOverlap, mergeOverlappingRanges, countPorts, isPortInSpec } from './nft-port-spec-normalizer.js';
9
+ export { isValidIP, isValidIPv4, isValidIPv6, isValidHostname, isValidTableName, isValidRate, validateIPs, validateHost, validateTableName, validateQosSettings, validateSettings, isIPForFamily, filterIPsByFamily } from './nft-rule-validator.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * NFTables Proxy Utilities
3
+ *
4
+ * This module exports utility functions and classes for NFTables operations.
5
+ */
6
+ // Command execution
7
+ export { NftCommandExecutor } from './nft-command-executor.js';
8
+ // Port specification normalization
9
+ export { normalizePortSpec, validatePorts, formatPortRange, portSpecToNftExpr, rangesOverlap, mergeOverlappingRanges, countPorts, isPortInSpec } from './nft-port-spec-normalizer.js';
10
+ // Rule validation
11
+ export { isValidIP, isValidIPv4, isValidIPv6, isValidHostname, isValidTableName, isValidRate, validateIPs, validateHost, validateTableName, validateQosSettings, validateSettings, isIPForFamily, filterIPsByFamily } from './nft-rule-validator.js';
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9wcm94aWVzL25mdGFibGVzLXByb3h5L3V0aWxzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSCxvQkFBb0I7QUFDcEIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFHL0QsbUNBQW1DO0FBQ25DLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsYUFBYSxFQUNiLGVBQWUsRUFDZixpQkFBaUIsRUFDakIsYUFBYSxFQUNiLHNCQUFzQixFQUN0QixVQUFVLEVBQ1YsWUFBWSxFQUNiLE1BQU0sK0JBQStCLENBQUM7QUFFdkMsa0JBQWtCO0FBQ2xCLE9BQU8sRUFDTCxTQUFTLEVBQ1QsV0FBVyxFQUNYLFdBQVcsRUFDWCxlQUFlLEVBQ2YsZ0JBQWdCLEVBQ2hCLFdBQVcsRUFDWCxXQUFXLEVBQ1gsWUFBWSxFQUNaLGlCQUFpQixFQUNqQixtQkFBbUIsRUFDbkIsZ0JBQWdCLEVBQ2hCLGFBQWEsRUFDYixpQkFBaUIsRUFDbEIsTUFBTSx5QkFBeUIsQ0FBQyJ9
@@ -0,0 +1,66 @@
1
+ /**
2
+ * NFTables Command Executor
3
+ *
4
+ * Handles command execution with retry logic, temp file management,
5
+ * and error handling for nftables operations.
6
+ */
7
+ export interface INftLoggerFn {
8
+ (level: 'info' | 'warn' | 'error' | 'debug', message: string, data?: Record<string, any>): void;
9
+ }
10
+ export interface INftExecutorOptions {
11
+ maxRetries?: number;
12
+ retryDelayMs?: number;
13
+ tempFilePath?: string;
14
+ }
15
+ /**
16
+ * NFTables command executor with retry logic and temp file support
17
+ */
18
+ export declare class NftCommandExecutor {
19
+ private log;
20
+ private static readonly NFT_CMD;
21
+ private maxRetries;
22
+ private retryDelayMs;
23
+ private tempFilePath;
24
+ constructor(log: INftLoggerFn, options?: INftExecutorOptions);
25
+ /**
26
+ * Execute a command with retry capability
27
+ */
28
+ executeWithRetry(command: string, maxRetries?: number, retryDelayMs?: number): Promise<string>;
29
+ /**
30
+ * Execute system command synchronously (single attempt, no retry)
31
+ * Used only for exit handlers where the process is terminating anyway.
32
+ */
33
+ executeSync(command: string): string;
34
+ /**
35
+ * Execute nftables commands with a temporary file
36
+ */
37
+ executeWithTempFile(rulesetContent: string): Promise<void>;
38
+ /**
39
+ * Check if nftables is available
40
+ */
41
+ checkAvailability(): Promise<boolean>;
42
+ /**
43
+ * Check if connection tracking modules are loaded
44
+ */
45
+ checkConntrackModules(): Promise<boolean>;
46
+ /**
47
+ * Run an nft command directly
48
+ */
49
+ nft(args: string): Promise<string>;
50
+ /**
51
+ * Run an nft command synchronously (for cleanup on exit)
52
+ */
53
+ nftSync(args: string): string;
54
+ /**
55
+ * Get the NFT command path
56
+ */
57
+ static get nftCmd(): string;
58
+ /**
59
+ * Update the temp file path
60
+ */
61
+ setTempFilePath(path: string): void;
62
+ /**
63
+ * Update retry settings
64
+ */
65
+ setRetryOptions(maxRetries: number, retryDelayMs: number): void;
66
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * NFTables Command Executor
3
+ *
4
+ * Handles command execution with retry logic, temp file management,
5
+ * and error handling for nftables operations.
6
+ */
7
+ import { exec, execSync } from 'child_process';
8
+ import { promisify } from 'util';
9
+ import { delay } from '../../../core/utils/async-utils.js';
10
+ import { AsyncFileSystem } from '../../../core/utils/fs-utils.js';
11
+ import { NftExecutionError } from '../models/index.js';
12
+ const execAsync = promisify(exec);
13
+ /**
14
+ * NFTables command executor with retry logic and temp file support
15
+ */
16
+ export class NftCommandExecutor {
17
+ static { this.NFT_CMD = 'nft'; }
18
+ constructor(log, options = {}) {
19
+ this.log = log;
20
+ this.maxRetries = options.maxRetries || 3;
21
+ this.retryDelayMs = options.retryDelayMs || 1000;
22
+ this.tempFilePath = options.tempFilePath || `/tmp/nft-rules-${Date.now()}.nft`;
23
+ }
24
+ /**
25
+ * Execute a command with retry capability
26
+ */
27
+ async executeWithRetry(command, maxRetries, retryDelayMs) {
28
+ const retries = maxRetries ?? this.maxRetries;
29
+ const delayMs = retryDelayMs ?? this.retryDelayMs;
30
+ let lastError;
31
+ for (let i = 0; i < retries; i++) {
32
+ try {
33
+ const { stdout } = await execAsync(command);
34
+ return stdout;
35
+ }
36
+ catch (err) {
37
+ lastError = err;
38
+ this.log('warn', `Command failed (attempt ${i + 1}/${retries}): ${command}`, { error: lastError.message });
39
+ // Wait before retry, unless it's the last attempt
40
+ if (i < retries - 1) {
41
+ await delay(delayMs);
42
+ }
43
+ }
44
+ }
45
+ throw new NftExecutionError(`Failed after ${retries} attempts: ${lastError?.message || 'Unknown error'}`);
46
+ }
47
+ /**
48
+ * Execute system command synchronously (single attempt, no retry)
49
+ * Used only for exit handlers where the process is terminating anyway.
50
+ */
51
+ executeSync(command) {
52
+ try {
53
+ return execSync(command, { timeout: 5000 }).toString();
54
+ }
55
+ catch (err) {
56
+ this.log('warn', `Sync command failed: ${command}`, { error: err.message });
57
+ throw err;
58
+ }
59
+ }
60
+ /**
61
+ * Execute nftables commands with a temporary file
62
+ */
63
+ async executeWithTempFile(rulesetContent) {
64
+ await AsyncFileSystem.writeFile(this.tempFilePath, rulesetContent);
65
+ try {
66
+ await this.executeWithRetry(`${NftCommandExecutor.NFT_CMD} -f ${this.tempFilePath}`, this.maxRetries, this.retryDelayMs);
67
+ }
68
+ finally {
69
+ // Always clean up the temp file
70
+ await AsyncFileSystem.remove(this.tempFilePath);
71
+ }
72
+ }
73
+ /**
74
+ * Check if nftables is available
75
+ */
76
+ async checkAvailability() {
77
+ try {
78
+ await this.executeWithRetry(`${NftCommandExecutor.NFT_CMD} --version`, this.maxRetries, this.retryDelayMs);
79
+ return true;
80
+ }
81
+ catch (err) {
82
+ this.log('error', `nftables is not available: ${err.message}`);
83
+ return false;
84
+ }
85
+ }
86
+ /**
87
+ * Check if connection tracking modules are loaded
88
+ */
89
+ async checkConntrackModules() {
90
+ try {
91
+ await this.executeWithRetry('lsmod | grep nf_conntrack', this.maxRetries, this.retryDelayMs);
92
+ return true;
93
+ }
94
+ catch (err) {
95
+ this.log('warn', 'Connection tracking modules might not be loaded, advanced NAT features may not work');
96
+ return false;
97
+ }
98
+ }
99
+ /**
100
+ * Run an nft command directly
101
+ */
102
+ async nft(args) {
103
+ return this.executeWithRetry(`${NftCommandExecutor.NFT_CMD} ${args}`, this.maxRetries, this.retryDelayMs);
104
+ }
105
+ /**
106
+ * Run an nft command synchronously (for cleanup on exit)
107
+ */
108
+ nftSync(args) {
109
+ return this.executeSync(`${NftCommandExecutor.NFT_CMD} ${args}`);
110
+ }
111
+ /**
112
+ * Get the NFT command path
113
+ */
114
+ static get nftCmd() {
115
+ return NftCommandExecutor.NFT_CMD;
116
+ }
117
+ /**
118
+ * Update the temp file path
119
+ */
120
+ setTempFilePath(path) {
121
+ this.tempFilePath = path;
122
+ }
123
+ /**
124
+ * Update retry settings
125
+ */
126
+ setRetryOptions(maxRetries, retryDelayMs) {
127
+ this.maxRetries = maxRetries;
128
+ this.retryDelayMs = retryDelayMs;
129
+ }
130
+ }
131
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmZ0LWNvbW1hbmQtZXhlY3V0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9wcm94aWVzL25mdGFibGVzLXByb3h5L3V0aWxzL25mdC1jb21tYW5kLWV4ZWN1dG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNqQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDM0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRXZELE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQVlsQzs7R0FFRztBQUNILE1BQU0sT0FBTyxrQkFBa0I7YUFDTCxZQUFPLEdBQUcsS0FBSyxDQUFDO0lBS3hDLFlBQ1UsR0FBaUIsRUFDekIsVUFBK0IsRUFBRTtRQUR6QixRQUFHLEdBQUgsR0FBRyxDQUFjO1FBR3pCLElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUM7UUFDMUMsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQztRQUNqRCxJQUFJLENBQUMsWUFBWSxHQUFHLE9BQU8sQ0FBQyxZQUFZLElBQUksa0JBQWtCLElBQUksQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDO0lBQ2pGLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFlLEVBQUUsVUFBbUIsRUFBRSxZQUFxQjtRQUNoRixNQUFNLE9BQU8sR0FBRyxVQUFVLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQztRQUM5QyxNQUFN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
@@ -0,0 +1,39 @@
1
+ /**
2
+ * NFTables Port Specification Normalizer
3
+ *
4
+ * Handles normalization and validation of port specifications
5
+ * for nftables rules.
6
+ */
7
+ import type { PortRange } from '../models/index.js';
8
+ /**
9
+ * Normalizes port specifications into an array of port ranges
10
+ */
11
+ export declare function normalizePortSpec(portSpec: number | PortRange | Array<number | PortRange>): PortRange[];
12
+ /**
13
+ * Validates port numbers or ranges
14
+ */
15
+ export declare function validatePorts(port: number | PortRange | Array<number | PortRange>): void;
16
+ /**
17
+ * Format port range for nftables rule
18
+ */
19
+ export declare function formatPortRange(range: PortRange): string;
20
+ /**
21
+ * Convert port spec to nftables expression
22
+ */
23
+ export declare function portSpecToNftExpr(portSpec: number | PortRange | Array<number | PortRange>): string;
24
+ /**
25
+ * Check if two port ranges overlap
26
+ */
27
+ export declare function rangesOverlap(range1: PortRange, range2: PortRange): boolean;
28
+ /**
29
+ * Merge overlapping port ranges
30
+ */
31
+ export declare function mergeOverlappingRanges(ranges: PortRange[]): PortRange[];
32
+ /**
33
+ * Calculate the total number of ports in a port specification
34
+ */
35
+ export declare function countPorts(portSpec: number | PortRange | Array<number | PortRange>): number;
36
+ /**
37
+ * Check if a port is within the given specification
38
+ */
39
+ export declare function isPortInSpec(port: number, portSpec: number | PortRange | Array<number | PortRange>): boolean;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * NFTables Port Specification Normalizer
3
+ *
4
+ * Handles normalization and validation of port specifications
5
+ * for nftables rules.
6
+ */
7
+ import { NftValidationError } from '../models/index.js';
8
+ /**
9
+ * Normalizes port specifications into an array of port ranges
10
+ */
11
+ export function normalizePortSpec(portSpec) {
12
+ const result = [];
13
+ if (Array.isArray(portSpec)) {
14
+ // If it's an array, process each element
15
+ for (const spec of portSpec) {
16
+ result.push(...normalizePortSpec(spec));
17
+ }
18
+ }
19
+ else if (typeof portSpec === 'number') {
20
+ // Single port becomes a range with the same start and end
21
+ result.push({ from: portSpec, to: portSpec });
22
+ }
23
+ else {
24
+ // Already a range
25
+ result.push(portSpec);
26
+ }
27
+ return result;
28
+ }
29
+ /**
30
+ * Validates port numbers or ranges
31
+ */
32
+ export function validatePorts(port) {
33
+ if (Array.isArray(port)) {
34
+ port.forEach(p => validatePorts(p));
35
+ return;
36
+ }
37
+ if (typeof port === 'number') {
38
+ if (port < 1 || port > 65535) {
39
+ throw new NftValidationError(`Invalid port number: ${port}`);
40
+ }
41
+ }
42
+ else if (typeof port === 'object') {
43
+ if (port.from < 1 || port.from > 65535 || port.to < 1 || port.to > 65535 || port.from > port.to) {
44
+ throw new NftValidationError(`Invalid port range: ${port.from}-${port.to}`);
45
+ }
46
+ }
47
+ }
48
+ /**
49
+ * Format port range for nftables rule
50
+ */
51
+ export function formatPortRange(range) {
52
+ if (range.from === range.to) {
53
+ return String(range.from);
54
+ }
55
+ return `${range.from}-${range.to}`;
56
+ }
57
+ /**
58
+ * Convert port spec to nftables expression
59
+ */
60
+ export function portSpecToNftExpr(portSpec) {
61
+ const ranges = normalizePortSpec(portSpec);
62
+ if (ranges.length === 1) {
63
+ return formatPortRange(ranges[0]);
64
+ }
65
+ // Multiple ports/ranges need to use a set
66
+ const ports = ranges.map(formatPortRange);
67
+ return `{ ${ports.join(', ')} }`;
68
+ }
69
+ /**
70
+ * Check if two port ranges overlap
71
+ */
72
+ export function rangesOverlap(range1, range2) {
73
+ return range1.from <= range2.to && range2.from <= range1.to;
74
+ }
75
+ /**
76
+ * Merge overlapping port ranges
77
+ */
78
+ export function mergeOverlappingRanges(ranges) {
79
+ if (ranges.length <= 1)
80
+ return ranges;
81
+ // Sort by start port
82
+ const sorted = [...ranges].sort((a, b) => a.from - b.from);
83
+ const merged = [sorted[0]];
84
+ for (let i = 1; i < sorted.length; i++) {
85
+ const current = sorted[i];
86
+ const lastMerged = merged[merged.length - 1];
87
+ if (current.from <= lastMerged.to + 1) {
88
+ // Ranges overlap or are adjacent, merge them
89
+ lastMerged.to = Math.max(lastMerged.to, current.to);
90
+ }
91
+ else {
92
+ // No overlap, add as new range
93
+ merged.push(current);
94
+ }
95
+ }
96
+ return merged;
97
+ }
98
+ /**
99
+ * Calculate the total number of ports in a port specification
100
+ */
101
+ export function countPorts(portSpec) {
102
+ const ranges = normalizePortSpec(portSpec);
103
+ return ranges.reduce((total, range) => total + (range.to - range.from + 1), 0);
104
+ }
105
+ /**
106
+ * Check if a port is within the given specification
107
+ */
108
+ export function isPortInSpec(port, portSpec) {
109
+ const ranges = normalizePortSpec(portSpec);
110
+ return ranges.some(range => port >= range.from && port <= range.to);
111
+ }
112
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmZ0LXBvcnQtc3BlYy1ub3JtYWxpemVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvcHJveGllcy9uZnRhYmxlcy1wcm94eS91dGlscy9uZnQtcG9ydC1zcGVjLW5vcm1hbGl6ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFHSCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUV4RDs7R0FFRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxRQUF3RDtJQUN4RixNQUFNLE1BQU0sR0FBZ0IsRUFBRSxDQUFDO0lBRS9CLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQzVCLHlDQUF5QztRQUN6QyxLQUFLLE1BQU0sSUFBSSxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQzVCLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQzFDLENBQUM7SUFDSCxDQUFDO1NBQU0sSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUN4QywwREFBMEQ7UUFDMUQsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDaEQsQ0FBQztTQUFNLENBQUM7UUFDTixrQkFBa0I7UUFDbEIsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxJQUFvRDtJQUNoRixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLENB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
@@ -0,0 +1,59 @@
1
+ /**
2
+ * NFTables Rule Validator
3
+ *
4
+ * Handles validation of settings and inputs for nftables operations.
5
+ * Prevents command injection and ensures valid values.
6
+ */
7
+ import type { NfTableProxyOptions } from '../models/index.js';
8
+ /**
9
+ * Validates an IP address (IPv4 or IPv6)
10
+ */
11
+ export declare function isValidIP(ip: string): boolean;
12
+ /**
13
+ * Validates an IPv4 address
14
+ */
15
+ export declare function isValidIPv4(ip: string): boolean;
16
+ /**
17
+ * Validates an IPv6 address
18
+ */
19
+ export declare function isValidIPv6(ip: string): boolean;
20
+ /**
21
+ * Validates a hostname
22
+ */
23
+ export declare function isValidHostname(hostname: string): boolean;
24
+ /**
25
+ * Validates a table name for nftables
26
+ */
27
+ export declare function isValidTableName(tableName: string): boolean;
28
+ /**
29
+ * Validates a rate specification (e.g., "10mbps")
30
+ */
31
+ export declare function isValidRate(rate: string): boolean;
32
+ /**
33
+ * Validates an array of IP addresses
34
+ */
35
+ export declare function validateIPs(ips?: string[]): void;
36
+ /**
37
+ * Validates a host (can be hostname or IP)
38
+ */
39
+ export declare function validateHost(host?: string): void;
40
+ /**
41
+ * Validates a table name
42
+ */
43
+ export declare function validateTableName(tableName?: string): void;
44
+ /**
45
+ * Validates QoS settings
46
+ */
47
+ export declare function validateQosSettings(qos?: NfTableProxyOptions['qos']): void;
48
+ /**
49
+ * Validates all NfTablesProxy settings
50
+ */
51
+ export declare function validateSettings(settings: NfTableProxyOptions): void;
52
+ /**
53
+ * Check if an IP matches the given family (ip or ip6)
54
+ */
55
+ export declare function isIPForFamily(ip: string, family: 'ip' | 'ip6'): boolean;
56
+ /**
57
+ * Filter IPs by family
58
+ */
59
+ export declare function filterIPsByFamily(ips: string[], family: 'ip' | 'ip6'): string[];
@@ -0,0 +1,130 @@
1
+ /**
2
+ * NFTables Rule Validator
3
+ *
4
+ * Handles validation of settings and inputs for nftables operations.
5
+ * Prevents command injection and ensures valid values.
6
+ */
7
+ import { NftValidationError } from '../models/index.js';
8
+ import { validatePorts } from './nft-port-spec-normalizer.js';
9
+ // IP address validation patterns
10
+ const IPV4_REGEX = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$/;
11
+ const IPV6_REGEX = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$/;
12
+ const HOSTNAME_REGEX = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
13
+ const TABLE_NAME_REGEX = /^[a-zA-Z0-9_]+$/;
14
+ const RATE_REGEX = /^[0-9]+[kKmMgG]?bps$/;
15
+ /**
16
+ * Validates an IP address (IPv4 or IPv6)
17
+ */
18
+ export function isValidIP(ip) {
19
+ return IPV4_REGEX.test(ip) || IPV6_REGEX.test(ip);
20
+ }
21
+ /**
22
+ * Validates an IPv4 address
23
+ */
24
+ export function isValidIPv4(ip) {
25
+ return IPV4_REGEX.test(ip);
26
+ }
27
+ /**
28
+ * Validates an IPv6 address
29
+ */
30
+ export function isValidIPv6(ip) {
31
+ return IPV6_REGEX.test(ip);
32
+ }
33
+ /**
34
+ * Validates a hostname
35
+ */
36
+ export function isValidHostname(hostname) {
37
+ return HOSTNAME_REGEX.test(hostname);
38
+ }
39
+ /**
40
+ * Validates a table name for nftables
41
+ */
42
+ export function isValidTableName(tableName) {
43
+ return TABLE_NAME_REGEX.test(tableName);
44
+ }
45
+ /**
46
+ * Validates a rate specification (e.g., "10mbps")
47
+ */
48
+ export function isValidRate(rate) {
49
+ return RATE_REGEX.test(rate);
50
+ }
51
+ /**
52
+ * Validates an array of IP addresses
53
+ */
54
+ export function validateIPs(ips) {
55
+ if (!ips)
56
+ return;
57
+ for (const ip of ips) {
58
+ if (!isValidIP(ip)) {
59
+ throw new NftValidationError(`Invalid IP address format: ${ip}`);
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * Validates a host (can be hostname or IP)
65
+ */
66
+ export function validateHost(host) {
67
+ if (!host)
68
+ return;
69
+ if (!isValidHostname(host) && !isValidIP(host)) {
70
+ throw new NftValidationError(`Invalid host format: ${host}`);
71
+ }
72
+ }
73
+ /**
74
+ * Validates a table name
75
+ */
76
+ export function validateTableName(tableName) {
77
+ if (!tableName)
78
+ return;
79
+ if (!isValidTableName(tableName)) {
80
+ throw new NftValidationError(`Invalid table name: ${tableName}. Only alphanumeric characters and underscores are allowed.`);
81
+ }
82
+ }
83
+ /**
84
+ * Validates QoS settings
85
+ */
86
+ export function validateQosSettings(qos) {
87
+ if (!qos?.enabled)
88
+ return;
89
+ if (qos.maxRate && !isValidRate(qos.maxRate)) {
90
+ throw new NftValidationError(`Invalid rate format: ${qos.maxRate}. Use format like "10mbps", "1gbps", etc.`);
91
+ }
92
+ if (qos.priority !== undefined) {
93
+ if (qos.priority < 1 || qos.priority > 10 || !Number.isInteger(qos.priority)) {
94
+ throw new NftValidationError(`Invalid priority: ${qos.priority}. Must be an integer between 1 and 10.`);
95
+ }
96
+ }
97
+ }
98
+ /**
99
+ * Validates all NfTablesProxy settings
100
+ */
101
+ export function validateSettings(settings) {
102
+ // Validate port numbers
103
+ validatePorts(settings.fromPort);
104
+ validatePorts(settings.toPort);
105
+ // Validate IP addresses
106
+ validateIPs(settings.ipAllowList);
107
+ validateIPs(settings.ipBlockList);
108
+ // Validate target host
109
+ validateHost(settings.toHost);
110
+ // Validate table name
111
+ validateTableName(settings.tableName);
112
+ // Validate QoS settings
113
+ validateQosSettings(settings.qos);
114
+ }
115
+ /**
116
+ * Check if an IP matches the given family (ip or ip6)
117
+ */
118
+ export function isIPForFamily(ip, family) {
119
+ if (family === 'ip6') {
120
+ return ip.includes(':');
121
+ }
122
+ return ip.includes('.');
123
+ }
124
+ /**
125
+ * Filter IPs by family
126
+ */
127
+ export function filterIPsByFamily(ips, family) {
128
+ return ips.filter(ip => isIPForFamily(ip, family));
129
+ }
130
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmZ0LXJ1bGUtdmFsaWRhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvcHJveGllcy9uZnRhYmxlcy1wcm94eS91dGlscy9uZnQtcnVsZS12YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFHSCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFOUQsaUNBQWlDO0FBQ2pDLE1BQU0sVUFBVSxHQUFHLHlJQUF5SSxDQUFDO0FBQzdKLE1BQU0sVUFBVSxHQUFHLGtzQkFBa3NCLENBQUM7QUFDdHRCLE1BQU0sY0FBYyxHQUFHLDZHQUE2RyxDQUFDO0FBQ3JJLE1BQU0sZ0JBQWdCLEdBQUcsaUJBQWlCLENBQUM7QUFDM0MsTUFBTSxVQUFVLEdBQUcsc0JBQXNCLENBQUM7QUFFMUM7O0dBRUc7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLEVBQVU7SUFDbEMsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDcEQsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FBQyxFQUFVO0lBQ3BDLE9BQU8sVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUM3QixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUFDLEVBQVU7SUFDcEMsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzdCLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsUUFBZ0I7SUFDOUMsT0FBTyxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3ZDLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFB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