@omindu/yaksha 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/bin/yaksha.js +329 -0
- package/package.json +28 -0
- package/src/bypass/firewall-evasion.js +354 -0
- package/src/client/index.js +544 -0
- package/src/core/connection.js +393 -0
- package/src/core/encryption.js +299 -0
- package/src/core/protocol.js +268 -0
- package/src/features/dns-override.js +403 -0
- package/src/features/multi-path.js +394 -0
- package/src/features/sni-spoof.js +355 -0
- package/src/features/tls-camouflage.js +369 -0
- package/src/features/traffic-obfuscation.js +338 -0
- package/src/index.js +106 -0
- package/src/security/auth.js +441 -0
- package/src/security/levels.js +316 -0
- package/src/server/index.js +551 -0
- package/src/utils/buffer-pool.js +150 -0
- package/src/utils/config.js +205 -0
- package/src/utils/logger.js +105 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Yaksha Traffic Obfuscation
|
|
5
|
+
* Make VPN traffic undetectable through pattern randomization
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
|
|
10
|
+
class TrafficObfuscation {
|
|
11
|
+
constructor(securityLevel = 'medium', options = {}) {
|
|
12
|
+
this.securityLevel = securityLevel;
|
|
13
|
+
this.mode = this._selectMode(securityLevel);
|
|
14
|
+
this.enabled = options.enabled !== false;
|
|
15
|
+
this.maxJitter = options.maxJitter || 50; // milliseconds
|
|
16
|
+
this.maxPadding = options.maxPadding || 255; // bytes
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Select obfuscation mode based on security level
|
|
21
|
+
*/
|
|
22
|
+
_selectMode(level) {
|
|
23
|
+
switch (level) {
|
|
24
|
+
case 'low':
|
|
25
|
+
return 'xor';
|
|
26
|
+
case 'medium':
|
|
27
|
+
return 'chacha20';
|
|
28
|
+
case 'high':
|
|
29
|
+
return 'aes-256-gcm';
|
|
30
|
+
default:
|
|
31
|
+
return 'chacha20';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Simple XOR obfuscation (low security, high speed)
|
|
37
|
+
*/
|
|
38
|
+
_xorObfuscate(data, key) {
|
|
39
|
+
const result = Buffer.allocUnsafe(data.length);
|
|
40
|
+
|
|
41
|
+
for (let i = 0; i < data.length; i++) {
|
|
42
|
+
result[i] = data[i] ^ key[i % key.length];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* ChaCha20 stream cipher obfuscation
|
|
50
|
+
*/
|
|
51
|
+
_chacha20Obfuscate(data, key, nonce) {
|
|
52
|
+
const cipher = crypto.createCipheriv('chacha20', key, nonce);
|
|
53
|
+
return Buffer.concat([cipher.update(data), cipher.final()]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* ChaCha20 stream cipher deobfuscation
|
|
58
|
+
*/
|
|
59
|
+
_chacha20Deobfuscate(data, key, nonce) {
|
|
60
|
+
const decipher = crypto.createDecipheriv('chacha20', key, nonce);
|
|
61
|
+
return Buffer.concat([decipher.update(data), decipher.final()]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* AES-256-GCM obfuscation
|
|
66
|
+
*/
|
|
67
|
+
_aesObfuscate(data, key, nonce) {
|
|
68
|
+
const cipher = crypto.createCipheriv('aes-256-gcm', key, nonce);
|
|
69
|
+
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
70
|
+
const authTag = cipher.getAuthTag();
|
|
71
|
+
|
|
72
|
+
return { data: encrypted, authTag };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* AES-256-GCM deobfuscation
|
|
77
|
+
*/
|
|
78
|
+
_aesDeobfuscate(data, key, nonce, authTag) {
|
|
79
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', key, nonce);
|
|
80
|
+
decipher.setAuthTag(authTag);
|
|
81
|
+
return Buffer.concat([decipher.update(data), decipher.final()]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Add random padding to data
|
|
86
|
+
*/
|
|
87
|
+
addRandomPadding(data) {
|
|
88
|
+
const paddingSize = crypto.randomInt(0, this.maxPadding + 1);
|
|
89
|
+
|
|
90
|
+
if (paddingSize === 0) {
|
|
91
|
+
return { data, paddingSize: 0 };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const padding = crypto.randomBytes(paddingSize);
|
|
95
|
+
const padded = Buffer.concat([data, padding]);
|
|
96
|
+
|
|
97
|
+
return { data: padded, paddingSize };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Remove padding from data
|
|
102
|
+
*/
|
|
103
|
+
removePadding(data, paddingSize) {
|
|
104
|
+
if (paddingSize === 0 || paddingSize >= data.length) {
|
|
105
|
+
return data;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return data.slice(0, -paddingSize);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Add timing jitter (async delay)
|
|
113
|
+
*/
|
|
114
|
+
async addTimingJitter() {
|
|
115
|
+
if (!this.enabled) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const jitter = crypto.randomInt(0, this.maxJitter + 1);
|
|
120
|
+
|
|
121
|
+
if (jitter > 0) {
|
|
122
|
+
await new Promise(resolve => setTimeout(resolve, jitter));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Randomize packet size by splitting or combining
|
|
128
|
+
*/
|
|
129
|
+
randomizePacketSize(data, targetSize = null) {
|
|
130
|
+
if (!targetSize) {
|
|
131
|
+
// Random target size between 500 and 1500 bytes
|
|
132
|
+
targetSize = crypto.randomInt(500, 1501);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (data.length <= targetSize) {
|
|
136
|
+
// Add padding to reach target size
|
|
137
|
+
const paddingSize = targetSize - data.length;
|
|
138
|
+
if (paddingSize > 0) {
|
|
139
|
+
const padding = crypto.randomBytes(paddingSize);
|
|
140
|
+
return {
|
|
141
|
+
packets: [Buffer.concat([data, padding])],
|
|
142
|
+
paddingSizes: [paddingSize]
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return { packets: [data], paddingSizes: [0] };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Split into multiple packets
|
|
149
|
+
const packets = [];
|
|
150
|
+
const paddingSizes = [];
|
|
151
|
+
let offset = 0;
|
|
152
|
+
|
|
153
|
+
while (offset < data.length) {
|
|
154
|
+
const chunkSize = Math.min(
|
|
155
|
+
crypto.randomInt(Math.floor(targetSize * 0.7), targetSize + 1),
|
|
156
|
+
data.length - offset
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const chunk = data.slice(offset, offset + chunkSize);
|
|
160
|
+
|
|
161
|
+
// Add random padding to each chunk
|
|
162
|
+
const paddingSize = crypto.randomInt(0, 100);
|
|
163
|
+
const padding = crypto.randomBytes(paddingSize);
|
|
164
|
+
const paddedChunk = Buffer.concat([chunk, padding]);
|
|
165
|
+
|
|
166
|
+
packets.push(paddedChunk);
|
|
167
|
+
paddingSizes.push(paddingSize);
|
|
168
|
+
offset += chunkSize;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return { packets, paddingSizes };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Obfuscate data
|
|
176
|
+
*/
|
|
177
|
+
obfuscate(data) {
|
|
178
|
+
if (!this.enabled) {
|
|
179
|
+
return {
|
|
180
|
+
data,
|
|
181
|
+
metadata: { mode: 'none' }
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
let result;
|
|
186
|
+
let metadata = { mode: this.mode };
|
|
187
|
+
|
|
188
|
+
switch (this.mode) {
|
|
189
|
+
case 'xor': {
|
|
190
|
+
const key = crypto.randomBytes(32);
|
|
191
|
+
result = this._xorObfuscate(data, key);
|
|
192
|
+
metadata.key = key;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
case 'chacha20': {
|
|
197
|
+
const key = crypto.randomBytes(32);
|
|
198
|
+
const nonce = crypto.randomBytes(12);
|
|
199
|
+
result = this._chacha20Obfuscate(data, key, nonce);
|
|
200
|
+
metadata.key = key;
|
|
201
|
+
metadata.nonce = nonce;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
case 'aes-256-gcm': {
|
|
206
|
+
const key = crypto.randomBytes(32);
|
|
207
|
+
const nonce = crypto.randomBytes(12);
|
|
208
|
+
const { data: encrypted, authTag } = this._aesObfuscate(data, key, nonce);
|
|
209
|
+
result = encrypted;
|
|
210
|
+
metadata.key = key;
|
|
211
|
+
metadata.nonce = nonce;
|
|
212
|
+
metadata.authTag = authTag;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
default:
|
|
217
|
+
result = data;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Add random padding
|
|
221
|
+
const { data: padded, paddingSize } = this.addRandomPadding(result);
|
|
222
|
+
metadata.paddingSize = paddingSize;
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
data: padded,
|
|
226
|
+
metadata
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Deobfuscate data
|
|
232
|
+
*/
|
|
233
|
+
deobfuscate(data, metadata) {
|
|
234
|
+
if (!this.enabled || metadata.mode === 'none') {
|
|
235
|
+
return data;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Remove padding first
|
|
239
|
+
let unpadded = this.removePadding(data, metadata.paddingSize || 0);
|
|
240
|
+
|
|
241
|
+
let result;
|
|
242
|
+
|
|
243
|
+
switch (metadata.mode) {
|
|
244
|
+
case 'xor':
|
|
245
|
+
result = this._xorObfuscate(unpadded, metadata.key); // XOR is symmetric
|
|
246
|
+
break;
|
|
247
|
+
|
|
248
|
+
case 'chacha20':
|
|
249
|
+
result = this._chacha20Deobfuscate(unpadded, metadata.key, metadata.nonce);
|
|
250
|
+
break;
|
|
251
|
+
|
|
252
|
+
case 'aes-256-gcm':
|
|
253
|
+
result = this._aesDeobfuscate(unpadded, metadata.key, metadata.nonce, metadata.authTag);
|
|
254
|
+
break;
|
|
255
|
+
|
|
256
|
+
default:
|
|
257
|
+
result = unpadded;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Mimic HTTP/2 traffic pattern
|
|
265
|
+
*/
|
|
266
|
+
mimicHTTP2Pattern(data) {
|
|
267
|
+
// Add HTTP/2 frame-like header (simplified)
|
|
268
|
+
const frameHeader = Buffer.allocUnsafe(9);
|
|
269
|
+
|
|
270
|
+
// Length (3 bytes)
|
|
271
|
+
const length = Math.min(data.length, 16383); // Max frame size
|
|
272
|
+
frameHeader.writeUIntBE(length, 0, 3);
|
|
273
|
+
|
|
274
|
+
// Type (1 byte) - DATA frame
|
|
275
|
+
frameHeader.writeUInt8(0x00, 3);
|
|
276
|
+
|
|
277
|
+
// Flags (1 byte)
|
|
278
|
+
frameHeader.writeUInt8(0x00, 4);
|
|
279
|
+
|
|
280
|
+
// Stream ID (4 bytes)
|
|
281
|
+
frameHeader.writeUInt32BE(crypto.randomInt(1, 1000), 5);
|
|
282
|
+
|
|
283
|
+
return Buffer.concat([frameHeader, data.slice(0, length)]);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Simulate burst traffic (like video streaming)
|
|
288
|
+
*/
|
|
289
|
+
async simulateBurstTraffic(dataChunks, callback) {
|
|
290
|
+
if (!this.enabled) {
|
|
291
|
+
for (const chunk of dataChunks) {
|
|
292
|
+
await callback(chunk);
|
|
293
|
+
}
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Send in bursts with pauses
|
|
298
|
+
const burstSize = crypto.randomInt(2, 6);
|
|
299
|
+
|
|
300
|
+
for (let i = 0; i < dataChunks.length; i++) {
|
|
301
|
+
await callback(dataChunks[i]);
|
|
302
|
+
|
|
303
|
+
// Add pause after burst
|
|
304
|
+
if ((i + 1) % burstSize === 0) {
|
|
305
|
+
const pauseDuration = crypto.randomInt(50, 200);
|
|
306
|
+
await new Promise(resolve => setTimeout(resolve, pauseDuration));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Enable obfuscation
|
|
313
|
+
*/
|
|
314
|
+
enable() {
|
|
315
|
+
this.enabled = true;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Disable obfuscation
|
|
320
|
+
*/
|
|
321
|
+
disable() {
|
|
322
|
+
this.enabled = false;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Get statistics
|
|
327
|
+
*/
|
|
328
|
+
getStats() {
|
|
329
|
+
return {
|
|
330
|
+
enabled: this.enabled,
|
|
331
|
+
mode: this.mode,
|
|
332
|
+
maxJitter: this.maxJitter,
|
|
333
|
+
maxPadding: this.maxPadding
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
module.exports = TrafficObfuscation;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Yaksha VPN Protocol Library
|
|
5
|
+
* Main entry point and exports
|
|
6
|
+
*
|
|
7
|
+
* @author Omindu Dissanayaka (SE U. G)
|
|
8
|
+
* @version 1.1.0
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// Core modules
|
|
13
|
+
const Protocol = require('./core/protocol');
|
|
14
|
+
const Encryption = require('./core/encryption');
|
|
15
|
+
const Connection = require('./core/connection');
|
|
16
|
+
|
|
17
|
+
// Security modules
|
|
18
|
+
const Authentication = require('./security/auth');
|
|
19
|
+
const SecurityLevels = require('./security/levels');
|
|
20
|
+
|
|
21
|
+
// Feature modules
|
|
22
|
+
const SNISpoofing = require('./features/sni-spoof');
|
|
23
|
+
const TrafficObfuscation = require('./features/traffic-obfuscation');
|
|
24
|
+
const MultiPath = require('./features/multi-path');
|
|
25
|
+
const DNSOverride = require('./features/dns-override');
|
|
26
|
+
const TLSCamouflage = require('./features/tls-camouflage');
|
|
27
|
+
|
|
28
|
+
// Bypass modules
|
|
29
|
+
const FirewallEvasion = require('./bypass/firewall-evasion');
|
|
30
|
+
|
|
31
|
+
// Server and Client
|
|
32
|
+
const YakshaServer = require('./server');
|
|
33
|
+
const YakshaClient = require('./client');
|
|
34
|
+
|
|
35
|
+
// Utilities
|
|
36
|
+
const Logger = require('./utils/logger');
|
|
37
|
+
const Config = require('./utils/config');
|
|
38
|
+
const BufferPool = require('./utils/buffer-pool');
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create a new Yaksha VPN server
|
|
42
|
+
* @param {Object} options - Server configuration options
|
|
43
|
+
* @returns {YakshaServer}
|
|
44
|
+
*/
|
|
45
|
+
function createServer(options = {}) {
|
|
46
|
+
return new YakshaServer(options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Create a new Yaksha VPN client
|
|
51
|
+
* @param {Object} options - Client configuration options
|
|
52
|
+
* @returns {YakshaClient}
|
|
53
|
+
*/
|
|
54
|
+
function createClient(options = {}) {
|
|
55
|
+
return new YakshaClient(options);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get version information
|
|
60
|
+
* @returns {string}
|
|
61
|
+
*/
|
|
62
|
+
function getVersion() {
|
|
63
|
+
return '1.1.0';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Main exports
|
|
67
|
+
module.exports = {
|
|
68
|
+
// Factory functions
|
|
69
|
+
createServer,
|
|
70
|
+
createClient,
|
|
71
|
+
|
|
72
|
+
// Server and Client classes
|
|
73
|
+
YakshaServer,
|
|
74
|
+
YakshaClient,
|
|
75
|
+
|
|
76
|
+
// Core
|
|
77
|
+
Protocol,
|
|
78
|
+
Encryption,
|
|
79
|
+
Connection,
|
|
80
|
+
|
|
81
|
+
// Security
|
|
82
|
+
Authentication,
|
|
83
|
+
SecurityLevels,
|
|
84
|
+
|
|
85
|
+
// Features
|
|
86
|
+
SNISpoofing,
|
|
87
|
+
TrafficObfuscation,
|
|
88
|
+
MultiPath,
|
|
89
|
+
DNSOverride,
|
|
90
|
+
TLSCamouflage,
|
|
91
|
+
|
|
92
|
+
// Bypass
|
|
93
|
+
FirewallEvasion,
|
|
94
|
+
|
|
95
|
+
// Utilities
|
|
96
|
+
Logger,
|
|
97
|
+
Config,
|
|
98
|
+
BufferPool,
|
|
99
|
+
|
|
100
|
+
// Info
|
|
101
|
+
version: getVersion(),
|
|
102
|
+
getVersion
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Default export
|
|
106
|
+
module.exports.default = module.exports;
|