x3ui-api 1.0.3 → 1.0.5

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.
@@ -0,0 +1,118 @@
1
+ import WireguardClientBuilder from './WireguardClientBuilder';
2
+ import {ClientSettings} from "../../index";
3
+
4
+ /**
5
+ * WireguardBuilder class for creating and managing Wireguard server configurations.
6
+ * This builder provides a fluent interface for setting up Wireguard servers and managing clients.
7
+ */
8
+ export default class WireguardBuilder {
9
+ /**
10
+ * Creates a new WireguardBuilder instance.
11
+ * @param client - The client connection or context to use for building the configuration
12
+ * @param options - Optional configuration parameters for the Wireguard server
13
+ */
14
+ constructor(client: any, options?: any);
15
+
16
+ /**
17
+ * Sets the port for the Wireguard server.
18
+ * @param port - The port number to listen on
19
+ * @returns The current builder instance for method chaining
20
+ */
21
+ setPort(port: number): this;
22
+
23
+ /**
24
+ * Sets a descriptive remark for the Wireguard server.
25
+ * @param remark - The remark or name for this server
26
+ * @returns The current builder instance for method chaining
27
+ */
28
+ setRemark(remark: string): this;
29
+
30
+ /**
31
+ * Sets the Maximum Transmission Unit (MTU) size.
32
+ * @param mtu - The MTU value in bytes
33
+ * @returns The current builder instance for method chaining
34
+ */
35
+ setMtu(mtu: number): this;
36
+
37
+ /**
38
+ * Sets the server's private key.
39
+ * @param secretKey - The Wireguard private key in base64 format
40
+ * @returns The current builder instance for method chaining
41
+ */
42
+ setSecretKey(secretKey: string): this;
43
+
44
+ /**
45
+ * Configures whether to use kernel TUN interface or userspace implementation.
46
+ * @param noKernelTun - If true, uses userspace implementation instead of kernel TUN
47
+ * @returns The current builder instance for method chaining
48
+ */
49
+ setNoKernelTun(noKernelTun: boolean): this;
50
+
51
+ /**
52
+ * Configures traffic sniffing options.
53
+ * @param enabled - Whether sniffing is enabled
54
+ * @param destOverride - Array of protocols to override destination with sniffed value
55
+ * @param metadataOnly - If true, only sniffs metadata
56
+ * @param routeOnly - If true, only uses sniffed information for routing
57
+ * @returns The current builder instance for method chaining
58
+ */
59
+ setSniffing(enabled: boolean, destOverride?: string[], metadataOnly?: boolean, routeOnly?: boolean): this;
60
+
61
+ /**
62
+ * Sets the IP address the server listens on.
63
+ * @param ip - The IP address to bind to
64
+ * @returns The current builder instance for method chaining
65
+ */
66
+ setListenIP(ip: string): this;
67
+
68
+ /**
69
+ * Sets the expiration time for the server configuration.
70
+ * @param timestamp - Unix timestamp when the configuration expires
71
+ * @returns The current builder instance for method chaining
72
+ */
73
+ setExpiryTime(timestamp: number): this;
74
+
75
+ /**
76
+ * Creates and adds a new client to this Wireguard server.
77
+ * @param options - Optional client settings
78
+ * @returns A new WireguardClientBuilder instance for configuring the client
79
+ */
80
+ addClient(options?: Partial<ClientSettings>): WireguardClientBuilder;
81
+
82
+ /**
83
+ * Generates a connection link for a client.
84
+ * @param clientIndex - Index of the client (default: 0)
85
+ * @param host - Host address to use in the link (defaults to server address)
86
+ * @param port - Port to use in the link (defaults to server port)
87
+ * @returns A formatted connection link string
88
+ */
89
+ getClientLink(clientIndex?: number, host?: string, port?: number): string;
90
+
91
+ /**
92
+ * Generates a configuration file for a client.
93
+ * @param clientIndex - Index of the client (default: 0)
94
+ * @param host - Host address to use in the config (defaults to server address)
95
+ * @param port - Port to use in the config (defaults to server port)
96
+ * @returns A formatted configuration file content as string
97
+ */
98
+ getClientConfig(clientIndex?: number, host?: string, port?: number): string;
99
+
100
+ /**
101
+ * Generates a random port number for the Wireguard server.
102
+ * @returns A random port number
103
+ */
104
+ generateRandomPort(): number;
105
+
106
+ /**
107
+ * Derives the public key from a given private key.
108
+ * @param secretKey - The Wireguard private key in base64 format
109
+ * @returns The corresponding public key in base64 format
110
+ */
111
+ derivePublicKey(secretKey: string): string;
112
+
113
+ /**
114
+ * Builds and finalizes the Wireguard server configuration.
115
+ * @returns A Promise that resolves to the built configuration
116
+ */
117
+ build(): Promise<any>;
118
+ }
@@ -0,0 +1,204 @@
1
+ const keyUtils = require('./keyUtils');
2
+ const WireguardClientBuilder = require('./WireguardClientBuilder');
3
+
4
+ module.exports = class WireguardBuilder {
5
+ constructor(client, options = {}) {
6
+ this.client = client;
7
+ // Initialize from InboundConfig
8
+ this.id = options.id || undefined;
9
+ this.port = options.port || 0;
10
+ this.remark = options.remark || '';
11
+ this.listenIP = options.listen || '';
12
+ this.expiryTime = options.expiryTime || 0;
13
+ this.enable = true;
14
+ this.up = options.up || 0;
15
+ this.down = options.down || 0;
16
+ this.total = options.total || 0;
17
+
18
+ // Initialize WireGuard specific settings
19
+ const settings = typeof options.settings === 'string'
20
+ ? JSON.parse(options.settings)
21
+ : options.settings || {};
22
+
23
+ this.mtu = settings.mtu || 1420;
24
+ this.secretKey = settings.secretKey || '';
25
+ this.publicKey = ''; // Will be derived from secretKey
26
+ this.noKernelTun = settings.noKernelTun || false;
27
+
28
+ // Initialize sniffing
29
+ this.sniffing = options.sniffing || {
30
+ enabled: false,
31
+ destOverride: ['http', 'tls', 'quic', 'fakedns'],
32
+ metadataOnly: false,
33
+ routeOnly: false
34
+ };
35
+
36
+ // Initialize allocate
37
+ this.allocate = options.allocate || {
38
+ strategy: 'always',
39
+ refresh: 5,
40
+ concurrency: 3
41
+ };
42
+
43
+ // Initialize clients
44
+ this.clients = [];
45
+
46
+ if (settings?.peers) {
47
+ settings.peers.forEach(peer => {
48
+ this.addClient(peer);
49
+ });
50
+ }
51
+
52
+ // If secretKey is provided, derive publicKey
53
+ if (this.secretKey) {
54
+ this.publicKey = keyUtils.derivePublicKey(this.secretKey);
55
+ }
56
+
57
+ // If no secretKey provided, generate one
58
+ if (!this.secretKey) {
59
+ let pair = keyUtils.generateKeyPair();
60
+ this.secretKey = pair.privateKey;
61
+ this.publicKey = pair.publicKey;
62
+ }
63
+ }
64
+
65
+ setPort(port) {
66
+ this.port = port;
67
+ return this;
68
+ }
69
+
70
+ setRemark(remark) {
71
+ this.remark = remark;
72
+ return this;
73
+ }
74
+
75
+ setMtu(mtu) {
76
+ this.mtu = mtu;
77
+ return this;
78
+ }
79
+
80
+ setSecretKey(secretKey) {
81
+ this.secretKey = secretKey;
82
+ this.publicKey = keyUtils.derivePublicKey(secretKey);
83
+ return this;
84
+ }
85
+
86
+ setNoKernelTun(noKernelTun) {
87
+ this.noKernelTun = noKernelTun;
88
+ return this;
89
+ }
90
+
91
+ setSniffing(enabled, destOverride = ['http', 'tls', 'quic', 'fakedns'], metadataOnly = false, routeOnly = false) {
92
+ this.sniffing = {
93
+ enabled,
94
+ destOverride,
95
+ metadataOnly,
96
+ routeOnly
97
+ };
98
+ return this;
99
+ }
100
+
101
+ setListenIP(ip) {
102
+ this.listenIP = ip;
103
+ return this;
104
+ }
105
+
106
+ setExpiryTime(timestamp) {
107
+ this.expiryTime = timestamp;
108
+ return this;
109
+ }
110
+
111
+ addClient(options = {}) {
112
+ const builder = new WireguardClientBuilder(this);
113
+ if (options.privateKey) builder.setPrivateKey(options.privateKey);
114
+ if (options.publicKey) builder.setPublicKey(options.publicKey);
115
+ if (options.preSharedKey) builder.setPreSharedKey(options.preSharedKey);
116
+ if (options.allowedIPs) builder.setAllowedIPs(options.allowedIPs);
117
+ if (options.keepAlive !== undefined) builder.setKeepAlive(options.keepAlive);
118
+ if (options.email) builder.setEmail(options.email);
119
+ if (options.totalGB) builder.setTotalGB(options.totalGB);
120
+ if (options.expiryTime) builder.setExpiryTime(options.expiryTime);
121
+ if (options.tgId) builder.setTgId(options.tgId);
122
+
123
+ this.clients.push(builder);
124
+ return builder;
125
+ }
126
+
127
+ getClientLink(clientIndex = 0, host, port) {
128
+ if (clientIndex < 0 || clientIndex >= this.clients.length) {
129
+ throw new Error('Invalid client index');
130
+ }
131
+ const client = this.clients[clientIndex];
132
+ return client.getLink(host || this.listenIP || 'localhost', port || this.port);
133
+ }
134
+
135
+ getClientConfig(clientIndex = 0, host, port) {
136
+ if (clientIndex < 0 || clientIndex >= this.clients.length) {
137
+ throw new Error('Invalid client index');
138
+ }
139
+ const client = this.clients[clientIndex];
140
+ return client.getConfigFile(host || this.listenIP || 'localhost', port || this.port);
141
+ }
142
+
143
+ generateRandomPort() {
144
+ return Math.floor(Math.random() * (65535 - 1024) + 1024);
145
+ }
146
+
147
+ async build() {
148
+ if (!this.remark) {
149
+ throw new Error('Remark is required');
150
+ }
151
+
152
+ // If no port specified, find unused one
153
+ if (!this.port) {
154
+ const inbounds = await this.client.getInbounds();
155
+ const usedPorts = new Set(inbounds.map(i => i.port));
156
+ let port;
157
+ do {
158
+ port = this.generateRandomPort();
159
+ } while (usedPorts.has(port));
160
+ this.port = port;
161
+ }
162
+
163
+ // If no secretKey provided, generate one
164
+ if (!this.secretKey) {
165
+ this.secretKey = keyUtils.generatePrivateKey();
166
+ this.publicKey = keyUtils.derivePublicKey(this.secretKey);
167
+ }
168
+
169
+ // If no clients added, create one default client
170
+ if (this.clients.length === 0) {
171
+ this.addClient();
172
+ }
173
+
174
+ // Build all clients
175
+ const clientConfigs = await Promise.all(this.clients.map(builder => builder.build()));
176
+
177
+ // Create tag for inbound
178
+ const tag = `inbound-${this.port}`;
179
+
180
+ // Build the complete inbound configuration
181
+ return {
182
+ id: this.id,
183
+ up: this.up,
184
+ down: this.down,
185
+ total: this.total,
186
+ remark: this.remark,
187
+ enable: this.enable,
188
+ expiryTime: this.expiryTime,
189
+ listen: this.listenIP,
190
+ port: this.port,
191
+ protocol: 'wireguard',
192
+ settings: {
193
+ mtu: this.mtu,
194
+ secretKey: this.secretKey,
195
+ peers: clientConfigs,
196
+ noKernelTun: this.noKernelTun
197
+ },
198
+ streamSettings: {},
199
+ tag,
200
+ sniffing: this.sniffing,
201
+ allocate: this.allocate
202
+ };
203
+ }
204
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Type definitions for WireguardClientBuilder
3
+ * Provides functionality for building WireGuard client configurations
4
+ */
5
+ import ClientBuilder from '../../core/ClientBuilder';
6
+
7
+ /**
8
+ * WireguardClientBuilder class for creating and managing WireGuard client configurations
9
+ * Extends the base ClientBuilder to provide WireGuard-specific functionality
10
+ */
11
+ export default class WireguardClientBuilder extends ClientBuilder {
12
+ /**
13
+ * Creates a new WireguardClientBuilder instance
14
+ * @param parent - The parent object that owns this builder
15
+ * @param options - Optional client settings
16
+ */
17
+ constructor(parent: any, options?: any);
18
+
19
+ /**
20
+ * Sets the client's private key
21
+ * @param privateKey - The WireGuard private key in base64 format
22
+ * @returns The builder instance for method chaining
23
+ */
24
+ setPrivateKey(privateKey: string): this;
25
+
26
+ /**
27
+ * Sets the server's public key
28
+ * @param publicKey - The WireGuard public key in base64 format
29
+ * @returns The builder instance for method chaining
30
+ */
31
+ setPublicKey(publicKey: string): this;
32
+
33
+ /**
34
+ * Sets the pre-shared key for additional security
35
+ * @param preSharedKey - The pre-shared key in base64 format
36
+ * @returns The builder instance for method chaining
37
+ */
38
+ setPreSharedKey(preSharedKey: string): this;
39
+
40
+ /**
41
+ * Sets the allowed IP addresses/ranges for routing through the tunnel
42
+ * @param allowedIPs - Array of IP addresses/ranges in CIDR notation
43
+ * @returns The builder instance for method chaining
44
+ */
45
+ setAllowedIPs(allowedIPs: string[]): this;
46
+
47
+ /**
48
+ * Sets the persistent keepalive interval
49
+ * @param keepAlive - Interval in seconds between keepalive packets
50
+ * @returns The builder instance for method chaining
51
+ */
52
+ setKeepAlive(keepAlive: number): this;
53
+
54
+ /**
55
+ * Generates a random pre-shared key
56
+ * @returns The builder instance for method chaining
57
+ */
58
+ generatePresharedKey(): this;
59
+
60
+ /**
61
+ * Generates a new public/private key pair
62
+ * @returns The builder instance for method chaining
63
+ */
64
+ generateKeyPair(): this;
65
+
66
+ /**
67
+ * Builds and returns the complete WireGuard client configuration
68
+ * @returns The WireGuard client configuration object
69
+ */
70
+ build(): any;
71
+
72
+ /**
73
+ * Generates a WireGuard connection URI/link for easy client configuration
74
+ * @param host - The server hostname or IP address
75
+ * @param port - The server port number
76
+ * @returns A WireGuard connection URI string
77
+ */
78
+ getLink(host: string, port: number): string;
79
+ }
@@ -0,0 +1,88 @@
1
+ const crypto = require("crypto");
2
+ const keyUtils = require('./keyUtils');
3
+ const ClientBuilder = require('./../../core/ClientBuilder');
4
+
5
+ module.exports = class WireguardClientBuilder extends ClientBuilder {
6
+ constructor(parent, options) {
7
+ super(parent);
8
+ this.privateKey = options.privateKey || '';
9
+ this.publicKey = options.publicKey || '';
10
+ this.preSharedKey = options.preSharedKey || '';
11
+ this.allowedIPs = options.allowedIPs || ['10.0.0.2/32'];
12
+ this.keepAlive = options.keepAlive || 0;
13
+ }
14
+
15
+ setPrivateKey(privateKey) {
16
+ this.privateKey = privateKey;
17
+ return this;
18
+ }
19
+
20
+ setPublicKey(publicKey) {
21
+ this.publicKey = publicKey;
22
+ return this;
23
+ }
24
+
25
+ setPreSharedKey(preSharedKey) {
26
+ this.preSharedKey = preSharedKey;
27
+ return this;
28
+ }
29
+
30
+ setAllowedIPs(allowedIPs) {
31
+ this.allowedIPs = allowedIPs;
32
+ return this;
33
+ }
34
+
35
+ setKeepAlive(keepAlive) {
36
+ this.keepAlive = keepAlive;
37
+ return this;
38
+ }
39
+
40
+ generatePresharedKey() {
41
+ this.preSharedKey = keyUtils.generatePresharedKey();
42
+ return this;
43
+ }
44
+
45
+ generateKeyPair() {
46
+ const keyPair = keyUtils.generateKeyPair();
47
+ this.privateKey = keyPair.privateKey;
48
+ this.publicKey = keyPair.publicKey;
49
+ return this;
50
+ }
51
+
52
+ build() {
53
+ const baseConfig = super.build();
54
+ return {
55
+ ...baseConfig,
56
+ privateKey: this.privateKey || '',
57
+ publicKey: this.publicKey || '',
58
+ preSharedKey: this.preSharedKey || '',
59
+ allowedIPs: this.allowedIPs,
60
+ keepAlive: this.keepAlive
61
+ };
62
+ }
63
+
64
+ getLink(host, port) {
65
+ // Generate WireGuard client configuration
66
+ const serverPublicKey = this.parent.secretKey ?
67
+ this.parent.publicKey :
68
+ 'MISSING_SERVER_PUBLIC_KEY';
69
+
70
+ const config = [
71
+ '[Interface]',
72
+ `PrivateKey = ${this.privateKey}`,
73
+ `Address = ${this.allowedIPs[0]}`,
74
+ 'DNS = 1.1.1.1, 1.0.0.1',
75
+ `MTU = ${this.parent.mtu || 1420}`,
76
+ '',
77
+ `# ${this.parent.remark || 'WireGuard'}-${this.email || 'default'}`,
78
+ '[Peer]',
79
+ `PublicKey = ${serverPublicKey}`,
80
+ 'AllowedIPs = 0.0.0.0/0, ::/0',
81
+ `Endpoint = ${host}:${port}`,
82
+ this.preSharedKey ? `PresharedKey = ${this.preSharedKey}` : '',
83
+ ].filter(Boolean).join('\n');
84
+
85
+ // Return the configuration as a data URI
86
+ return config;
87
+ }
88
+ }
@@ -0,0 +1,9 @@
1
+ import WireguardBuilder from "./WireguardBuilder";
2
+ import WireguardClientBuilder from "./WireguardClientBuilder";
3
+
4
+ declare const _default: {
5
+ WireguardBuilder: typeof WireguardBuilder;
6
+ WireguardClientBuilder: typeof WireguardClientBuilder;
7
+ };
8
+
9
+ export default _default;
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ WireguardBuilder: require('./WireguardBuilder'),
3
+ WireguardClientBuilder: require('./WireguardClientBuilder')
4
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * WireGuard key utilities
3
+ * Pure JavaScript implementation of Curve25519 for WireGuard key generation
4
+ */
5
+
6
+ const crypto = require('crypto');
7
+
8
+ /**
9
+ * Generate a new WireGuard private key
10
+ * @returns {string} Base64-encoded private key
11
+ */
12
+ function generatePrivateKey() {
13
+ const key = crypto.randomBytes(32);
14
+ return key.toString('base64');
15
+ }
16
+
17
+ /**
18
+ * Generate a new WireGuard pre-shared key
19
+ * @returns {string} Base64-encoded pre-shared key
20
+ */
21
+ function generatePresharedKey() {
22
+ const key = crypto.randomBytes(32);
23
+ return key.toString('base64');
24
+ }
25
+
26
+ /**
27
+ * Derive a public key from a private key using Curve25519
28
+ * @param {string} privateKeyBase64 Base64-encoded private key
29
+ * @returns {string} Base64-encoded public key
30
+ */
31
+ function derivePublicKey(privateKeyBase64) {
32
+ const privateKey = Buffer.from(privateKeyBase64, 'base64');
33
+ const publicKey = crypto.createPublicKey({
34
+ key: crypto.createPrivateKey({
35
+ key: Buffer.concat([
36
+ Buffer.from('302e020100300506032b656e04220420', 'hex'),
37
+ privateKey
38
+ ]),
39
+ format: 'der',
40
+ type: 'pkcs8'
41
+ }),
42
+ format: 'der',
43
+ type: 'spki'
44
+ }).export({ format: 'der', type: 'spki' });
45
+
46
+ // Extract the raw public key bytes
47
+ return publicKey.slice(-32).toString('base64');
48
+ }
49
+
50
+ /**
51
+ * Generate a new WireGuard key pair
52
+ * @returns {Object} Object containing privateKey and publicKey in base64 format
53
+ */
54
+ function generateKeyPair() {
55
+ const privateKey = generatePrivateKey();
56
+ const publicKey = derivePublicKey(privateKey);
57
+ return { privateKey, publicKey };
58
+ }
59
+
60
+ /**
61
+ * Validate a WireGuard private key
62
+ * @param {string} privateKeyBase64 Base64-encoded private key
63
+ * @returns {boolean} True if valid, false otherwise
64
+ */
65
+ function isValidPrivateKey(privateKeyBase64) {
66
+ try {
67
+ const buf = Buffer.from(privateKeyBase64, 'base64');
68
+ return buf.length === 32;
69
+ } catch {
70
+ return false;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Validate a WireGuard public key
76
+ * @param {string} publicKeyBase64 Base64-encoded public key
77
+ * @returns {boolean} True if valid, false otherwise
78
+ */
79
+ function isValidPublicKey(publicKeyBase64) {
80
+ try {
81
+ const buf = Buffer.from(publicKeyBase64, 'base64');
82
+ return buf.length === 32;
83
+ } catch {
84
+ return false;
85
+ }
86
+ }
87
+
88
+ module.exports = {
89
+ generatePrivateKey,
90
+ generatePresharedKey,
91
+ derivePublicKey,
92
+ generateKeyPair,
93
+ isValidPrivateKey,
94
+ isValidPublicKey
95
+ };