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'] ?? '');
|
||||
|
||||
// More flexible matching - try multiple approaches
|
||||
// Normalize all values for comparison
|
||||
$normalizedSourceIP = strtolower(trim($sourceIP));
|
||||
$normalizedDestIP = strtolower(trim($destIP));
|
||||
$normalizedStateSourceIP = strtolower(trim($stateSourceIP));
|
||||
$normalizedStateDestIP = strtolower(trim($stateDestIP));
|
||||
$normalizedProtocol = strtoupper(trim($protocol));
|
||||
|
||||
// Check if this state matches the log entry (more lenient matching)
|
||||
$sourceMatch = false;
|
||||
$reverseMatch = false;
|
||||
// Very flexible matching logic
|
||||
$ipMatch = false;
|
||||
|
||||
// Try exact match
|
||||
if ($normalizedStateSourceIP === $normalizedSourceIP && $normalizedStateDestIP === $normalizedDestIP) {
|
||||
$sourceMatch = true;
|
||||
} elseif ($normalizedStateSourceIP === $normalizedDestIP && $normalizedStateDestIP === $normalizedSourceIP) {
|
||||
$reverseMatch = true;
|
||||
// Check if IPs match in either direction
|
||||
if (($normalizedStateSourceIP === $normalizedSourceIP && $normalizedStateDestIP === $normalizedDestIP) ||
|
||||
($normalizedStateSourceIP === $normalizedDestIP && $normalizedStateDestIP === $normalizedSourceIP)) {
|
||||
$ipMatch = true;
|
||||
}
|
||||
|
||||
// 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;
|
||||
// Also try if one of the IPs matches (useful for single-sided matching)
|
||||
if (!$ipMatch && (
|
||||
$normalizedStateSourceIP === $normalizedSourceIP ||
|
||||
$normalizedStateSourceIP === $normalizedDestIP ||
|
||||
$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)
|
||||
$protocolMatch = true;
|
||||
if (!empty($protocol) && $protocol !== '-') {
|
||||
$protocolMatch = (strtoupper(trim($protocol)) === $stateProtocol);
|
||||
}
|
||||
// Protocol match
|
||||
$protocolMatch = (empty($protocol) || $protocol === '-' || $normalizedProtocol === $stateProtocol);
|
||||
|
||||
// Check port match - focus on destination port which is the service port
|
||||
// Source port is usually ephemeral and not relevant for matching
|
||||
$portMatch = true;
|
||||
if (!empty($destPort) && $destPort !== '-') {
|
||||
// Port match - check if destination port from log matches any port in state
|
||||
$portMatch = false;
|
||||
if (empty($destPort) || $destPort === '-') {
|
||||
$portMatch = true; // No port specified, match all
|
||||
} else {
|
||||
$destPortNum = (int)$destPort;
|
||||
// Match if either state's source or destination port equals the log's destination port
|
||||
// This handles bidirectional connections
|
||||
$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 ($stateDestPort === $destPortNum || $stateSourcePort === $destPortNum) {
|
||||
$portMatch = 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);
|
||||
$packets = (int)($state['packets_total'] ?? $state['packets'] ?? 0);
|
||||
$stateName = strtoupper($state['state'] ?? 'UNKNOWN');
|
||||
|
||||
Reference in New Issue
Block a user