@omindu/yaksha 1.0.0 → 1.0.1

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/README.md ADDED
@@ -0,0 +1,597 @@
1
+ # Yaksha VPN Protocol
2
+
3
+ <div align="center">
4
+
5
+ ⚡️ **Lightning-Fast** • 🔒 **Military-Grade Security** • 🚀 **Ultra-Lightweight** • 🛡️ **Firewall Bypass**
6
+
7
+ [![NPM Version](https://img.shields.io/npm/v/yaksha)](https://www.npmjs.com/package/yaksha)
8
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
+ [![Node](https://img.shields.io/node/v/yaksha)](https://nodejs.org)
10
+ [![Downloads](https://img.shields.io/npm/dm/yaksha)](https://www.npmjs.com/package/yaksha)
11
+
12
+ A high-performance, lightweight VPN protocol library with advanced firewall bypass capabilities, built for Node.js.
13
+
14
+ [Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [Documentation](#-documentation) • [Examples](#-examples)
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## 🎯 Overview
21
+
22
+ **Yaksha** is a modern VPN protocol implementation designed for maximum performance and security. It combines military-grade encryption with advanced traffic obfuscation techniques to bypass even the most restrictive firewalls and Deep Packet Inspection (DPI) systems.
23
+
24
+ ### Why Yaksha?
25
+
26
+ - ⚡️ **Blazing Fast**: >1 Gbps throughput, <5ms latency overhead
27
+ - 🪶 **Ultra-Lightweight**: <2000 lines of core code, <50MB memory per 1000 connections
28
+ - 🔒 **Military-Grade Security**: AES-256-GCM, ChaCha20-Poly1305, double encryption
29
+ - 🛡️ **Firewall Bypass**: SNI spoofing, traffic obfuscation, DPI evasion
30
+ - 🌐 **DNS Security**: DNS-over-HTTPS, DNS-over-TLS with DNSSEC
31
+ - 🚦 **Multi-Path Routing**: Aggregate bandwidth across multiple connections
32
+ - 🎭 **TLS Camouflage**: Traffic looks like legitimate HTTPS
33
+ - 📦 **Easy to Use**: Simple API, comprehensive documentation
34
+ - 🔧 **Highly Configurable**: Four security levels (Low/Medium/High/Custom)
35
+ - 🌍 **Cross-Platform**: Pure JavaScript, works everywhere Node.js runs
36
+
37
+ ---
38
+
39
+ ## ✨ Features
40
+
41
+ ### Core Features
42
+
43
+ | Feature | Description |
44
+ |---------|-------------|
45
+ | **Custom Protocol** | Lightweight, efficient protocol optimized for VPN traffic |
46
+ | **Multiple Encryption** | ChaCha20-Poly1305, AES-256-GCM, double encryption |
47
+ | **Perfect Forward Secrecy** | X25519 key exchange with automatic key rotation |
48
+ | **Authentication** | Password, token, and certificate-based auth with 2FA |
49
+ | **TCP + UDP** | Control channel (TCP) + high-speed data channel (UDP) |
50
+ | **Connection Pooling** | Efficient resource management for 10,000+ connections |
51
+
52
+ ### Advanced Features
53
+
54
+ | Feature | Description |
55
+ |---------|-------------|
56
+ | **SNI Spoofing** | Replace Server Name Indication with fake domains |
57
+ | **Bug Host Support** | Use specific domains to bypass network restrictions |
58
+ | **Traffic Obfuscation** | Randomize patterns to evade detection |
59
+ | **Multi-Path Routing** | Split traffic across 2-5 simultaneous connections |
60
+ | **DNS Override** | Tunnel all DNS queries through encrypted VPN |
61
+ | **TLS Camouflage** | Mimic TLS 1.3 handshake and traffic patterns |
62
+ | **Firewall Evasion** | Port hopping, packet fragmentation, timing manipulation |
63
+ | **DPI Resistance** | Encrypted payload, randomized structure, protocol masquerading |
64
+ | **Anti-Replay Protection** | Nonce + timestamp validation |
65
+ | **Rate Limiting** | Prevent brute force attacks |
66
+
67
+ ### Security Levels
68
+
69
+ #### 🟢 **LOW** (Speed Priority)
70
+ - **Encryption**: ChaCha20-Poly1305
71
+ - **Throughput**: ~2000 MB/s
72
+ - **Latency**: <2ms overhead
73
+ - **Use Cases**: Streaming, gaming, general browsing
74
+
75
+ #### 🟡 **MEDIUM** (Balanced)
76
+ - **Encryption**: AES-256-GCM
77
+ - **Throughput**: ~1000 MB/s
78
+ - **Latency**: <5ms overhead
79
+ - **Use Cases**: Daily use, business applications
80
+
81
+ #### 🔴 **HIGH** (Security Priority)
82
+ - **Encryption**: Double (AES-256-GCM + ChaCha20-Poly1305)
83
+ - **Throughput**: ~500 MB/s
84
+ - **Latency**: <10ms overhead
85
+ - **Use Cases**: Banking, sensitive data, high-security environments
86
+
87
+ #### ⚙️ **CUSTOM** (User-Defined)
88
+ - **Encryption**: Configurable (ChaCha20, AES-256-GCM, or Double)
89
+ - **Throughput**: Varies based on configuration
90
+ - **Latency**: Varies based on configuration
91
+ - **Use Cases**: Specific requirements, fine-tuned security/performance balance
92
+ - **Flexibility**: Mix and match features from any level
93
+ - **Base Levels**: Start from LOW, MEDIUM, or HIGH and customize
94
+
95
+ **Custom Level Features:**
96
+ ```javascript
97
+ // Create custom configuration based on medium level
98
+ const customConfig = SecurityLevels.createCustomConfig({
99
+ encryption: 'double', // Override encryption
100
+ keyExchange: 'x25519-rotate', // Override key exchange
101
+ obfuscation: 'aes-256-gcm', // Override obfuscation
102
+ multiPath: 3, // Custom path count
103
+ keyRotation: true, // Enable key rotation
104
+ keyRotationInterval: 2000 // Custom rotation interval
105
+ }, 'medium'); // Base level
106
+
107
+ // Use with server/client
108
+ const server = createServer({
109
+ securityLevel: 'custom',
110
+ customSecurityConfig: customConfig
111
+ });
112
+ ```
113
+
114
+ ---
115
+
116
+ ## 📦 Installation
117
+
118
+ ```bash
119
+ npm install @omindu/yaksha
120
+ ```
121
+
122
+ ### Requirements
123
+
124
+ - **Node.js**: >=14.0.0
125
+ - **OS**: Windows, Linux, macOS
126
+ - **Dependencies**: `tweetnacl` (automatically installed)
127
+
128
+ ---
129
+
130
+ ## 🚀 Quick Start
131
+
132
+ ### Server
133
+
134
+ ```javascript
135
+ const yaksha = require('@omindu/yaksha');
136
+
137
+ // Create server
138
+ const server = yaksha.createServer({
139
+ port: 8443,
140
+ securityLevel: 'medium',
141
+ authMethod: 'token'
142
+ });
143
+
144
+ // Register client
145
+ server.auth.registerToken('client1', 'your-secret-token');
146
+
147
+ // Start server
148
+ await server.start();
149
+ console.log('VPN server running on port 8443');
150
+ ```
151
+
152
+ ### Client
153
+
154
+ ```javascript
155
+ const yaksha = require('@omindu/yaksha');
156
+
157
+ // Create client
158
+ const client = yaksha.createClient({
159
+ server: 'vpn.example.com',
160
+ port: 8443,
161
+ securityLevel: 'medium',
162
+ authCredentials: {
163
+ identifier: 'client1',
164
+ token: 'your-secret-token'
165
+ }
166
+ });
167
+
168
+ // Connect
169
+ await client.connect();
170
+ console.log('Connected to VPN server');
171
+
172
+ // Send data
173
+ await client.send(Buffer.from('Hello, VPN!'));
174
+ ```
175
+
176
+ ### CLI Usage
177
+
178
+ ```bash
179
+ # Start server
180
+ yaksha server --port 8443 --security high
181
+
182
+ # Connect client
183
+ yaksha client --server vpn.example.com --token abc123
184
+
185
+ # Generate keys
186
+ yaksha keygen
187
+
188
+ # Run benchmarks
189
+ yaksha benchmark
190
+ ```
191
+
192
+ ---
193
+
194
+ ## 📖 Documentation
195
+
196
+ ### Server API
197
+
198
+ ```javascript
199
+ const server = yaksha.createServer(options);
200
+ ```
201
+
202
+ **Options:**
203
+ - `port` (number): Server port (default: 8443)
204
+ - `host` (string): Bind address (default: '0.0.0.0')
205
+ - `securityLevel` (string): 'low', 'medium', 'high', or 'custom' (default: 'medium')
206
+ - `customSecurityConfig` (object): Custom security configuration (required if securityLevel is 'custom')
207
+ - `authMethod` (string): 'password', 'token', or 'certificate' (default: 'token')
208
+ - `maxConnections` (number): Maximum concurrent connections (default: 10000)
209
+ - `logLevel` (string): 'debug', 'info', 'warn', 'error' (default: 'info')
210
+
211
+ **Methods:**
212
+ - `await server.start()`: Start the server
213
+ - `await server.stop()`: Stop the server
214
+ - `server.sendToClient(sessionId, data, protocol)`: Send data to specific client
215
+ - `server.getStats()`: Get server statistics
216
+
217
+ **Events:**
218
+ - `listening`: Server started
219
+ - `connection`: New client connected
220
+ - `disconnection`: Client disconnected
221
+ - `data`: Data received from client
222
+ - `error`: Error occurred
223
+
224
+ ### Client API
225
+
226
+ ```javascript
227
+ const client = yaksha.createClient(options);
228
+ ```
229
+
230
+ **Options:**
231
+ - `server` (string): Server address (required)
232
+ - `port` (number): Server port (default: 8443)
233
+ - `securityLevel` (string): 'low', 'medium', 'high', or 'custom' (default: 'medium')
234
+ - `customSecurityConfig` (object): Custom security configuration (required if securityLevel is 'custom')
235
+ - `autoReconnect` (boolean): Auto-reconnect on disconnect (default: true)
236
+ - `authCredentials` (object): Authentication credentials
237
+ - `features` (object): Enable/disable features
238
+
239
+ **Methods:**
240
+ - `await client.connect()`: Connect to server
241
+ - `await client.disconnect()`: Disconnect from server
242
+ - `await client.send(data, protocol)`: Send data through VPN
243
+ - `await client.resolveDNS(domain, type)`: Resolve DNS through VPN
244
+ - `client.getStats()`: Get client statistics
245
+
246
+ **Events:**
247
+ - `connected`: Connected to server
248
+ - `disconnected`: Disconnected from server
249
+ - `reconnecting`: Attempting reconnection
250
+ - `data`: Data received from server
251
+ - `error`: Error occurred
252
+
253
+ ---
254
+
255
+ ## 💡 Examples
256
+
257
+ ### Basic Server
258
+
259
+ ```javascript
260
+ const yaksha = require('@omindu/yaksha');
261
+
262
+ const server = yaksha.createServer({
263
+ port: 8443,
264
+ securityLevel: 'medium',
265
+ authMethod: 'token'
266
+ });
267
+
268
+ server.auth.registerToken('client1', 'secret-token-123');
269
+
270
+ server.on('connection', (sessionId, address) => {
271
+ console.log(`Client connected: ${address}`);
272
+ });
273
+
274
+ await server.start();
275
+ ```
276
+
277
+ ### Advanced Configuration
278
+
279
+ ```javascript
280
+ const client = yaksha.createClient({
281
+ server: 'vpn.example.com',
282
+ port: 8443,
283
+ securityLevel: 'high',
284
+ features: {
285
+ sniSpoofing: true,
286
+ trafficObfuscation: true,
287
+ multiPath: true,
288
+ dnsOverride: true,
289
+ tlsCamouflage: true,
290
+ firewallEvasion: true
291
+ },
292
+ authCredentials: {
293
+ identifier: 'secure-client',
294
+ certificate: 'base64-cert',
295
+ totpToken: '123456'
296
+ }
297
+ });
298
+
299
+ await client.connect();
300
+ ```
301
+
302
+ ### Custom Security Level
303
+
304
+ ```javascript
305
+ const { createServer, createClient, SecurityLevels } = require('@omindu/yaksha');
306
+
307
+ // Create custom configuration
308
+ const customConfig = SecurityLevels.createCustomConfig({
309
+ encryption: 'double',
310
+ keyExchange: 'x25519-rotate',
311
+ obfuscation: 'aes-256-gcm',
312
+ multiPath: 3,
313
+ keyRotation: true,
314
+ keyRotationInterval: 2000,
315
+ tlsCamouflage: 'full'
316
+ }, 'medium'); // Base level
317
+
318
+ // Server with custom security
319
+ const server = createServer({
320
+ port: 8443,
321
+ securityLevel: 'custom',
322
+ customSecurityConfig: customConfig
323
+ });
324
+
325
+ // Client with custom security
326
+ const client = createClient({
327
+ server: 'localhost',
328
+ port: 8443,
329
+ securityLevel: 'custom',
330
+ customSecurityConfig: customConfig
331
+ });
332
+ ```
333
+
334
+ ### DNS Resolution
335
+
336
+ ```javascript
337
+ const addresses = await client.resolveDNS('example.com', 'A');
338
+ console.log('IP addresses:', addresses);
339
+ ```
340
+
341
+ ### Bug Host Configuration
342
+
343
+ Bug Host allows bypassing network restrictions by setting SNI to an allowed domain:
344
+
345
+ ```javascript
346
+ // Client with bug host
347
+ const client = createClient({
348
+ server: 'vpn.example.com',
349
+ port: 8443,
350
+ bugHost: 'cloudflare.com', // SNI appears as cloudflare.com
351
+ securityLevel: 'custom',
352
+ customSecurityConfig: {
353
+ sniSpoofing: 'static',
354
+ bugHost: 'cloudflare.com'
355
+ }
356
+ });
357
+
358
+ // Popular bug hosts
359
+ const bugHosts = {
360
+ cdn: 'cloudflare.com',
361
+ social: 'facebook.com',
362
+ tech: 'google.com',
363
+ education: 'wikipedia.org'
364
+ };
365
+ ```
366
+
367
+ **See [examples/bug-host-example.js](examples/bug-host-example.js) for comprehensive bug host usage.**
368
+
369
+ ---
370
+
371
+ ## 🔧 Configuration
372
+
373
+ ### Environment Variables
374
+
375
+ ```bash
376
+ YAKSHA_HOST=0.0.0.0
377
+ YAKSHA_PORT=8443
378
+ YAKSHA_SECURITY_LEVEL=medium
379
+ YAKSHA_AUTH_METHOD=token
380
+ YAKSHA_LOG_LEVEL=info
381
+ ```
382
+
383
+ ### Configuration File
384
+
385
+ ```json
386
+ {
387
+ "server": {
388
+ "host": "0.0.0.0",
389
+ "port": 8443,
390
+ "maxConnections": 10000
391
+ },
392
+ "security": {
393
+ "level": "high",
394
+ "authMethod": "certificate"
395
+ },
396
+ "features": {
397
+ "sniSpoofing": true,
398
+ "trafficObfuscation": true,
399
+ "multiPath": true,
400
+ "dnsOverride": true,
401
+ "tlsCamouflage": true,
402
+ "firewallEvasion": true
403
+ }
404
+ }
405
+ ```
406
+
407
+ Load with: `const config = new yaksha.Config(); config.loadFromFile('config.json');`
408
+
409
+ ---
410
+
411
+ ## 📊 Performance
412
+
413
+ ### Benchmarks
414
+
415
+ | Metric | Value |
416
+ |--------|-------|
417
+ | Throughput | >1 Gbps on gigabit connection |
418
+ | Latency Overhead | <5ms (medium security) |
419
+ | Memory Usage | <50MB per 1000 connections |
420
+ | CPU Usage | <10% on 4-core modern CPU |
421
+ | Concurrent Connections | 10,000+ |
422
+ | Packet Processing | ~100,000 packets/second |
423
+
424
+ ### Optimization Tips
425
+
426
+ 1. **Use UDP for data**: Lower latency than TCP
427
+ 2. **Enable buffer pooling**: Reduces GC pressure
428
+ 3. **Choose appropriate security level**: Balance security vs performance
429
+ 4. **Enable multi-path**: Aggregate bandwidth
430
+ 5. **Adjust MTU**: Optimize for your network
431
+
432
+ ---
433
+
434
+ ## 🔒 Security
435
+
436
+ ### Encryption Algorithms
437
+
438
+ - **ChaCha20-Poly1305**: Fast, secure stream cipher
439
+ - **AES-256-GCM**: Industry standard, hardware-accelerated
440
+ - **Double Encryption**: Maximum security (AES + ChaCha20)
441
+
442
+ ### Key Exchange
443
+
444
+ - **X25519**: Elliptic curve Diffie-Hellman
445
+ - **Perfect Forward Secrecy**: New keys for each session
446
+ - **Key Rotation**: Automatic rekeying (high security mode)
447
+
448
+ ### Authentication
449
+
450
+ - **Password**: bcrypt hashing, rate limiting
451
+ - **Token**: Time-based, automatic rotation
452
+ - **Certificate**: X.509 with optional 2FA
453
+
454
+ ### Security Best Practices
455
+
456
+ 1. Always use TLS/SSL in production
457
+ 2. Enable all firewall bypass features
458
+ 3. Use high security level for sensitive data
459
+ 4. Rotate authentication tokens regularly
460
+ 5. Use custom security level for specific requirements
461
+ 6. Monitor for unusual traffic patterns
462
+ 7. Keep dependencies updated
463
+
464
+ ### Custom Security Configurations
465
+
466
+ Yaksha supports custom security configurations through the `createCustomConfig` method:
467
+
468
+ ```javascript
469
+ const { SecurityLevels } = require('@omindu/yaksha');
470
+
471
+ // IoT Device (Low resource, moderate security)
472
+ const iotConfig = SecurityLevels.createCustomConfig({
473
+ encryption: 'chacha20-poly1305',
474
+ obfuscation: 'xor',
475
+ multiPath: 1,
476
+ keyRotation: false
477
+ }, 'low');
478
+
479
+ // Corporate VPN (Balanced + Compliance)
480
+ const corporateConfig = SecurityLevels.createCustomConfig({
481
+ encryption: 'aes-256-gcm',
482
+ certificateValidation: true,
483
+ keyRotation: true,
484
+ multiPath: 4
485
+ }, 'medium');
486
+
487
+ // Maximum Security (Government/Banking)
488
+ const maxSecurityConfig = SecurityLevels.createCustomConfig({
489
+ encryption: 'double',
490
+ twoFactorAuth: true,
491
+ keyRotationInterval: 250,
492
+ multiPath: 8
493
+ }, 'high');
494
+ ```
495
+
496
+ **See [examples/custom-level-example.js](examples/custom-level-example.js) for more custom configurations.**
497
+
498
+ ---
499
+
500
+ ## 🧪 Testing
501
+
502
+ ```bash
503
+ # Run all tests
504
+ npm test
505
+
506
+ # Run specific test suite
507
+ npm test -- core.test.js
508
+
509
+ # Run with coverage
510
+ npm run test:coverage
511
+
512
+ # Run benchmarks
513
+ npm run benchmark
514
+ ```
515
+
516
+ ---
517
+
518
+ ## 🤝 Contributing
519
+
520
+ Contributions are welcome! Please read our [Contributing Guidelines](CONTRIBUTING.md) first.
521
+
522
+ 1. Fork the repository
523
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
524
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
525
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
526
+ 5. Open a Pull Request
527
+
528
+ ---
529
+
530
+ ## 📝 License
531
+
532
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
533
+
534
+ ---
535
+
536
+ ## 👤 Author
537
+
538
+ **Omindu Dissanayaka** (SE U. G)
539
+
540
+ - GitHub: [@OminduDissanayaka](https://github.com/OminduDissanayaka)
541
+ - Email: contact@example.com
542
+
543
+ ---
544
+
545
+ ## 🙏 Acknowledgments
546
+
547
+ - Built with Node.js
548
+ - Uses TweetNaCl for some cryptographic operations
549
+ - Inspired by modern VPN protocols (WireGuard, OpenVPN)
550
+
551
+ ---
552
+
553
+ ## 📚 Additional Documentation
554
+
555
+ - [API Reference](docs/API.md)
556
+ - [Security Model](docs/SECURITY.md)
557
+ - [Protocol Specification](docs/PROTOCOL.md)
558
+ - [Performance Tuning](docs/PERFORMANCE.md)
559
+ - [Troubleshooting](docs/TROUBLESHOOTING.md)
560
+
561
+ ---
562
+
563
+ ## 🗺️ Roadmap
564
+
565
+ ### Version 1.1
566
+ - [ ] WebSocket support
567
+ - [ ] QUIC protocol support
568
+ - [ ] IPv6 support
569
+ - [ ] Plugin system
570
+
571
+ ### Version 1.2
572
+ - [ ] GUI client
573
+ - [ ] Mobile support (React Native)
574
+ - [ ] Traffic statistics dashboard
575
+ - [ ] Web admin panel
576
+
577
+ ### Version 2.0
578
+ - [ ] P2P mode
579
+ - [ ] Mesh networking
580
+ - [ ] Blockchain-based authentication
581
+ - [ ] Quantum-resistant encryption
582
+
583
+ ---
584
+
585
+ ## ⚠️ Disclaimer
586
+
587
+ This software is provided for educational and research purposes. Ensure compliance with local laws and regulations when using VPN technology. The authors are not responsible for misuse of this software.
588
+
589
+ ---
590
+
591
+ <div align="center">
592
+
593
+ Made with ❤️ by Omindu Dissanayaka
594
+
595
+ **If you find this project useful, please give it a ⭐️**
596
+
597
+ </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omindu/yaksha",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Lightning-fast, lightweight VPN protocol library with advanced firewall bypass capabilities",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -1,12 +1,18 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * Yaksha Protocol Handler
5
- * Custom protocol for packet parsing and handling
4
+ * Yaksha Protocol Implementation (v1.1.0 - Cross-Platform Fixed)
5
+ * Fixed for Linux server <-> Windows client compatibility
6
+ * - Explicit unsigned integer operations
7
+ * - Platform-independent CRC32 checksum
8
+ * - Robust buffer handling with proper byte ordering
6
9
  */
7
10
 
8
11
  const crypto = require('crypto');
9
- const { globalPool } = require('../utils/buffer-pool');
12
+
13
+ // Protocol constants
14
+ const PROTOCOL_VERSION = 0x01;
15
+ const HEADER_SIZE = 16; // bytes
10
16
 
11
17
  // Packet types
12
18
  const PACKET_TYPES = {
@@ -17,12 +23,6 @@ const PACKET_TYPES = {
17
23
  KEEPALIVE: 0x05
18
24
  };
19
25
 
20
- // Protocol version
21
- const PROTOCOL_VERSION = 0x01;
22
-
23
- // Header size (fixed 16 bytes)
24
- const HEADER_SIZE = 16;
25
-
26
26
  class Protocol {
27
27
  constructor(options = {}) {
28
28
  this.version = PROTOCOL_VERSION;
@@ -31,56 +31,59 @@ class Protocol {
31
31
  }
32
32
 
33
33
  /**
34
- * Create a packet header
35
- * Header structure (16 bytes):
36
- * - Version (1 byte)
37
- * - Type (1 byte)
38
- * - Length (2 bytes) - payload length
39
- * - Session ID (4 bytes)
40
- * - Sequence (4 bytes)
41
- * - Checksum (4 bytes)
34
+ * Create protocol header with explicit byte ordering
35
+ * CRITICAL: Uses big-endian for all multi-byte values for cross-platform consistency
42
36
  */
43
- createHeader(type, payloadLength, sessionId, sequence) {
44
- const header = globalPool.acquire(HEADER_SIZE, true);
45
-
46
- // Version
47
- header.writeUInt8(this.version, 0);
48
-
49
- // Type
50
- header.writeUInt8(type, 1);
51
-
52
- // Length (uint16, max 65535)
53
- header.writeUInt16BE(payloadLength, 2);
54
-
55
- // Session ID (uint32)
56
- header.writeUInt32BE(sessionId, 4);
57
-
58
- // Sequence (uint32)
59
- header.writeUInt32BE(sequence, 8);
60
-
61
- // Checksum placeholder (will be filled later)
62
- header.writeUInt32BE(0, 12);
63
-
37
+ createHeader(type, length, sessionId, sequence) {
38
+ const header = Buffer.alloc(HEADER_SIZE); // Zero-filled for consistency
39
+
40
+ // Force unsigned integers to prevent sign issues across platforms
41
+ const safeType = (type & 0xFF) >>> 0;
42
+ const safeLength = (length & 0xFFFF) >>> 0;
43
+ const safeSessionId = (sessionId >>> 0);
44
+ const safeSequence = (sequence >>> 0);
45
+
46
+ header.writeUInt8(this.version, 0); // Version (1 byte)
47
+ header.writeUInt8(safeType, 1); // Type (1 byte)
48
+ header.writeUInt16BE(safeLength, 2); // Length (2 bytes, big-endian)
49
+ header.writeUInt32BE(safeSessionId, 4); // Session ID (4 bytes, big-endian)
50
+ header.writeUInt32BE(safeSequence, 8); // Sequence (4 bytes, big-endian)
51
+ header.writeUInt32BE(0, 12); // Checksum placeholder (4 bytes)
52
+
64
53
  return header;
65
54
  }
66
55
 
67
56
  /**
68
- * Calculate CRC32 checksum
57
+ * Calculate CRC32 checksum with explicit unsigned operations
58
+ * CRITICAL FIX: Ensures same result on Linux and Windows
69
59
  */
70
60
  calculateChecksum(data) {
71
- // Simple CRC32 implementation
72
- let crc = 0xFFFFFFFF;
61
+ // Ensure we're working with a Buffer
62
+ if (!Buffer.isBuffer(data)) {
63
+ data = Buffer.from(data);
64
+ }
65
+
66
+ let crc = 0xFFFFFFFF >>> 0; // Force unsigned
67
+
73
68
  for (let i = 0; i < data.length; i++) {
74
- crc ^= data[i];
69
+ const byte = data[i] & 0xFF; // Ensure byte is 0-255
70
+ crc = (crc ^ byte) >>> 0;
71
+
75
72
  for (let j = 0; j < 8; j++) {
76
- crc = (crc >>> 1) ^ (0xEDB88320 & -(crc & 1));
73
+ // Explicit unsigned right shift and bitwise operations
74
+ if ((crc & 1) !== 0) {
75
+ crc = ((crc >>> 1) ^ 0xEDB88320) >>> 0;
76
+ } else {
77
+ crc = (crc >>> 1) >>> 0;
78
+ }
77
79
  }
78
80
  }
79
- return (crc ^ 0xFFFFFFFF) >>> 0;
81
+
82
+ return ((crc ^ 0xFFFFFFFF) >>> 0);
80
83
  }
81
84
 
82
85
  /**
83
- * Add random padding for traffic obfuscation
86
+ * Add random padding for obfuscation
84
87
  */
85
88
  addPadding(data, maxPaddingSize = 255) {
86
89
  if (!this.enablePadding) {
@@ -102,27 +105,48 @@ class Protocol {
102
105
  * Remove padding from data
103
106
  */
104
107
  removePadding(data, paddingSize) {
105
- if (paddingSize === 0) {
108
+ if (paddingSize === 0 || !paddingSize) {
106
109
  return data;
107
110
  }
108
111
  return data.slice(0, -paddingSize);
109
112
  }
110
113
 
111
114
  /**
112
- * Serialize packet
115
+ * Serialize packet (Linux/Windows compatible)
116
+ * CRITICAL FIX: Proper buffer construction and checksum calculation
113
117
  */
114
118
  serialize(type, payload, sessionId, sequence) {
119
+ // Ensure payload is a proper Buffer
120
+ if (!Buffer.isBuffer(payload)) {
121
+ if (typeof payload === 'string') {
122
+ payload = Buffer.from(payload, 'utf8');
123
+ } else {
124
+ payload = Buffer.from(payload);
125
+ }
126
+ }
127
+
115
128
  // Add padding to payload
116
129
  const { data: paddedPayload, paddingSize } = this.addPadding(payload);
117
130
 
118
- // Create header
119
- const header = this.createHeader(type, paddedPayload.length, sessionId, sequence);
131
+ // Force safe unsigned integers
132
+ const safeSessionId = (sessionId >>> 0);
133
+ const safeSequence = (sequence >>> 0);
134
+
135
+ // Create header with zero checksum
136
+ const header = this.createHeader(type, paddedPayload.length, safeSessionId, safeSequence);
120
137
 
121
- // Combine header and payload
122
- const packet = Buffer.concat([header, paddedPayload]);
138
+ // Create complete packet buffer (avoid Buffer.concat for consistency)
139
+ const totalSize = header.length + paddedPayload.length;
140
+ const packet = Buffer.allocUnsafe(totalSize);
141
+
142
+ // Copy header and payload explicitly
143
+ header.copy(packet, 0, 0, header.length);
144
+ paddedPayload.copy(packet, header.length, 0, paddedPayload.length);
123
145
 
124
- // Calculate and update checksum (checksum covers header + payload)
125
- const checksum = this.calculateChecksum(packet);
146
+ // Calculate checksum over entire packet (with checksum field zeroed)
147
+ const checksum = this.calculateChecksum(packet) >>> 0;
148
+
149
+ // Write checksum to header
126
150
  packet.writeUInt32BE(checksum, 12);
127
151
 
128
152
  return { packet, paddingSize };
@@ -132,20 +156,25 @@ class Protocol {
132
156
  * Parse packet header
133
157
  */
134
158
  parseHeader(buffer) {
159
+ if (!Buffer.isBuffer(buffer)) {
160
+ throw new Error('Invalid buffer: not a Buffer object');
161
+ }
162
+
135
163
  if (buffer.length < HEADER_SIZE) {
136
- throw new Error('Buffer too small for header');
164
+ throw new Error(`Buffer too small for header: ${buffer.length} bytes (need ${HEADER_SIZE})`);
137
165
  }
138
166
 
139
- const version = buffer.readUInt8(0);
140
- const type = buffer.readUInt8(1);
141
- const length = buffer.readUInt16BE(2);
142
- const sessionId = buffer.readUInt32BE(4);
143
- const sequence = buffer.readUInt32BE(8);
144
- const checksum = buffer.readUInt32BE(12);
167
+ // Read with explicit unsigned operations
168
+ const version = buffer.readUInt8(0) & 0xFF;
169
+ const type = buffer.readUInt8(1) & 0xFF;
170
+ const length = buffer.readUInt16BE(2) >>> 0;
171
+ const sessionId = buffer.readUInt32BE(4) >>> 0;
172
+ const sequence = buffer.readUInt32BE(8) >>> 0;
173
+ const checksum = buffer.readUInt32BE(12) >>> 0;
145
174
 
146
175
  // Validate version
147
176
  if (version !== this.version) {
148
- throw new Error(`Unsupported protocol version: ${version}`);
177
+ throw new Error(`Unsupported protocol version: ${version} (expected ${this.version})`);
149
178
  }
150
179
 
151
180
  // Validate type
@@ -155,7 +184,7 @@ class Protocol {
155
184
 
156
185
  // Validate length
157
186
  if (length > this.maxPayloadSize) {
158
- throw new Error(`Payload too large: ${length}`);
187
+ throw new Error(`Payload too large: ${length} (max ${this.maxPayloadSize})`);
159
188
  }
160
189
 
161
190
  return {
@@ -169,99 +198,89 @@ class Protocol {
169
198
  }
170
199
 
171
200
  /**
172
- * Deserialize packet
201
+ * Deserialize packet (Linux/Windows compatible)
202
+ * CRITICAL FIX: Robust validation and error reporting
173
203
  */
174
204
  deserialize(buffer, paddingSize = 0) {
175
- // Parse header
176
- const header = this.parseHeader(buffer);
205
+ if (!Buffer.isBuffer(buffer)) {
206
+ throw new Error('Invalid buffer: not a Buffer object');
207
+ }
177
208
 
178
- // Check if we have complete packet
179
- const expectedSize = HEADER_SIZE + header.length;
180
- if (buffer.length < expectedSize) {
181
- throw new Error(`Incomplete packet: expected ${expectedSize}, got ${buffer.length}`);
209
+ // Parse header first
210
+ const header = this.parseHeader(buffer);
211
+
212
+ const totalExpectedSize = HEADER_SIZE + header.length;
213
+ if (buffer.length < totalExpectedSize) {
214
+ throw new Error(
215
+ `Incomplete packet: got ${buffer.length} bytes, expected ${totalExpectedSize} ` +
216
+ `(header=${HEADER_SIZE}, payload=${header.length})`
217
+ );
182
218
  }
183
219
 
184
- // Verify checksum
185
- const storedChecksum = header.checksum;
220
+ // Extract payload (create new buffer to avoid reference issues)
221
+ const payloadStart = HEADER_SIZE;
222
+ const payloadEnd = payloadStart + header.length;
223
+ const payload = Buffer.allocUnsafe(header.length);
224
+ buffer.copy(payload, 0, payloadStart, payloadEnd);
225
+
226
+ // Verify checksum - recalculate with checksum field zeroed
227
+ const verifyBuffer = Buffer.allocUnsafe(buffer.length);
228
+ buffer.copy(verifyBuffer, 0, 0, buffer.length);
229
+ verifyBuffer.writeUInt32BE(0, 12); // Zero out checksum field
186
230
 
187
- // Create a copy of packet and zero out checksum field for verification
188
- const packetCopy = Buffer.from(buffer.slice(0, expectedSize));
189
- packetCopy.writeUInt32BE(0, 12);
231
+ const calculatedChecksum = this.calculateChecksum(verifyBuffer) >>> 0;
232
+ const receivedChecksum = header.checksum >>> 0;
190
233
 
191
- const calculatedChecksum = this.calculateChecksum(packetCopy);
192
-
193
- if (storedChecksum !== calculatedChecksum) {
194
- throw new Error('Checksum verification failed');
234
+ if (receivedChecksum !== calculatedChecksum) {
235
+ // Detailed error for debugging cross-platform issues
236
+ const debugInfo = {
237
+ received: '0x' + receivedChecksum.toString(16).padStart(8, '0').toUpperCase(),
238
+ calculated: '0x' + calculatedChecksum.toString(16).padStart(8, '0').toUpperCase(),
239
+ packetSize: buffer.length,
240
+ headerSize: HEADER_SIZE,
241
+ payloadSize: header.length,
242
+ type: header.type,
243
+ sequence: header.sequence,
244
+ platform: process.platform,
245
+ nodeVersion: process.version
246
+ };
247
+
248
+ throw new Error(
249
+ `Checksum verification failed!\n` +
250
+ ` Received: ${debugInfo.received}\n` +
251
+ ` Calculated: ${debugInfo.calculated}\n` +
252
+ ` Packet: ${debugInfo.packetSize} bytes (header=${debugInfo.headerSize}, payload=${debugInfo.payloadSize})\n` +
253
+ ` Type: ${debugInfo.type}, Sequence: ${debugInfo.sequence}\n` +
254
+ ` Platform: ${debugInfo.platform}, Node: ${debugInfo.nodeVersion}`
255
+ );
195
256
  }
196
257
 
197
- // Extract payload
198
- let payload = buffer.slice(HEADER_SIZE, expectedSize);
199
-
200
- // Remove padding if present
201
- payload = this.removePadding(payload, paddingSize);
258
+ // Remove padding from payload
259
+ const unpaddedPayload = this.removePadding(payload, paddingSize);
202
260
 
203
261
  return {
204
- header,
205
- payload,
206
- totalSize: expectedSize
262
+ type: header.type,
263
+ payload: unpaddedPayload,
264
+ sessionId: header.sessionId,
265
+ sequence: header.sequence,
266
+ checksum: header.checksum
207
267
  };
208
268
  }
209
269
 
210
- /**
211
- * Create HANDSHAKE packet
212
- */
213
- createHandshake(sessionId, sequence, data) {
214
- return this.serialize(PACKET_TYPES.HANDSHAKE, data, sessionId, sequence);
215
- }
216
-
217
- /**
218
- * Create DATA packet
219
- */
220
- createData(sessionId, sequence, data) {
221
- return this.serialize(PACKET_TYPES.DATA, data, sessionId, sequence);
222
- }
223
-
224
- /**
225
- * Create ACK packet
226
- */
227
- createAck(sessionId, sequence, ackSequence) {
228
- const ackBuffer = Buffer.allocUnsafe(4);
229
- ackBuffer.writeUInt32BE(ackSequence, 0);
230
- return this.serialize(PACKET_TYPES.ACK, ackBuffer, sessionId, sequence);
231
- }
232
-
233
- /**
234
- * Create CLOSE packet
235
- */
236
- createClose(sessionId, sequence, reason = '') {
237
- const reasonBuffer = Buffer.from(reason, 'utf8');
238
- return this.serialize(PACKET_TYPES.CLOSE, reasonBuffer, sessionId, sequence);
239
- }
240
-
241
- /**
242
- * Create KEEPALIVE packet
243
- */
244
- createKeepalive(sessionId, sequence) {
245
- const timestamp = Buffer.allocUnsafe(8);
246
- timestamp.writeBigUInt64BE(BigInt(Date.now()), 0);
247
- return this.serialize(PACKET_TYPES.KEEPALIVE, timestamp, sessionId, sequence);
248
- }
249
-
250
270
  /**
251
271
  * Get packet type name
252
272
  */
253
- getTypeName(type) {
254
- const typeNames = {
255
- [PACKET_TYPES.HANDSHAKE]: 'HANDSHAKE',
256
- [PACKET_TYPES.DATA]: 'DATA',
257
- [PACKET_TYPES.ACK]: 'ACK',
258
- [PACKET_TYPES.CLOSE]: 'CLOSE',
259
- [PACKET_TYPES.KEEPALIVE]: 'KEEPALIVE'
260
- };
261
- return typeNames[type] || 'UNKNOWN';
273
+ getPacketTypeName(type) {
274
+ for (const [name, value] of Object.entries(PACKET_TYPES)) {
275
+ if (value === type) {
276
+ return name;
277
+ }
278
+ }
279
+ return `UNKNOWN(${type})`;
262
280
  }
263
281
  }
264
282
 
283
+ // Export
265
284
  module.exports = Protocol;
266
285
  module.exports.PACKET_TYPES = PACKET_TYPES;
267
286
  module.exports.HEADER_SIZE = HEADER_SIZE;
@@ -0,0 +1,268 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Yaksha Protocol Handler
5
+ * Custom protocol for packet parsing and handling
6
+ */
7
+
8
+ const crypto = require('crypto');
9
+ const { globalPool } = require('../utils/buffer-pool');
10
+
11
+ // Packet types
12
+ const PACKET_TYPES = {
13
+ HANDSHAKE: 0x01,
14
+ DATA: 0x02,
15
+ ACK: 0x03,
16
+ CLOSE: 0x04,
17
+ KEEPALIVE: 0x05
18
+ };
19
+
20
+ // Protocol version
21
+ const PROTOCOL_VERSION = 0x01;
22
+
23
+ // Header size (fixed 16 bytes)
24
+ const HEADER_SIZE = 16;
25
+
26
+ class Protocol {
27
+ constructor(options = {}) {
28
+ this.version = PROTOCOL_VERSION;
29
+ this.maxPayloadSize = options.maxPayloadSize || 65535;
30
+ this.enablePadding = options.enablePadding !== false;
31
+ }
32
+
33
+ /**
34
+ * Create a packet header
35
+ * Header structure (16 bytes):
36
+ * - Version (1 byte)
37
+ * - Type (1 byte)
38
+ * - Length (2 bytes) - payload length
39
+ * - Session ID (4 bytes)
40
+ * - Sequence (4 bytes)
41
+ * - Checksum (4 bytes)
42
+ */
43
+ createHeader(type, payloadLength, sessionId, sequence) {
44
+ const header = globalPool.acquire(HEADER_SIZE, true);
45
+
46
+ // Version
47
+ header.writeUInt8(this.version, 0);
48
+
49
+ // Type
50
+ header.writeUInt8(type, 1);
51
+
52
+ // Length (uint16, max 65535)
53
+ header.writeUInt16BE(payloadLength, 2);
54
+
55
+ // Session ID (uint32)
56
+ header.writeUInt32BE(sessionId, 4);
57
+
58
+ // Sequence (uint32)
59
+ header.writeUInt32BE(sequence, 8);
60
+
61
+ // Checksum placeholder (will be filled later)
62
+ header.writeUInt32BE(0, 12);
63
+
64
+ return header;
65
+ }
66
+
67
+ /**
68
+ * Calculate CRC32 checksum
69
+ */
70
+ calculateChecksum(data) {
71
+ // Simple CRC32 implementation
72
+ let crc = 0xFFFFFFFF;
73
+ for (let i = 0; i < data.length; i++) {
74
+ crc ^= data[i];
75
+ for (let j = 0; j < 8; j++) {
76
+ crc = (crc >>> 1) ^ (0xEDB88320 & -(crc & 1));
77
+ }
78
+ }
79
+ return (crc ^ 0xFFFFFFFF) >>> 0;
80
+ }
81
+
82
+ /**
83
+ * Add random padding for traffic obfuscation
84
+ */
85
+ addPadding(data, maxPaddingSize = 255) {
86
+ if (!this.enablePadding) {
87
+ return { data, paddingSize: 0 };
88
+ }
89
+
90
+ const paddingSize = crypto.randomInt(0, Math.min(maxPaddingSize + 1, 256));
91
+ if (paddingSize === 0) {
92
+ return { data, paddingSize: 0 };
93
+ }
94
+
95
+ const padding = crypto.randomBytes(paddingSize);
96
+ const paddedData = Buffer.concat([data, padding]);
97
+
98
+ return { data: paddedData, paddingSize };
99
+ }
100
+
101
+ /**
102
+ * Remove padding from data
103
+ */
104
+ removePadding(data, paddingSize) {
105
+ if (paddingSize === 0) {
106
+ return data;
107
+ }
108
+ return data.slice(0, -paddingSize);
109
+ }
110
+
111
+ /**
112
+ * Serialize packet
113
+ */
114
+ serialize(type, payload, sessionId, sequence) {
115
+ // Add padding to payload
116
+ const { data: paddedPayload, paddingSize } = this.addPadding(payload);
117
+
118
+ // Create header
119
+ const header = this.createHeader(type, paddedPayload.length, sessionId, sequence);
120
+
121
+ // Combine header and payload
122
+ const packet = Buffer.concat([header, paddedPayload]);
123
+
124
+ // Calculate and update checksum (checksum covers header + payload)
125
+ const checksum = this.calculateChecksum(packet);
126
+ packet.writeUInt32BE(checksum, 12);
127
+
128
+ return { packet, paddingSize };
129
+ }
130
+
131
+ /**
132
+ * Parse packet header
133
+ */
134
+ parseHeader(buffer) {
135
+ if (buffer.length < HEADER_SIZE) {
136
+ throw new Error('Buffer too small for header');
137
+ }
138
+
139
+ const version = buffer.readUInt8(0);
140
+ const type = buffer.readUInt8(1);
141
+ const length = buffer.readUInt16BE(2);
142
+ const sessionId = buffer.readUInt32BE(4);
143
+ const sequence = buffer.readUInt32BE(8);
144
+ const checksum = buffer.readUInt32BE(12);
145
+
146
+ // Validate version
147
+ if (version !== this.version) {
148
+ throw new Error(`Unsupported protocol version: ${version}`);
149
+ }
150
+
151
+ // Validate type
152
+ if (!Object.values(PACKET_TYPES).includes(type)) {
153
+ throw new Error(`Invalid packet type: ${type}`);
154
+ }
155
+
156
+ // Validate length
157
+ if (length > this.maxPayloadSize) {
158
+ throw new Error(`Payload too large: ${length}`);
159
+ }
160
+
161
+ return {
162
+ version,
163
+ type,
164
+ length,
165
+ sessionId,
166
+ sequence,
167
+ checksum
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Deserialize packet
173
+ */
174
+ deserialize(buffer, paddingSize = 0) {
175
+ // Parse header
176
+ const header = this.parseHeader(buffer);
177
+
178
+ // Check if we have complete packet
179
+ const expectedSize = HEADER_SIZE + header.length;
180
+ if (buffer.length < expectedSize) {
181
+ throw new Error(`Incomplete packet: expected ${expectedSize}, got ${buffer.length}`);
182
+ }
183
+
184
+ // Verify checksum
185
+ const storedChecksum = header.checksum;
186
+
187
+ // Create a copy of packet and zero out checksum field for verification
188
+ const packetCopy = Buffer.from(buffer.slice(0, expectedSize));
189
+ packetCopy.writeUInt32BE(0, 12);
190
+
191
+ const calculatedChecksum = this.calculateChecksum(packetCopy);
192
+
193
+ if (storedChecksum !== calculatedChecksum) {
194
+ throw new Error('Checksum verification failed');
195
+ }
196
+
197
+ // Extract payload
198
+ let payload = buffer.slice(HEADER_SIZE, expectedSize);
199
+
200
+ // Remove padding if present
201
+ payload = this.removePadding(payload, paddingSize);
202
+
203
+ return {
204
+ header,
205
+ payload,
206
+ totalSize: expectedSize
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Create HANDSHAKE packet
212
+ */
213
+ createHandshake(sessionId, sequence, data) {
214
+ return this.serialize(PACKET_TYPES.HANDSHAKE, data, sessionId, sequence);
215
+ }
216
+
217
+ /**
218
+ * Create DATA packet
219
+ */
220
+ createData(sessionId, sequence, data) {
221
+ return this.serialize(PACKET_TYPES.DATA, data, sessionId, sequence);
222
+ }
223
+
224
+ /**
225
+ * Create ACK packet
226
+ */
227
+ createAck(sessionId, sequence, ackSequence) {
228
+ const ackBuffer = Buffer.allocUnsafe(4);
229
+ ackBuffer.writeUInt32BE(ackSequence, 0);
230
+ return this.serialize(PACKET_TYPES.ACK, ackBuffer, sessionId, sequence);
231
+ }
232
+
233
+ /**
234
+ * Create CLOSE packet
235
+ */
236
+ createClose(sessionId, sequence, reason = '') {
237
+ const reasonBuffer = Buffer.from(reason, 'utf8');
238
+ return this.serialize(PACKET_TYPES.CLOSE, reasonBuffer, sessionId, sequence);
239
+ }
240
+
241
+ /**
242
+ * Create KEEPALIVE packet
243
+ */
244
+ createKeepalive(sessionId, sequence) {
245
+ const timestamp = Buffer.allocUnsafe(8);
246
+ timestamp.writeBigUInt64BE(BigInt(Date.now()), 0);
247
+ return this.serialize(PACKET_TYPES.KEEPALIVE, timestamp, sessionId, sequence);
248
+ }
249
+
250
+ /**
251
+ * Get packet type name
252
+ */
253
+ getTypeName(type) {
254
+ const typeNames = {
255
+ [PACKET_TYPES.HANDSHAKE]: 'HANDSHAKE',
256
+ [PACKET_TYPES.DATA]: 'DATA',
257
+ [PACKET_TYPES.ACK]: 'ACK',
258
+ [PACKET_TYPES.CLOSE]: 'CLOSE',
259
+ [PACKET_TYPES.KEEPALIVE]: 'KEEPALIVE'
260
+ };
261
+ return typeNames[type] || 'UNKNOWN';
262
+ }
263
+ }
264
+
265
+ module.exports = Protocol;
266
+ module.exports.PACKET_TYPES = PACKET_TYPES;
267
+ module.exports.HEADER_SIZE = HEADER_SIZE;
268
+ module.exports.PROTOCOL_VERSION = PROTOCOL_VERSION;