IDS: Dynamically generate and import the HTTP ports.

Message ID 20200403142501.8604-1-stefan.schantl@ipfire.org
State Accepted
Commit e698090e7f696923ff146b272b587a3eeca34c6c
Headers
Series IDS: Dynamically generate and import the HTTP ports. |

Commit Message

Stefan Schantl April 3, 2020, 2:25 p.m. UTC
  With this commit suricata reads the HTTP port declarations from a newly
introduced external file
(/var/ipfire/suricata/suricata-http-ports.yaml).

This file dynamically will be generated. HTTP ports always are the
default port "80" and "81" for update Accelerator and HTTP access to the
WUI. In case the Web-proxy is used, the configured proxy port and/or Transparent
Proxy port also will be declared as a HTTP port and written to that file.

In case one of the proxy ports will be changed, the HTTP port file will
be re-generated and suricate restarted if launched. Also if an old
backup with snort will be restored the convert script handles the
generation of the HTTP ports file.

Finally the suricata-generate-http-ports-file as a tiny script which
simply generates the http ports file and needs to be launched during the
installation of a core update. (The script will no be required
anymore, so it could be deleted afterwards.)

Fixes #12308.

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
---
 config/cfgroot/ids-functions.pl               | 51 +++++++++++++++++++
 config/suricata/convert-snort                 | 18 +++++--
 .../suricata-generate-http-ports-file         | 47 +++++++++++++++++
 config/suricata/suricata.yaml                 |  4 +-
 html/cgi-bin/ids.cgi                          |  5 +-
 html/cgi-bin/proxy.cgi                        | 36 ++++++++++++-
 6 files changed, 154 insertions(+), 7 deletions(-)
 create mode 100644 config/suricata/suricata-generate-http-ports-file
  

Patch

diff --git a/config/cfgroot/ids-functions.pl b/config/cfgroot/ids-functions.pl
index af8a927e0..5bc3e77ec 100644
--- a/config/cfgroot/ids-functions.pl
+++ b/config/cfgroot/ids-functions.pl
@@ -37,6 +37,9 @@  our $homenet_file = "$settingsdir/suricata-homenet.yaml";
 # File where the addresses of the used DNS servers are stored.
 our $dns_servers_file = "$settingsdir/suricata-dns-servers.yaml";
 
+# File where the HTTP ports definition is stored.
+our $http_ports_file = "$settingsdir/suricata-http-ports.yaml";
+
 # File which contains the enabled sids.
 our $enabled_sids_file = "$settingsdir/oinkmaster-enabled-sids.conf";
 
