diff --git a/lib/services/protocol_blocking_service.dart b/lib/services/protocol_blocking_service.dart index 9df0efb..7e366f0 100644 --- a/lib/services/protocol_blocking_service.dart +++ b/lib/services/protocol_blocking_service.dart @@ -177,53 +177,38 @@ class ProtocolBlockingService { } static Future _analyzeFullPayload(String hexPacketLine, String peerIP) async { - print('🔍 DEEP PAYLOAD ANALYSIS for peer $peerIP'); - // Extract hex bytes from tcpdump output final hexBytes = _extractHexBytes(hexPacketLine); if (hexBytes.isEmpty) { - print('❌ No hex payload data found'); return; } - print('📊 Analyzing ${hexBytes.length} bytes of raw packet data'); - - // Convert hex to single string for nDPI analyzer - final hexString = hexBytes.join(''); - - try { - // Use our nDPI analyzer for true protocol detection - final result = await Process.run('./protocol_analyzer', [hexString]); + // Check if this looks like a handshake (first packet of connection) + if (_isHandshakePacket(hexBytes)) { + print('🤝 HANDSHAKE DETECTED FROM $peerIP'); + print('📦 RAW HEX DATA:'); - if (result.exitCode == 0) { - final output = result.stdout.toString().trim(); - print('✅ nDPI DEEP ANALYSIS: $output'); + // Print hex data in readable format + for (int i = 0; i < hexBytes.length; i += 16) { + final chunk = hexBytes.skip(i).take(16); + final hexLine = chunk.map((h) => h.padLeft(2, '0')).join(' '); + final asciiLine = chunk.map((h) { + final byte = int.parse(h, radix: 16); + return (byte >= 32 && byte <= 126) ? String.fromCharCode(byte) : '.'; + }).join(); - // Parse protocol from nDPI output - final protocolMatch = RegExp(r'"protocol":\s*"([^"]+)"').firstMatch(output); - final categoryMatch = RegExp(r'"category":\s*"([^"]+)"').firstMatch(output); - - if (protocolMatch != null) { - final protocol = protocolMatch.group(1) ?? 'Unknown'; - final category = categoryMatch?.group(1) ?? 'Unknown'; - - print('🎯 PAYLOAD PROTOCOL: $protocol (Category: $category)'); - - if (_shouldBlockProtocol(protocol, category)) { - print('🚫 BLOCKING PAYLOAD-DETECTED PROTOCOL: $protocol'); - // TODO: Implement actual blocking - } else { - print('✅ ALLOWING PAYLOAD-DETECTED PROTOCOL: $protocol'); - } - } - } else { - print('⚠️ nDPI analyzer failed, using fallback payload analysis'); - await _fallbackPayloadAnalysis(hexBytes, peerIP); + print('${i.toString().padLeft(4, '0')}: ${hexLine.padRight(48)} |$asciiLine|'); } - } catch (e) { - print('❌ Error running nDPI analyzer: $e'); - await _fallbackPayloadAnalysis(hexBytes, peerIP); + + // Also show raw ASCII if readable + final asciiData = _extractAsciiFromHex(hexBytes); + final readableAscii = asciiData.replaceAll(RegExp(r'[^\x20-\x7E]'), '.'); + if (readableAscii.contains(RegExp(r'[a-zA-Z]'))) { + print('📝 ASCII: $readableAscii'); + } + + print('═══════════════════════════════════════'); } } @@ -773,6 +758,51 @@ class ProtocolBlockingService { return false; } + static bool _isHandshakePacket(List hexBytes) { + if (hexBytes.length < 20) return false; + + // Check for TCP SYN packet (handshake initiation) + if (hexBytes.length >= 34) { + // IP header is first 20 bytes, TCP header starts at byte 20 + // TCP flags are at offset 33 (13th byte of TCP header) + try { + final tcpFlags = int.parse(hexBytes[33], radix: 16); + // Check for SYN flag (0x02) - indicates handshake + if (tcpFlags & 0x02 != 0) { + return true; + } + } catch (e) { + // Ignore parsing errors + } + } + + // Check for common handshake patterns in payload + final asciiData = _extractAsciiFromHex(hexBytes); + + // BitTorrent handshake starts with 19 + "BitTorrent protocol" + if (hexBytes.length >= 20 && hexBytes[0] == '13') { + return true; + } + + // HTTP requests + if (asciiData.startsWith('GET ') || asciiData.startsWith('POST ') || + asciiData.startsWith('HEAD ') || asciiData.startsWith('PUT ')) { + return true; + } + + // TLS Client Hello + if (hexBytes.length >= 6 && hexBytes[0] == '16' && hexBytes[1] == '03') { + return true; + } + + // SSH handshake + if (asciiData.startsWith('SSH-')) { + return true; + } + + return false; + } + static List _extractHexBytes(String tcpdumpOutput) { final hexPattern = RegExp(r'0x[0-9a-f]+:\s*([0-9a-f\s]+)', caseSensitive: false); final matches = hexPattern.allMatches(tcpdumpOutput);