diff --git a/lib/services/protocol_blocking_service.dart b/lib/services/protocol_blocking_service.dart index 9f2bbd3..4eea534 100644 --- a/lib/services/protocol_blocking_service.dart +++ b/lib/services/protocol_blocking_service.dart @@ -104,11 +104,12 @@ class ProtocolBlockingService { static Future _startContinuousMonitoring() async { try { - print('🔄 Starting continuous packet monitoring...'); + print('🔄 Starting continuous PAYLOAD monitoring...'); _continuousMonitor = await Process.start('tcpdump', [ '-i', 'any', '-l', // Line buffered for real-time output - '-v', // Verbose + '-s', '0', // Capture full packet (unlimited snap length) + '-x', // Output in hex format for payload analysis // Only capture forwarded packets from VPN peers to internet 'src net 10.0.0.0/24 and not dst net 10.0.0.0/24', ]); @@ -137,40 +138,118 @@ class ProtocolBlockingService { } static Future _processCapturedPacket(String packetLine) async { - print('📦 DECRYPTED VPN TRAFFIC: $packetLine'); + // Skip timestamp/header lines, only process hex data lines + if (!packetLine.contains('0x') || packetLine.trim().isEmpty) { + return; + } - // Check if it's from our monitored peers and analyze + // Check if it's from our monitored peers and analyze payload for (final peerIP in _activePeerIPs) { if (packetLine.contains(peerIP)) { - print('🎯 PEER TRAFFIC FROM $peerIP: $packetLine'); - await _analyzePacketLine(packetLine, peerIP); + print('🎯 PEER TRAFFIC FROM $peerIP - ANALYZING PAYLOAD'); + await _analyzeFullPayload(packetLine, peerIP); break; } } } - static Future _analyzePacketLine(String packetLine, String peerIP) async { - // Simple protocol detection from packet line - String? protocol; + static Future _analyzeFullPayload(String hexPacketLine, String peerIP) async { + print('🔍 DEEP PAYLOAD ANALYSIS for peer $peerIP'); - if (packetLine.toLowerCase().contains('bittorrent') || - packetLine.contains(':6881') || packetLine.contains(':6882')) { - protocol = 'BitTorrent'; - } else if (packetLine.contains('.https:') || packetLine.contains(':443')) { - protocol = 'HTTPS'; - } else if (packetLine.contains('.http:') || packetLine.contains(':80')) { - protocol = 'HTTP'; - } else if (packetLine.contains('.ssh:') || packetLine.contains(':22')) { - protocol = 'SSH'; + // Extract hex bytes from tcpdump output + final hexBytes = _extractHexBytes(hexPacketLine); + + if (hexBytes.isEmpty) { + print('❌ No hex payload data found'); + return; } - if (protocol != null) { - print('🎯 PROTOCOL DETECTED: $protocol'); - if (['BitTorrent', 'P2P'].contains(protocol)) { - print('🚫 BLOCKING PROTOCOL: $protocol'); + 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]); + + if (result.exitCode == 0) { + final output = result.stdout.toString().trim(); + print('✅ nDPI DEEP ANALYSIS: $output'); + + // 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('✅ ALLOWING PROTOCOL: $protocol'); + print('⚠️ nDPI analyzer failed, using fallback payload analysis'); + await _fallbackPayloadAnalysis(hexBytes, peerIP); } + } catch (e) { + print('❌ Error running nDPI analyzer: $e'); + await _fallbackPayloadAnalysis(hexBytes, peerIP); + } + } + + static Future _fallbackPayloadAnalysis(List hexBytes, String peerIP) async { + print('🔍 FALLBACK: Manual payload signature detection'); + + // Convert hex to ASCII for pattern matching + final asciiData = _extractAsciiFromHex(hexBytes); + final hexString = hexBytes.join('').toLowerCase(); + + print('🔤 ASCII sample: ${asciiData.replaceAll(RegExp(r'[^\x20-\x7E]'), '.').substring(0, 100)}...'); + + String? detectedProtocol; + + // BitTorrent handshake signature: "BitTorrent protocol" (hex: 426974546f7272656e742070726f746f636f6c) + if (asciiData.contains('BitTorrent protocol') || + hexString.contains('13426974546f7272656e742070726f746f636f6c')) { + detectedProtocol = 'BitTorrent'; + print('🚨 BitTorrent handshake signature found in payload!'); + } + // SSH handshake + else if (asciiData.contains('SSH-2.0') || asciiData.contains('SSH-1.')) { + detectedProtocol = 'SSH'; + print('🔐 SSH handshake signature found in payload!'); + } + // HTTP signatures + else if (asciiData.contains('GET ') || asciiData.contains('POST ') || + asciiData.contains('HTTP/1.1') || asciiData.contains('HTTP/2')) { + detectedProtocol = 'HTTP'; + print('🌐 HTTP signature found in payload!'); + } + // TLS Client Hello (0x16 0x03 0x01/0x03) + else if (hexString.startsWith('16') && (hexString.startsWith('160301') || hexString.startsWith('160303'))) { + detectedProtocol = 'TLS'; + print('🔒 TLS handshake signature found in payload!'); + } + + if (detectedProtocol != null) { + print('🎯 PAYLOAD SIGNATURE DETECTED: $detectedProtocol'); + + if (['BitTorrent'].contains(detectedProtocol)) { + print('🚫 BLOCKING PAYLOAD-DETECTED PROTOCOL: $detectedProtocol'); + print('💡 This would be blocked regardless of port!'); + } else { + print('✅ ALLOWING PAYLOAD-DETECTED PROTOCOL: $detectedProtocol'); + } + } else { + print('❓ UNKNOWN PROTOCOL - No payload signatures matched'); + print('🔍 First 32 hex bytes: ${hexBytes.take(32).join(' ')}'); } }