feat: enhance firewall log matching logic with improved IP, protocol, and port checks for increased flexibility
This commit is contained in:
@@ -1671,60 +1671,66 @@ class Firewall extends Component
|
|||||||
|
|
||||||
$stateProtocol = strtoupper($state['protocol'] ?? '');
|
$stateProtocol = strtoupper($state['protocol'] ?? '');
|
||||||
|
|
||||||
// More flexible matching - try multiple approaches
|
// Normalize all values for comparison
|
||||||
$normalizedSourceIP = strtolower(trim($sourceIP));
|
$normalizedSourceIP = strtolower(trim($sourceIP));
|
||||||
$normalizedDestIP = strtolower(trim($destIP));
|
$normalizedDestIP = strtolower(trim($destIP));
|
||||||
$normalizedStateSourceIP = strtolower(trim($stateSourceIP));
|
$normalizedStateSourceIP = strtolower(trim($stateSourceIP));
|
||||||
$normalizedStateDestIP = strtolower(trim($stateDestIP));
|
$normalizedStateDestIP = strtolower(trim($stateDestIP));
|
||||||
|
$normalizedProtocol = strtoupper(trim($protocol));
|
||||||
|
|
||||||
// Check if this state matches the log entry (more lenient matching)
|
// Very flexible matching logic
|
||||||
$sourceMatch = false;
|
$ipMatch = false;
|
||||||
$reverseMatch = false;
|
|
||||||
|
|
||||||
// Try exact match
|
// Check if IPs match in either direction
|
||||||
if ($normalizedStateSourceIP === $normalizedSourceIP && $normalizedStateDestIP === $normalizedDestIP) {
|
if (($normalizedStateSourceIP === $normalizedSourceIP && $normalizedStateDestIP === $normalizedDestIP) ||
|
||||||
$sourceMatch = true;
|
($normalizedStateSourceIP === $normalizedDestIP && $normalizedStateDestIP === $normalizedSourceIP)) {
|
||||||
} elseif ($normalizedStateSourceIP === $normalizedDestIP && $normalizedStateDestIP === $normalizedSourceIP) {
|
$ipMatch = true;
|
||||||
$reverseMatch = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try partial match (contains) for cases where IP format differs
|
// Also try if one of the IPs matches (useful for single-sided matching)
|
||||||
if (!$sourceMatch && !$reverseMatch) {
|
if (!$ipMatch && (
|
||||||
if ((str_contains($normalizedStateSourceIP, $normalizedSourceIP) || str_contains($normalizedSourceIP, $normalizedStateSourceIP)) &&
|
$normalizedStateSourceIP === $normalizedSourceIP ||
|
||||||
(str_contains($normalizedStateDestIP, $normalizedDestIP) || str_contains($normalizedDestIP, $normalizedStateDestIP))) {
|
$normalizedStateSourceIP === $normalizedDestIP ||
|
||||||
$sourceMatch = true;
|
$normalizedStateDestIP === $normalizedSourceIP ||
|
||||||
|
$normalizedStateDestIP === $normalizedDestIP)) {
|
||||||
|
// At least one IP matches, check if the other makes sense
|
||||||
|
if ($normalizedStateSourceIP === $normalizedSourceIP || $normalizedStateDestIP === $normalizedSourceIP) {
|
||||||
|
if ($normalizedStateSourceIP === $normalizedDestIP || $normalizedStateDestIP === $normalizedDestIP) {
|
||||||
|
$ipMatch = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check protocol match (more lenient)
|
// Protocol match
|
||||||
$protocolMatch = true;
|
$protocolMatch = (empty($protocol) || $protocol === '-' || $normalizedProtocol === $stateProtocol);
|
||||||
if (!empty($protocol) && $protocol !== '-') {
|
|
||||||
$protocolMatch = (strtoupper(trim($protocol)) === $stateProtocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check port match - focus on destination port which is the service port
|
// Port match - check if destination port from log matches any port in state
|
||||||
// Source port is usually ephemeral and not relevant for matching
|
$portMatch = false;
|
||||||
$portMatch = true;
|
if (empty($destPort) || $destPort === '-') {
|
||||||
if (!empty($destPort) && $destPort !== '-') {
|
$portMatch = true; // No port specified, match all
|
||||||
|
} else {
|
||||||
$destPortNum = (int)$destPort;
|
$destPortNum = (int)$destPort;
|
||||||
// Match if either state's source or destination port equals the log's destination port
|
if ($stateDestPort === $destPortNum || $stateSourcePort === $destPortNum) {
|
||||||
// This handles bidirectional connections
|
$portMatch = true;
|
||||||
$portMatch = ($stateDestPort === $destPortNum || $stateSourcePort === $destPortNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Also consider matching without port if IPs and protocol match
|
|
||||||
// This is useful for firewall logs that don't include source port
|
|
||||||
$relaxedMatch = false;
|
|
||||||
if (!$sourceMatch && !$reverseMatch && empty($sourcePort)) {
|
|
||||||
// If no source port in log, be more lenient with matching
|
|
||||||
if (($normalizedStateSourceIP === $normalizedSourceIP || $normalizedStateDestIP === $normalizedSourceIP) &&
|
|
||||||
($normalizedStateSourceIP === $normalizedDestIP || $normalizedStateDestIP === $normalizedDestIP) &&
|
|
||||||
$protocolMatch && $portMatch) {
|
|
||||||
$relaxedMatch = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($sourceMatch || $reverseMatch || $relaxedMatch) && $protocolMatch && $portMatch) {
|
// Log first potential match for debugging
|
||||||
|
if ($ipMatch && $protocolMatch && $portMatch && count($matchingConnections) === 0) {
|
||||||
|
Log::info('First match found', [
|
||||||
|
'state_source' => $stateSourceIP,
|
||||||
|
'state_dest' => $stateDestIP,
|
||||||
|
'state_protocol' => $stateProtocol,
|
||||||
|
'state_src_port' => $stateSourcePort,
|
||||||
|
'state_dst_port' => $stateDestPort,
|
||||||
|
'log_source' => $sourceIP,
|
||||||
|
'log_dest' => $destIP,
|
||||||
|
'log_protocol' => $protocol,
|
||||||
|
'log_dest_port' => $destPort,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ipMatch && $protocolMatch && $portMatch) {
|
||||||
$bytes = (int)($state['bytes_total'] ?? $state['bytes'] ?? 0);
|
$bytes = (int)($state['bytes_total'] ?? $state['bytes'] ?? 0);
|
||||||
$packets = (int)($state['packets_total'] ?? $state['packets'] ?? 0);
|
$packets = (int)($state['packets_total'] ?? $state['packets'] ?? 0);
|
||||||
$stateName = strtoupper($state['state'] ?? 'UNKNOWN');
|
$stateName = strtoupper($state['state'] ?? 'UNKNOWN');
|
||||||
|
|||||||
Reference in New Issue
Block a user