]> git.ipfire.org Git - people/ummeegge/ipfire-2.x.git/commitdiff
connections.cgi: Enhance with zone filter and search functionality connections
authorummeegge <ummeegge@ipfire.org>
Wed, 7 May 2025 05:48:38 +0000 (07:48 +0200)
committerummeegge <ummeegge@ipfire.org>
Wed, 7 May 2025 05:48:38 +0000 (07:48 +0200)
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 <ummeegge@ipfire.org>
html/cgi-bin/connections.cgi

index b9473cceb50e3d5f8490d6257041fb4722f4b33d..4ae37d85d8357e966c95332ed78a77ad42d2539e 100644 (file)
@@ -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 "<p><b>$Lang::tr{'connections unable to read conntrack table'}</b></p>\n";
+       &Header::closesection();
+       &Header::closebigbox();
+       &Header::closepage();
+       exit;
+}
+my @sorted_conntrack = sort { (split(' ', $b))[4] <=> (split(' ', $a))[4] } @conntrack_data;
 
-foreach my $line (<CONNTRACK>) {
+foreach my $line (@sorted_conntrack) {
        my @conn = split(' ', $line);
 
        # The first bit is the l3 protocol.
@@ -449,7 +457,8 @@ foreach my $line (<CONNTRACK>) {
        # 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 (<CONNTRACK>) {
                                $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 (<CONNTRACK>) {
                                $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 "</table>";
 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};
 }