From: ummeegge Date: Wed, 7 May 2025 05:48:38 +0000 (+0200) Subject: connections.cgi: Enhance with zone filter and search functionality X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fconnections;p=people%2Fummeegge%2Fipfire-2.x.git connections.cgi: Enhance with zone filter and search functionality Improved connections.cgi with the following features: - Added zone filter to select network zones (LAN, INTERNET, DMZ, etc.) via clickable legend. - Included NAT IPs in filtering for all zones. - Added search function to filter connections by IP, port, or protocol. With jQuery toggle on/off . - Display filter status showing active filters and connection count. FIXES/extensions: - Fix multi-pattern search to use AND logic - Corrected search filter to apply AND instead of OR for IP, port, and protocol criteria. - Added case-insensitive protocol matching and input sanitization for robustness. - Added ipcolour cache and pre-filtered networks. - Replaced external sort with Perl sorting for conntrack table. - Removed redundant close(CONNTRACK) call. Signed-off-by: ummeegge --- diff --git a/html/cgi-bin/connections.cgi b/html/cgi-bin/connections.cgi index b9473cceb5..4ae37d85d8 100644 --- a/html/cgi-bin/connections.cgi +++ b/html/cgi-bin/connections.cgi @@ -35,10 +35,11 @@ require "${General::swroot}/ids-functions.pl"; require "${General::swroot}/location-functions.pl"; my $colour_multicast = "#A0A0A0"; - my %settings = (); -&General::readhash("/var/ipfire/ethernet/settings", \%settings); +# Cache for ipcolour results to speed up lookups +my %ipcolour_cache = (); +&General::readhash("/var/ipfire/ethernet/settings", \%settings); &Header::showhttpheaders(); # Collect all known networks @@ -175,7 +176,7 @@ if (-e "${General::swroot}/ovpn/n2nconf") { # Pre-sort networks for faster lookup my @networks = reverse sort { &Network::get_prefix($a) <=> &Network::get_prefix($b) -} keys %networks; +} grep { defined($_) && &Network::check_subnet($_) } keys %networks; # Define zones and their corresponding colors my %zones = ( @@ -322,10 +323,17 @@ END # Read and sort the connection tracking table my $connection_count = 0; -open(CONNTRACK, "/usr/local/bin/getconntracktable | sort -k 5,5 --numeric-sort --reverse |") - or die "Unable to read conntrack table"; +my @conntrack_data = &General::system_output("/usr/local/bin/getconntracktable"); +if (!@conntrack_data) { + print "

$Lang::tr{'connections unable to read conntrack table'}

\n"; + &Header::closesection(); + &Header::closebigbox(); + &Header::closepage(); + exit; +} +my @sorted_conntrack = sort { (split(' ', $b))[4] <=> (split(' ', $a))[4] } @conntrack_data; -foreach my $line () { +foreach my $line (@sorted_conntrack) { my @conn = split(' ', $line); # The first bit is the l3 protocol. @@ -449,7 +457,8 @@ foreach my $line () { # Apply search filter if ($search_enabled && ($search_ip || $search_port || $search_protocol)) { my $matches_search = 1; - if ($search_ip) { + + if ($search_ip && $matches_search) { $matches_search = 0; if (($sip && $sip =~ /\Q$search_ip\E/i) || ($sip_ret && $sip_ret =~ /\Q$search_ip\E/i) || @@ -458,7 +467,8 @@ foreach my $line () { $matches_search = 1; } } - if ($search_port) { + + if ($search_port && $matches_search) { $matches_search = 0; if (($sport && $sport eq $search_port) || ($sport_ret && $sport_ret eq $search_port) || @@ -467,12 +477,14 @@ foreach my $line () { $matches_search = 1; } } - if ($search_protocol) { + + if ($search_protocol && $matches_search) { $matches_search = 0; if (lc($l4proto) eq lc($search_protocol)) { $matches_search = 1; } } + next unless $matches_search; } @@ -588,8 +600,6 @@ END $connection_count++; } -close(CONNTRACK); - # Print filter status if (@selected_zones || $search_enabled) { my @filter_parts; @@ -629,22 +639,21 @@ print ""; sub ipcolour($) { my $address = shift; - # Sort all networks so we find the best match - my @networks = reverse sort { - &Network::get_prefix($a) <=> &Network::get_prefix($b) - } keys %networks; + # Check cache first + if (exists $ipcolour_cache{$address}) { + return $ipcolour_cache{$address}; + } + # Use pre-sorted and filtered networks foreach my $network (@networks) { - if (defined $network) { - if (&Network::check_subnet($network)) { - if (&Network::ip_address_in_network($address, $network)) { - return $networks{$network}; - } - } + if (&Network::ip_address_in_network($address, $network)) { + $ipcolour_cache{$address} = $networks{$network}; + return $networks{$network}; } } # If we don't know the network, the address must be from the RED network + $ipcolour_cache{$address} = ${Header::colourred}; return ${Header::colourred}; }