Add nDPI protocol analyzer and integrate with handshake analysis

This commit is contained in:
ImBenji
2025-08-29 01:29:06 +01:00
parent 9e8432293e
commit 7f28184857
3 changed files with 207 additions and 39 deletions

View File

@@ -358,55 +358,84 @@ class ProtocolBlockingService {
}
}
static void _analyzeHandshake(String handshakeData, Connection conn) {
print('════════════════ HANDSHAKE SIGNATURE ANALYSIS ════════════════');
static Future<void> _analyzeHandshake(String handshakeData, Connection conn) async {
print('════════════════ nDPI PROTOCOL ANALYSIS ════════════════');
print('📍 Connection: $conn');
// Extract raw bytes from tcpdump hex output
// Extract hex bytes from tcpdump output
final hexBytes = _extractHexBytes(handshakeData);
final asciiData = _extractAsciiFromHex(hexBytes);
print('📊 Raw Data Length: ${handshakeData.length} chars');
print('🔢 Hex Bytes (first 64): ${hexBytes.take(64).join(' ')}');
print('📝 ASCII Representation: ${asciiData.replaceAll('\n', '\\n').replaceAll('\r', '\\r')}');
print('🔍 First 32 bytes as string: ${String.fromCharCodes(hexBytes.take(32).map((h) => int.tryParse(h, radix: 16) ?? 0).where((b) => b >= 32 && b <= 126))}');
// Protocol detection with signature details
final data = handshakeData.toLowerCase();
String? detectedProtocol;
String signature = '';
if (data.contains('bittorrent protocol') || hexBytes.join('').contains('13426974546f7272656e742070726f746f636f6c')) {
detectedProtocol = 'BitTorrent';
signature = 'BitTorrent handshake signature detected';
} else if (data.contains('ssh-2.0') || data.contains('ssh-1.')) {
detectedProtocol = 'SSH';
signature = 'SSH protocol version string';
} else if (data.contains('get ') || data.contains('post ') || data.contains('http/')) {
detectedProtocol = 'HTTP';
signature = 'HTTP request headers';
} else if (data.contains('220 ') && conn.remotePort == 25) {
detectedProtocol = 'SMTP';
signature = 'SMTP welcome message';
} else if (data.contains('220 ') && conn.remotePort == 21) {
detectedProtocol = 'FTP';
signature = 'FTP welcome message';
} else if (hexBytes.isNotEmpty && hexBytes.first == '16' && hexBytes.length > 5) {
// TLS detection
detectedProtocol = 'TLS/SSL';
signature = 'TLS ClientHello/ServerHello (0x16 record type)';
if (hexBytes.isEmpty) {
print('❌ No hex data found in tcpdump output');
print('══════════════════════════════════════════════════════════════');
return;
}
if (detectedProtocol != null) {
print('🎯 PROTOCOL IDENTIFIED: $detectedProtocol');
print('📋 Signature: $signature');
} else {
print('❓ UNKNOWN PROTOCOL');
print('💡 Pattern not recognized - logging for analysis');
// Convert hex bytes to single hex string for C analyzer
final hexString = hexBytes.join('');
print('🔢 Analyzing ${hexBytes.length} bytes of packet data');
try {
// Call our C nDPI analyzer
final result = await Process.run('./protocol_analyzer', [hexString]);
if (result.exitCode == 0) {
print('✅ nDPI Analysis Results:');
print(result.stdout.toString().trim());
// Parse JSON output to extract protocol info
try {
final jsonStr = result.stdout.toString().trim();
// Simple protocol extraction - look for protocol field
final protocolMatch = RegExp(r'"protocol":\s*"([^"]+)"').firstMatch(jsonStr);
final categoryMatch = RegExp(r'"category":\s*"([^"]+)"').firstMatch(jsonStr);
if (protocolMatch != null) {
final protocol = protocolMatch.group(1) ?? 'Unknown';
final category = categoryMatch?.group(1) ?? 'Unknown';
print('🎯 DETECTED: $protocol (Category: $category)');
// Check if this is a protocol we want to block
if (_shouldBlockProtocol(protocol, category)) {
print('🚫 BLOCKING PROTOCOL: $protocol');
// TODO: Implement blocking logic here
} else {
print('✅ ALLOWING PROTOCOL: $protocol');
}
}
} catch (e) {
print('⚠️ Error parsing nDPI results: $e');
}
} else {
print('❌ nDPI analyzer failed:');
print(' Exit code: ${result.exitCode}');
print(' Error: ${result.stderr}');
}
} catch (e) {
print('❌ Error running nDPI analyzer: $e');
}
print('══════════════════════════════════════════════════════════════');
}
static bool _shouldBlockProtocol(String protocol, String category) {
// Define protocols/categories to block
final blockedProtocols = {
'BitTorrent', 'uTorrent', 'Transmission', 'qBittorrent',
'eMule', 'KaZaA', 'Gnutella', 'DirectConnect',
'Skype_Call', // Block Skype calls but allow chat
};
final blockedCategories = {
'Download', 'P2P', 'FileSharing'
};
return blockedProtocols.contains(protocol) ||
blockedCategories.contains(category);
}
static List<String> _extractHexBytes(String tcpdumpOutput) {
final hexPattern = RegExp(r'0x[0-9a-f]+:\s*([0-9a-f\s]+)', caseSensitive: false);
final matches = hexPattern.allMatches(tcpdumpOutput);