@@ -89,6 +92,10 @@  my @suricatactrl_cmds = ( 'start', 'stop', 'restart', 'reload', 'fix-rules-dir',
 # Array with supported cron intervals.
 my @cron_intervals = ('off', 'daily', 'weekly' );
 
+# Array which contains the HTTP ports, which statically will be declared as HTTP_PORTS in the
+# http_ports_file.
+my @http_ports = ('80', '81');
+
 #
 ## Function to check and create all IDS related files, if the does not exist.
 #
@@ -738,6 +745,50 @@  sub generate_dns_servers_file() {
 	close(FILE);
 }
 
+#
+# Function to generate and write the file which contains the HTTP_PORTS definition.
+#
+sub generate_http_ports_file() {
+	my %proxysettings;
+
+	# Read-in proxy settings
+	&General::readhash("${General::swroot}/proxy/advanced/settings", \%proxysettings);
+
+	# Check if the proxy is enabled.
+	if (( -e "${General::swroot}/proxy/enable") || (-e "${General::swroot}/proxy/enable_blue")) {
+		# Add the proxy port to the array of HTTP ports.
+		push(@http_ports, $proxysettings{'PROXY_PORT'});
+	}
+
+	# Check if the transparent mode of the proxy is enabled.
+	if ((-e "${General::swroot}/proxy/transparent") || (-e "${General::swroot}/proxy/transparent_blue")) {
+		# Add the transparent proxy port to the array of HTTP ports.
+		push(@http_ports, $proxysettings{'TRANSPARENT_PORT'});
+	}
+
+	# Format HTTP_PORTS declaration.
+	my $line = "";
+
+	# Generate line which will be written to the http ports file.
+	$line = join(",", @http_ports);
+
+	# Open file to store the HTTP_PORTS.
+	open(FILE, ">$http_ports_file") or die "Could not open $http_ports_file. $!\n";
+
+	# Print yaml header.
+	print FILE "%YAML 1.1\n";
+	print FILE "---\n\n";
+
+	# Print notice about autogenerated file.
+	print FILE "#Autogenerated file. Any custom changes will be overwritten!\n";
+
+	# Print the generated HTTP_PORTS declaration to the file.
+	print FILE "HTTP_PORTS:\t\"[$line]\"\n";
+
+	# Close file handle.
+	close(FILE);
+}
+
 #
 ## Function to generate and write the file for used rulefiles.
 #
diff --git a/config/suricata/convert-snort b/config/suricata/convert-snort
index ee52548e9..3e938137e 100644
--- a/config/suricata/convert-snort
+++ b/config/suricata/convert-snort
@@ -2,7 +2,7 @@ 
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2019 IPFire Development Team <info@ipfire.org>                #
+# Copyright (C) 2020 IPFire Development Team <info@ipfire.org>                #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
@@ -298,7 +298,17 @@  if (-f $IDS::rulestarball) {
 &IDS::set_ownership("$IDS::dns_servers_file");
 
 #
-## Step 11: Setup automatic ruleset updates.
+## Step 11: Generate file which contains the HTTP ports.
+#
+
+# Call subfunction to generate the file.
+&IDS::generate_http_ports_file();
+
+# Set correct ownership for the http_ports_file.
+&IDS::set_ownership("$IDS::http_ports_file");
+
+#
+## Step 12: Setup automatic ruleset updates.
 #
 
 # Check if a ruleset is configured.
@@ -308,7 +318,7 @@  if($rulessettings{"RULES"}) {
 }
 
 #
-## Step 12: Grab used ruleset files from snort config file and convert
+## Step 13: Grab used ruleset files from snort config file and convert
 ##         them into the new format.
 #
 
@@ -354,7 +364,7 @@  close(SNORTCONF);
 &IDS::write_used_rulefiles_file(@enabled_rule_files);
 
 #
-## Step 13: Start the IDS if enabled.
+## Step 14: Start the IDS if enabled.
 #
 
 # Check if the IDS should be started.
diff --git a/config/suricata/suricata-generate-http-ports-file b/config/suricata/suricata-generate-http-ports-file
new file mode 100644
index 000000000..f0d6bb823
--- /dev/null
+++ b/config/suricata/suricata-generate-http-ports-file
@@ -0,0 +1,47 @@ 
+#!/usr/bin/perl
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2012 IPFire Development Team <info@ipfire.org>                #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+use strict;
+
+require '/var/ipfire/general-functions.pl';
+require "${General::swroot}/ids-functions.pl";
+
+exit unless(-f $IDS::ids_settings_file and -f $IDS::rules_settings_file);
+
+#
+## Step 1: Generate and write the HTTP ports file.
+#
+
+# Call subfunction to generate the HTTP ports file.
+&IDS::generate_http_ports_file();
+
+# Set correct ownership.
+&IDS::set_ownership("$IDS::http_ports_file");
+
+#
+## Step 2: Restart suricata if necessary.
+#
+
+# Check if the IDS should be started.
+if(&IDS::ids_is_running()) {
+	# Call suricatactrl and reload the rules.
+	&IDS::call_suricatactrl("restart");
+}
diff --git a/config/suricata/suricata.yaml b/config/suricata/suricata.yaml
index 54016a887..973b2686c 100644
--- a/config/suricata/suricata.yaml
+++ b/config/suricata/suricata.yaml
@@ -30,7 +30,9 @@  vars:
     ENIP_SERVER: "$HOME_NET"
 
   port-groups:
-    HTTP_PORTS: "[80,81]"
+    # Incluse HTTP_PORTS declaration from external file.
+    include: /var/ipfire/suricata/suricata-http-ports.yaml
+
     SHELLCODE_PORTS: "!80"
     ORACLE_PORTS: 1521
     SSH_PORTS: "[22,222]"
diff --git a/html/cgi-bin/ids.cgi b/html/cgi-bin/ids.cgi
index c3e5eefdb..df7138e08 100644
--- a/html/cgi-bin/ids.cgi
+++ b/html/cgi-bin/ids.cgi
@@ -2,7 +2,7 @@ 
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2007-2018  IPFire Team  <info@ipfire.org>                     #
+# Copyright (C) 2007-2020  IPFire Team  <info@ipfire.org>                     #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
@@ -625,6 +625,9 @@  if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) {
 	# Generate file to the store the DNS servers.
 	&IDS::generate_dns_servers_file();
 
+	# Generate file to store the HTTP ports.
+	&IDS::generate_http_ports_file();
+
 	# Write the modify sid's file and pass the taken ruleaction.
 	&IDS::write_modify_sids_file();
 
diff --git a/html/cgi-bin/proxy.cgi b/html/cgi-bin/proxy.cgi
index 06aca579b..73646a5ae 100644
--- a/html/cgi-bin/proxy.cgi
+++ b/html/cgi-bin/proxy.cgi
@@ -2,7 +2,7 @@ 
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2007-2013  IPFire Team  <info@ipfire.org>                     #
+# Copyright (C) 2007-2020  IPFire Team  <info@ipfire.org>                     #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
@@ -37,6 +37,8 @@  require '/var/ipfire/general-functions.pl';
 require "${General::swroot}/lang.pl";
 require "${General::swroot}/header.pl";
 
+require "${General::swroot}/ids-functions.pl";
+
 my @squidversion = `/usr/sbin/squid -v`;
 my $http_port='81';
 my $https_port='444';
@@ -550,6 +552,29 @@  ERROR:
 
 	if ($proxysettings{'VALID'} eq 'yes')
 	{
+		# Determine if suricata may needs to be restarted.
+		my $suricata_proxy_ports_changed;
+
+		# Check if the IDS is running
+		if(&IDS::ids_is_running()) {
+			my %oldproxysettings;
+
+			# Read-in current proxy settings and store them as oldsettings hash.
+			&General::readhash("${General::swroot}/proxy/advanced/settings", \%oldproxysettings);
+
+			# Check if the proxy port has been changed.
+			unless ($proxysettings{'PROXY_PORT'} eq $oldproxysettings{'PROXY_PORT'}) {
+				# Port has changed, suricata needs to be adjusted.
+				$suricata_proxy_ports_changed = 1;
+			}
+
+			# Check if the transparent port has been changed.
+			unless ($proxysettings{'TRANSPARENT_PORT'} eq $oldproxysettings{'TRANSPARENT_PORT'}) {
+				# Transparent port has changed, suricata needs to be adjusted.
+				$suricata_proxy_ports_changed = 1;
+			}
+		}
+
 		&write_acls;
 
 		delete $proxysettings{'SRC_SUBNETS'};
@@ -627,6 +652,15 @@  ERROR:
 
 		if ($proxysettings{'ACTION'} eq $Lang::tr{'advproxy save and restart'}) { system('/usr/local/bin/squidctrl restart >/dev/null 2>&1'); }
 		if ($proxysettings{'ACTION'} eq $Lang::tr{'proxy reconfigure'}) { system('/usr/local/bin/squidctrl reconfigure >/dev/null 2>&1'); }
+
+		# Check if the suricata_proxy_ports_changed flag has been set.
+		if ($suricata_proxy_ports_changed) {
+			# Re-generate HTTP ports file.
+			&IDS::generate_http_ports_file();
+
+			# Restart suricata.
+			&IDS::call_suricatactrl("restart");
+		}
   }
 }