Simplify to detect and print handshake packet contents
- Detect TCP SYN packets and protocol-specific handshakes - Print raw hex data in readable hex dump format with ASCII - Show actual packet contents for signature analysis
This commit is contained in:
@@ -177,53 +177,38 @@ class ProtocolBlockingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> _analyzeFullPayload(String hexPacketLine, String peerIP) async {
|
static Future<void> _analyzeFullPayload(String hexPacketLine, String peerIP) async {
|
||||||
print('🔍 DEEP PAYLOAD ANALYSIS for peer $peerIP');
|
|
||||||
|
|
||||||
// Extract hex bytes from tcpdump output
|
// Extract hex bytes from tcpdump output
|
||||||
final hexBytes = _extractHexBytes(hexPacketLine);
|
final hexBytes = _extractHexBytes(hexPacketLine);
|
||||||
|
|
||||||
if (hexBytes.isEmpty) {
|
if (hexBytes.isEmpty) {
|
||||||
print('❌ No hex payload data found');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
print('📊 Analyzing ${hexBytes.length} bytes of raw packet data');
|
// Check if this looks like a handshake (first packet of connection)
|
||||||
|
if (_isHandshakePacket(hexBytes)) {
|
||||||
|
print('🤝 HANDSHAKE DETECTED FROM $peerIP');
|
||||||
|
print('📦 RAW HEX DATA:');
|
||||||
|
|
||||||
// Convert hex to single string for nDPI analyzer
|
// Print hex data in readable format
|
||||||
final hexString = hexBytes.join('');
|
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();
|
||||||
|
|
||||||
try {
|
print('${i.toString().padLeft(4, '0')}: ${hexLine.padRight(48)} |$asciiLine|');
|
||||||
// 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');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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');
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
print('⚠️ nDPI analyzer failed, using fallback payload analysis');
|
print('═══════════════════════════════════════');
|
||||||
await _fallbackPayloadAnalysis(hexBytes, peerIP);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
print('❌ Error running nDPI analyzer: $e');
|
|
||||||
await _fallbackPayloadAnalysis(hexBytes, peerIP);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,6 +758,51 @@ class ProtocolBlockingService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _isHandshakePacket(List<String> 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<String> _extractHexBytes(String tcpdumpOutput) {
|
static List<String> _extractHexBytes(String tcpdumpOutput) {
|
||||||
final hexPattern = RegExp(r'0x[0-9a-f]+:\s*([0-9a-f\s]+)', caseSensitive: false);
|
final hexPattern = RegExp(r'0x[0-9a-f]+:\s*([0-9a-f\s]+)', caseSensitive: false);
|
||||||
final matches = hexPattern.allMatches(tcpdumpOutput);
|
final matches = hexPattern.allMatches(tcpdumpOutput);
|
||||||
|
|||||||
Reference in New Issue
Block a user