# along with IPFire; if not, write to the Free Software #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
# #
-# Copyright (C) 2018 IPFire Team <info@ipfire.org>. #
+# Copyright (C) 2018-2019 IPFire Team <info@ipfire.org> #
# #
############################################################################
# File where the addresses of the homenet are stored.
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 which contains the enabled sids.
our $enabled_sids_file = "$settingsdir/oinkmaster-enabled-sids.conf";
# Check if an upstream proxy is configured.
if ($proxysettings{'UPSTREAM_PROXY'}) {
- my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
my $proxy_url;
- # Check if we got a peer.
- if ($peer) {
- $proxy_url = "http://";
-
- # Check if the proxy requires authentication.
- if (($proxysettings{'UPSTREAM_USER'}) && ($proxysettings{'UPSTREAM_PASSWORD'})) {
- $proxy_url .= "$proxysettings{'UPSTREAM_USER'}\:$proxysettings{'UPSTREAM_PASSWORD'}\@";
- }
-
- # Add proxy server address and port.
- $proxy_url .= "$peer\:$peerport";
- } else {
- # Log error message and break.
- &_log_to_syslog("Could not proper configure the proxy server access.");
+ $proxy_url = "http://";
- # Return "1" - false.
- return 1;
+ # Check if the proxy requires authentication.
+ if (($proxysettings{'UPSTREAM_USER'}) && ($proxysettings{'UPSTREAM_PASSWORD'})) {
+ $proxy_url .= "$proxysettings{'UPSTREAM_USER'}\:$proxysettings{'UPSTREAM_PASSWORD'}\@";
}
+ # Add proxy server address and port.
+ $proxy_url .= $proxysettings{'UPSTREAM_PROXY'};
+
# Setup proxy settings.
$downloader->proxy(['http', 'https'], $proxy_url);
}
# Load perl module to deal with temporary files.
use File::Temp;
- # Generate temporay file name, located in "/var/tmp" and with a suffix of ".tar.gz".
+ # Generate temporary file name, located in "/var/tmp" and with a suffix of ".tar.gz".
my $tmp = File::Temp->new( SUFFIX => ".tar.gz", DIR => "/var/tmp/", UNLINK => 0 );
my $tmpfile = $tmp->filename();
# Overwrite existing rules tarball with the new downloaded one.
move("$tmpfile", "$rulestarball");
+ # Set correct ownership for the rulesdir and files.
+ set_ownership("$rulestarball");
+
# If we got here, everything worked fine. Return nothing.
return;
}
# Skip element if it has config as file extension.
next if ($file =~ m/\.config$/);
+ # Skip rules file for whitelisted hosts.
+ next if ("$rulespath/$file" eq $whitelist_file);
+
# Delete the current processed file, if not, exit this function
# and return an error message.
unlink("$rulespath/$file") or return "Could not delete $rulespath/$file. $!\n";
close(FILE);
}
+#
+# Function to generate and write the file which contains the configured and used DNS servers.
+#
+sub generate_dns_servers_file() {
+ # Open file which contains the current used DNS configuration.
+ open (FILE, "${General::swroot}/red/dns") or die "Could not read DNS configuration from ${General::swroot}/red/dns. $!\n";
+
+ # Read-in whole file content and store it in a temporary array.
+ my @file_content = split(' ', <FILE>);
+
+ # Close file handle.
+ close(FILE);
+
+ # Format dns servers declaration.
+ my $line = "\"\[";
+
+ # Check if the current DNS configuration is using the local recursor mode.
+ if ($file_content[0] eq "local" && $file_content[1] eq "recursor") {
+ # The responsible DNS servers on red are directly used, and because we are not able
+ # to specify each single DNS server address here, we currently have to thread each
+ # address which is not part of the HOME_NET as possible DNS server.
+ $line = "$line" . "!\$HOME_NET";
+
+ } else {
+ # Loop through the array which contains the file content.
+ foreach my $server (@file_content) {
+ # Remove newlines.
+ chomp($server);
+
+ # Add the DNS server to the line.
+ $line = "$line" . "$server";
+
+ # Check if the current DNS server was the last in the array.
+ if ($server ne $file_content[-1]) {
+ # Add "," for the next DNS server.
+ $line = "$line" . "\,";
+ }
+ }
+ }
+
+ # Close the line...
+ $line = "$line" . "\]\"";
+
+ # Open file to store the used DNS server addresses.
+ open(FILE, ">$dns_servers_file") or die "Could not open $dns_servers_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 DNS declaration to the file.
+ print FILE "DNS_SERVERS:\t$line\n";
+
+ # Close file handle.
+ close(FILE);
+}
+
#
## Function to generate and write the file for used rulefiles.
#
#
## Function to generate and write the file for modify the ruleset.
#
-sub write_modify_sids_file($) {
- my ($ruleaction) = @_;
+sub write_modify_sids_file() {
+ # Get configured settings.
+ my %idssettings=();
+ my %rulessettings=();
+ &General::readhash("$ids_settings_file", \%idssettings);
+ &General::readhash("$rules_settings_file", \%rulessettings);
+
+ # Gather the configured ruleset.
+ my $ruleset = $rulessettings{'RULES'};
# Open modify sid's file for writing.
open(FILE, ">$modify_sids_file") or die "Could not write to $modify_sids_file. $!\n";
print FILE "#Autogenerated file. Any custom changes will be overwritten!\n";
# Check if the traffic only should be monitored.
- unless($ruleaction eq "alert") {
- # Tell oinkmaster to switch all rules from alert to drop.
- print FILE "modifysid \* \"alert\" \| \"drop\"\n";
+ unless($idssettings{'MONITOR_TRAFFIC_ONLY'} eq 'on') {
+ # Suricata is in IPS mode, which means that the rule actions have to be changed
+ # from 'alert' to 'drop', however not all rules should be changed. Some rules
+ # exist purely to set a flowbit which is used to convey other information, such
+ # as a specific type of file being downloaded, to other rulewhich then check for
+ # malware in that file. Rules which fall into the first category should stay as
+ # alert since not all flows of that type contain malware.
+
+ if($ruleset eq 'registered' or $ruleset eq 'subscripted' or $ruleset eq 'community') {
+ # These types of rulesfiles contain meta-data which gives the action that should
+ # be used when in IPS mode. Do the following:
+ #
+ # 1. Disable all rules and set the action to 'drop'
+ # 2. Set the action back to 'alert' if the rule contains 'flowbits:noalert;'
+ # This should give rules not in the policy a reasonable default if the user
+ # manually enables them.
+ # 3. Enable rules and set actions according to the meta-data strings.
+
+ my $policy = 'balanced'; # Placeholder to allow policy to be changed.
+
+ print FILE <<END;
+modifysid * "^#?(?:alert|drop)" | "#drop"
+modifysid * "^#drop(.+flowbits:noalert;)" | "#alert\${1}"
+modifysid * "^#(?:alert|drop)(.+policy $policy-ips alert)" | "alert\${1}"
+modifysid * "^#(?:alert|drop)(.+policy $policy-ips drop)" | "drop\${1}"
+END
+ } else {
+ # These rulefiles don't have the metadata, so set rules to 'drop' unless they
+ # contain the string 'flowbits:noalert;'.
+ print FILE <<END;
+modifysid * "^(#?)(?:alert|drop)" | "\${1}drop"
+modifysid * "^(#?)drop(.+flowbits:noalert;)" | "\${1}alert\${2}"
+END
+ }
}
# Close file handle.
# Remove newlines.
chomp($version_string);
- # Grab the version from the version string.
+ # Grab the version from the version string.
$version_string =~ /([0-9]+([.][0-9]+)+)/;
# Splitt the version into single chunks.
} else {
# Return the full version string.
return "$major_ver.$minor_ver.$patchlevel";
- }
+ }
}
#