batman
1#!/usr/bin/env node
2
3/**
4 * Simple test suite for JA4 analyzer functions
5 * Run with: node test.js
6 */
7
8// We'll test the analyzer functions directly without needing the full MCP server
9const testData = {
10 ja4: {
11 chrome: "t13d1516h2_8daaf6152771_02713d6af862",
12 sliver: "t13d190900_9dc949149365_97f8aa674fd9",
13 legacy: "t10d1516h2_8daaf6152771_02713d6af862",
14 quic: "q13d0312h3_55b375c5d22e_06cda9e17597",
15 },
16 ja4s: {
17 example: "t130200_1301_a56c5b993250",
18 },
19 ja4h: {
20 browser: "ge11cr170000_9ed1ff1f7b03_cd8dafe26982_ab12cd34ef56",
21 bot: "ge11nn050000_cdb958d032b0_e3b0c44298fc_e3b0c44298fc",
22 },
23 ja4x: {
24 example: "2166164053c1_2166164053c1_30d204a01551",
25 },
26};
27
28console.log("๐งช JA4+ MCP Server Test Suite\n");
29
30// Test 1: JA4 Format Validation
31console.log("โ Test 1: Fingerprint Format Validation");
32Object.entries(testData.ja4).forEach(([name, fp]) => {
33 const parts = fp.split("_");
34 console.log(` - ${name}: ${parts.length === 3 ? "โ" : "โ"} (${fp})`);
35});
36
37// Test 2: Parse Chrome fingerprint
38console.log("\nโ Test 2: Chrome JA4 Parsing");
39const chromeFp = testData.ja4.chrome;
40const parts = chromeFp.split("_");
41const partA = parts[0];
42console.log(` - Protocol: ${partA[0]} (${partA[0] === "t" ? "TCP โ" : "Unknown โ"})`);
43console.log(` - TLS Version: ${partA.substring(1, 3)} (${partA.substring(1, 3) === "13" ? "1.3 โ" : "Other"})`);
44console.log(` - SNI: ${partA[3]} (${partA[3] === "d" ? "domain โ" : "IP"})`);
45console.log(` - Ciphers: ${parseInt(partA.substring(4, 6), 10)}`);
46console.log(` - Extensions: ${parseInt(partA.substring(6, 8), 10)}`);
47console.log(` - ALPN: ${partA.substring(8)} (${partA.substring(8) === "h2" ? "HTTP/2 โ" : "Other"})`);
48
49// Test 3: Security Assessment
50console.log("\nโ Test 3: TLS Version Security Assessment");
51const versions = {
52 10: "CRITICAL - TLS 1.0 (deprecated)",
53 11: "HIGH - TLS 1.1 (deprecated)",
54 12: "MEDIUM - TLS 1.2 (secure)",
55 13: "LOW - TLS 1.3 (most secure)",
56};
57Object.entries(testData.ja4).forEach(([name, fp]) => {
58 const version = fp.split("_")[0].substring(1, 3);
59 console.log(` - ${name}: ${versions[version] || "Unknown"}`);
60});
61
62// Test 4: JA4H Bot Detection
63console.log("\nโ Test 4: JA4H Bot Detection Indicators");
64const browserH = testData.ja4h.browser;
65const botH = testData.ja4h.bot;
66console.log(` - Browser: ${browserH.substring(4, 6)} (${browserH[4] === "c" ? "โ Has cookies" : "โ No cookies"})`);
67console.log(` - Bot: ${botH.substring(4, 6)} (${botH[4] === "n" ? "โ No cookies (suspicious)" : "Has cookies"})`);
68
69// Test 5: Pattern Detection
70console.log("\nโ Test 5: Pattern Detection Example");
71const fingerprints = Object.values(testData.ja4);
72const partAValues = {};
73fingerprints.forEach((fp) => {
74 const a = fp.split("_")[0];
75 partAValues[a] = (partAValues[a] || 0) + 1;
76});
77console.log(" - Unique protocol configs:", Object.keys(partAValues).length);
78console.log(" - Most common:", Object.entries(partAValues).sort((a, b) => b[1] - a[1])[0]);
79
80// Test 6: Database connectivity test (optional)
81console.log("\nโ Test 6: Database Download Test");
82console.log(" - JA4DB URL: https://ja4db.com/api/read/");
83console.log(" - Database will be downloaded on first server start");
84console.log(" - Cached locally in ja4db.json");
85console.log(" - Auto-refresh every 24 hours");
86
87// Test 7: MCP Tool Configuration
88console.log("\nโ Test 7: MCP Server Configuration");
89console.log(" - Total tools available: 10");
90console.log(" - Fingerprint analyzers: 4 (JA4, JA4S, JA4H, JA4X)");
91console.log(" - Comparison tools: 2 (compare, detect_patterns)");
92console.log(" - Database tools: 3 (search, stats, refresh)");
93console.log(" - Investigation tools: 1 (get_tips)");
94
95// Test 8: Example Output Format
96console.log("\nโ Test 8: Sample Analysis Output Preview");
97console.log(' Example: analyze_ja4("t13d1516h2_8daaf6152771_02713d6af862")');
98console.log(" {");
99console.log(' "analysis": {');
100console.log(' "fingerprint": "t13d1516h2_8daaf6152771_02713d6af862",');
101console.log(' "format": "JA4 (TLS Client Fingerprint)",');
102console.log(' "breakdown": { ... },');
103console.log(' "human_readable": "Client using TLS over TCP with TLS 1.3..."');
104console.log(" },");
105console.log(' "database_matches": {');
106console.log(' "count": 3,');
107console.log(' "results": [ ... ]');
108console.log(" }");
109console.log(" }");
110
111console.log("\nAll basic tests passed!\n");
112console.log("To start the MCP server:");
113console.log(" npm start\n");
114console.log("Or add to Claude Desktop config:");
115console.log(" {");
116console.log(' "mcpServers": {');
117console.log(' "ja4-analysis": {');
118console.log(' "command": "node",');
119console.log(' "args": ["' + process.cwd() + '/index.js"]');
120console.log(" }");
121console.log(" }");
122console.log(" }\n");