2025-07-21 19:40:01 +00:00
|
|
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
|
|
import * as smartproxy from '../ts/index.js';
|
|
|
|
|
|
|
|
tap.test('Protocol Detection - TLS Detection', async () => {
|
|
|
|
// Test TLS handshake detection
|
|
|
|
const tlsHandshake = Buffer.from([
|
|
|
|
0x16, // Handshake record type
|
|
|
|
0x03, 0x01, // TLS 1.0
|
|
|
|
0x00, 0x05, // Length: 5 bytes
|
|
|
|
0x01, // ClientHello
|
|
|
|
0x00, 0x00, 0x01, 0x00 // Handshake length and data
|
|
|
|
]);
|
|
|
|
|
|
|
|
const detector = new smartproxy.detection.TlsDetector();
|
|
|
|
expect(detector.canHandle(tlsHandshake)).toEqual(true);
|
|
|
|
|
|
|
|
const result = detector.detect(tlsHandshake);
|
|
|
|
expect(result).toBeDefined();
|
|
|
|
expect(result?.protocol).toEqual('tls');
|
|
|
|
expect(result?.connectionInfo.tlsVersion).toEqual('TLSv1.0');
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('Protocol Detection - HTTP Detection', async () => {
|
|
|
|
// Test HTTP request detection
|
|
|
|
const httpRequest = Buffer.from(
|
|
|
|
'GET /test HTTP/1.1\r\n' +
|
|
|
|
'Host: example.com\r\n' +
|
|
|
|
'User-Agent: TestClient/1.0\r\n' +
|
|
|
|
'\r\n'
|
|
|
|
);
|
|
|
|
|
|
|
|
const detector = new smartproxy.detection.HttpDetector();
|
|
|
|
expect(detector.canHandle(httpRequest)).toEqual(true);
|
|
|
|
|
|
|
|
const result = detector.detect(httpRequest);
|
|
|
|
expect(result).toBeDefined();
|
|
|
|
expect(result?.protocol).toEqual('http');
|
|
|
|
expect(result?.connectionInfo.method).toEqual('GET');
|
|
|
|
expect(result?.connectionInfo.path).toEqual('/test');
|
|
|
|
expect(result?.connectionInfo.domain).toEqual('example.com');
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('Protocol Detection - Main Detector TLS', async () => {
|
|
|
|
const tlsHandshake = Buffer.from([
|
|
|
|
0x16, // Handshake record type
|
|
|
|
0x03, 0x03, // TLS 1.2
|
|
|
|
0x00, 0x05, // Length: 5 bytes
|
|
|
|
0x01, // ClientHello
|
|
|
|
0x00, 0x00, 0x01, 0x00 // Handshake length and data
|
|
|
|
]);
|
|
|
|
|
|
|
|
const result = await smartproxy.detection.ProtocolDetector.detect(tlsHandshake);
|
|
|
|
expect(result.protocol).toEqual('tls');
|
|
|
|
expect(result.connectionInfo.tlsVersion).toEqual('TLSv1.2');
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('Protocol Detection - Main Detector HTTP', async () => {
|
|
|
|
const httpRequest = Buffer.from(
|
|
|
|
'POST /api/test HTTP/1.1\r\n' +
|
|
|
|
'Host: api.example.com\r\n' +
|
|
|
|
'Content-Type: application/json\r\n' +
|
|
|
|
'Content-Length: 2\r\n' +
|
|
|
|
'\r\n' +
|
|
|
|
'{}'
|
|
|
|
);
|
|
|
|
|
|
|
|
const result = await smartproxy.detection.ProtocolDetector.detect(httpRequest);
|
|
|
|
expect(result.protocol).toEqual('http');
|
|
|
|
expect(result.connectionInfo.method).toEqual('POST');
|
|
|
|
expect(result.connectionInfo.path).toEqual('/api/test');
|
|
|
|
expect(result.connectionInfo.domain).toEqual('api.example.com');
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('Protocol Detection - Unknown Protocol', async () => {
|
|
|
|
const unknownData = Buffer.from('UNKNOWN PROTOCOL DATA\r\n');
|
|
|
|
|
|
|
|
const result = await smartproxy.detection.ProtocolDetector.detect(unknownData);
|
|
|
|
expect(result.protocol).toEqual('unknown');
|
|
|
|
expect(result.isComplete).toEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('Protocol Detection - Fragmented HTTP', async () => {
|
2025-07-22 10:35:39 +00:00
|
|
|
// Create connection context
|
|
|
|
const context = smartproxy.detection.ProtocolDetector.createConnectionContext({
|
|
|
|
sourceIp: '127.0.0.1',
|
|
|
|
sourcePort: 12345,
|
|
|
|
destIp: '127.0.0.1',
|
|
|
|
destPort: 80,
|
|
|
|
socketId: 'test-connection-1'
|
|
|
|
});
|
2025-07-21 19:40:01 +00:00
|
|
|
|
|
|
|
// First fragment
|
|
|
|
const fragment1 = Buffer.from('GET /test HT');
|
2025-07-22 10:35:39 +00:00
|
|
|
let result = await smartproxy.detection.ProtocolDetector.detectWithContext(
|
2025-07-21 19:40:01 +00:00
|
|
|
fragment1,
|
2025-07-22 10:35:39 +00:00
|
|
|
context
|
2025-07-21 19:40:01 +00:00
|
|
|
);
|
|
|
|
expect(result.protocol).toEqual('http');
|
|
|
|
expect(result.isComplete).toEqual(false);
|
|
|
|
|
|
|
|
// Second fragment
|
|
|
|
const fragment2 = Buffer.from('TP/1.1\r\nHost: example.com\r\n\r\n');
|
2025-07-22 10:35:39 +00:00
|
|
|
result = await smartproxy.detection.ProtocolDetector.detectWithContext(
|
2025-07-21 19:40:01 +00:00
|
|
|
fragment2,
|
2025-07-22 10:35:39 +00:00
|
|
|
context
|
2025-07-21 19:40:01 +00:00
|
|
|
);
|
|
|
|
expect(result.protocol).toEqual('http');
|
|
|
|
expect(result.isComplete).toEqual(true);
|
|
|
|
expect(result.connectionInfo.method).toEqual('GET');
|
|
|
|
expect(result.connectionInfo.path).toEqual('/test');
|
|
|
|
expect(result.connectionInfo.domain).toEqual('example.com');
|
2025-07-22 10:35:39 +00:00
|
|
|
|
|
|
|
// Clean up fragments
|
|
|
|
smartproxy.detection.ProtocolDetector.cleanupConnection(context);
|
2025-07-21 19:40:01 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('Protocol Detection - HTTP Methods', async () => {
|
|
|
|
const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
|
|
|
|
|
|
|
|
for (const method of methods) {
|
|
|
|
const request = Buffer.from(
|
|
|
|
`${method} /test HTTP/1.1\r\n` +
|
|
|
|
'Host: example.com\r\n' +
|
|
|
|
'\r\n'
|
|
|
|
);
|
|
|
|
|
|
|
|
const detector = new smartproxy.detection.HttpDetector();
|
|
|
|
const result = detector.detect(request);
|
|
|
|
expect(result?.connectionInfo.method).toEqual(method);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('Protocol Detection - Invalid Data', async () => {
|
|
|
|
// Binary data that's not a valid protocol
|
|
|
|
const binaryData = Buffer.from([0xFF, 0xFE, 0xFD, 0xFC, 0xFB]);
|
|
|
|
|
|
|
|
const result = await smartproxy.detection.ProtocolDetector.detect(binaryData);
|
|
|
|
expect(result.protocol).toEqual('unknown');
|
|
|
|
});
|
|
|
|
|
2025-07-22 11:28:06 +00:00
|
|
|
tap.test('cleanup detection', async () => {
|
|
|
|
// Clean up the protocol detector instance
|
|
|
|
smartproxy.detection.ProtocolDetector.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
export default tap.start();
|