Add nDPI protocol analyzer and integrate with handshake analysis
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user