From 3db1a4c19303936a4100a46a39926a52e77dab31 Mon Sep 17 00:00:00 2001 From: "Joseph.Rawlings" Date: Thu, 4 Dec 2025 22:32:33 -0500 Subject: [PATCH] feat: enhance network analysis with improved matching logic and detailed logging --- .../Servers/Proxmox/Livewire/Firewall.php | 73 +++++++++++++++---- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/extensions/Servers/Proxmox/Livewire/Firewall.php b/extensions/Servers/Proxmox/Livewire/Firewall.php index 2d864b808..2fab9c37b 100644 --- a/extensions/Servers/Proxmox/Livewire/Firewall.php +++ b/extensions/Servers/Proxmox/Livewire/Firewall.php @@ -1621,8 +1621,19 @@ class Firewall extends Component // Fetch all firewall states $allStates = $client->listStates(); + // Log the search parameters for debugging + Log::info('Searching for network analysis match', [ + 'sourceIP' => $sourceIP, + 'destIP' => $destIP, + 'sourcePort' => $sourcePort, + 'destPort' => $destPort, + 'protocol' => $protocol, + 'total_states' => count($allStates) + ]); + // Filter states matching the log entry $matchingConnections = []; + $debugSamples = []; foreach ($allStates as $state) { $rawSource = (string)($state['source'] ?? ''); @@ -1632,6 +1643,16 @@ class Firewall extends Component $stateSourceIP = $this->extractIpFromField($rawSource); $stateDestIP = $this->extractIpFromField($rawDestination); + // Store first 5 for debugging + if (count($debugSamples) < 5) { + $debugSamples[] = [ + 'raw_source' => $rawSource, + 'raw_destination' => $rawDestination, + 'extracted_source' => $stateSourceIP, + 'extracted_dest' => $stateDestIP, + ]; + } + // Extract ports $stateSourcePort = null; $stateDestPort = null; @@ -1650,26 +1671,42 @@ class Firewall extends Component $stateProtocol = strtoupper($state['protocol'] ?? ''); - // Check if this state matches the log entry - // Match can be source->dest or dest->source (bidirectional) - $sourceMatch = ( - strtolower(trim($stateSourceIP)) === strtolower(trim($sourceIP)) && - strtolower(trim($stateDestIP)) === strtolower(trim($destIP)) - ); + // More flexible matching - try multiple approaches + $normalizedSourceIP = strtolower(trim($sourceIP)); + $normalizedDestIP = strtolower(trim($destIP)); + $normalizedStateSourceIP = strtolower(trim($stateSourceIP)); + $normalizedStateDestIP = strtolower(trim($stateDestIP)); - $reverseMatch = ( - strtolower(trim($stateSourceIP)) === strtolower(trim($destIP)) && - strtolower(trim($stateDestIP)) === strtolower(trim($sourceIP)) - ); + // Check if this state matches the log entry (more lenient matching) + $sourceMatch = false; + $reverseMatch = false; - // Check protocol match - $protocolMatch = empty($protocol) || - strtoupper(trim($protocol)) === $stateProtocol; + // Try exact match + if ($normalizedStateSourceIP === $normalizedSourceIP && $normalizedStateDestIP === $normalizedDestIP) { + $sourceMatch = true; + } elseif ($normalizedStateSourceIP === $normalizedDestIP && $normalizedStateDestIP === $normalizedSourceIP) { + $reverseMatch = true; + } - // Check port match (if specified in log) + // Try partial match (contains) for cases where IP format differs + if (!$sourceMatch && !$reverseMatch) { + if ((str_contains($normalizedStateSourceIP, $normalizedSourceIP) || str_contains($normalizedSourceIP, $normalizedStateSourceIP)) && + (str_contains($normalizedStateDestIP, $normalizedDestIP) || str_contains($normalizedDestIP, $normalizedStateDestIP))) { + $sourceMatch = true; + } + } + + // Check protocol match (more lenient) + $protocolMatch = true; + if (!empty($protocol) && $protocol !== '-') { + $protocolMatch = (strtoupper(trim($protocol)) === $stateProtocol); + } + + // Check port match (more lenient - check if either port matches) $portMatch = true; if (!empty($destPort) && $destPort !== '-') { - $portMatch = ($stateDestPort == $destPort) || ($stateSourcePort == $destPort); + $destPortNum = (int)$destPort; + $portMatch = ($stateDestPort === $destPortNum || $stateSourcePort === $destPortNum); } if (($sourceMatch || $reverseMatch) && $protocolMatch && $portMatch) { @@ -1697,6 +1734,12 @@ class Firewall extends Component } } + // Log results for debugging + Log::info('Network analysis match results', [ + 'matches_found' => count($matchingConnections), + 'debug_samples' => $debugSamples + ]); + // Sort by bytes (highest first) usort($matchingConnections, fn($a, $b) => $b['bytes'] <=> $a['bytes']);