]> git.ipfire.org Git - ipfire-2.x.git/blame - config/suricata/convert-snort
IDS: Dynamically generate and import the HTTP ports.
[ipfire-2.x.git] / config / suricata / convert-snort
CommitLineData
5b0b4182
SS
1#!/usr/bin/perl
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
e698090e 5# Copyright (C) 2020 IPFire Development Team <info@ipfire.org> #
5b0b4182
SS
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
22use strict;
23
24require '/var/ipfire/general-functions.pl';
25require "${General::swroot}/ids-functions.pl";
26
27# Snort settings file, which contains the settings from the WUI.
28my $snort_settings_file = "${General::swroot}/snort/settings";
29
30# Main snort config file.
31my $snort_config_file = "/etc/snort/snort.conf";
32
33# Snort rules tarball.
34my $snort_rules_tarball = "/var/tmp/snortrules.tar.gz";
35
5b0b4182 36#
cde7cab2
SS
37## Step 1: Convert snort user and group to suricata if exist.
38#
39
40# Check if the snort user exists.
41if (getpwnam("snort")) {
42 # Change username.
43 my @command = (
44 '/usr/sbin/usermod',
45 '-l', 'suricata', 'snort'
46 );
47
48 system(@command) == 0 or die "Could not change username: @command failed: $?\n";
49
50 # Adjust home directory.
51 @command = (
52 '/usr/sbin/usermod',
53 '-d', "/var/log/suricata",
54 'suricata'
55 );
56
57 system(@command) == 0 or die "Failed to adjust home directory: @command failed: $?\n";
58}
59
60# Check if the snort group exists.
61if (getgrnam("snort")) {
62 # Change groupname
63 my @command = (
64 '/usr/sbin/groupmod',
65 '-n', 'suricata', 'snort'
66 );
67
68 system(@command) == 0 or die "Could not rename groupname: @command failed: $?\n";
69}
70
71#
72## Step 2: Setup directory and file layout, if not present and set correct
5b0b4182
SS
73## ownership. The converter runs as a privileged user, but the files
74## needs to be full access-able by the WUI user and group (nobody:nobody).
75#
76
5b0b4182
SS
77# Check if the settings directory exists.
78unless (-d $IDS::settingsdir) {
79 # Create the directory.
80 mkdir($IDS::settingsdir);
81}
82
83# Check if the rules directory exists.
84unless (-d $IDS::rulespath) {
85 # Create the directory.
86 mkdir($IDS::rulespath);
87}
88
5b0b4182
SS
89# Create file layout, if not exists yet.
90&IDS::check_and_create_filelayout();
91
36e69d34
SS
92# Set correct ownership for settingsdir and rulespath.
93&IDS::set_ownership("$IDS::settingsdir");
94&IDS::set_ownership("$IDS::rulespath");
5b0b4182 95
78690361
SS
96# Check if a snort settings file exists.
97unless( -f "$snort_settings_file") {
98 print "$snort_settings_file not found - Nothing to do. Exiting!\n";
99 exit(0);
100}
101
102# Check if the snort settings file is empty.
103if (-z "$snort_settings_file") {
104 print "$snort_settings_file is empty - Nothing to do. Exiting!\n";
105 exit(0);
106}
107
5b0b4182 108#
cde7cab2 109## Step 3: Import snort settings and convert to the required format for the new IDS
5b0b4182
SS
110## (suricata).
111#
112
113# Hash which contains the "old" snort settings.
114my %snortsettings;
115
116# Hash which contains the IDS (suricata) settings.
117#
118# Add default value for MONITOR_TRAFFIC_ONLY which will be "on"
119# when migrating from snort to the new IDS.
120my %idssettings = (
121 "MONITOR_TRAFFIC_ONLY" => "on",
122);
123
124# Hash which contains the RULES settings.
125#
126# Set default value for UPDATE_INTERVAL to weekly.
127my %rulessettings = (
128 "AUTOUPDATE_INTERVAL" => "weekly",
129);
130
131# Get all available network zones.
132my @network_zones = &IDS::get_available_network_zones();
133
134# Read-in snort settings file.
135&General::readhash("$snort_settings_file", \%snortsettings);
136
137# Loop through the array of network zones.
138foreach my $zone (@network_zones) {
139 # Convert current zone into upper case.
140 my $zone_upper = uc($zone);
141
142 # Check if the current network zone is "red".
143 if($zone eq "red") {
144 # Check if snort was enabled and enabled on red.
145 if ($snortsettings{"ENABLE_SNORT"} eq "on") {
146 # Enable the IDS.
147 $idssettings{"ENABLE_IDS"} = "on";
148
149 # Enable the IDS on RED.
150 $idssettings{"ENABLE_IDS_$zone_upper"} = "on";
151 }
152 } else {
153 # Check if snort was enabled on the current zone.
154 if ($snortsettings{"ENABLE_SNORT_$zone_upper"} eq "on") {
155 # Enable the IDS on this zone too.
156 $idssettings{"ENABLE_IDS_$zone_upper"} = "on";
157 }
158 }
159}
160
161# Grab the choosen ruleset from snort settings hash and store it in the rules
162# settings hash.
163$rulessettings{"RULES"} = $snortsettings{"RULES"};
164
165# Check if an oinkcode has been provided.
166if($snortsettings{"OINKCODE"}) {
167 # Take the oinkcode from snort settings hash and store it in the rules
168 # settings hash.
169 $rulessettings{"OINKCODE"} = $snortsettings{"OINKCODE"};
170}
171
172#
cde7cab2 173## Step 4: Import guardian settings and whitelist if the addon is installed.
5b0b4182
SS
174#
175
176# Pakfire meta file for owncloud.
177# (File exists when the addon is installed.)
178my $guardian_meta = "/opt/pakfire/db/installed/meta-guardian";
179
180# Check if the guardian addon is installed.
181if (-f $guardian_meta) {
182 # File which contains the taken setting for guardian.
183 my $guardian_settings_file = "${General::swroot}/guardian/settings";
184
185 # File which contains the white-listed hosts.
186 my $guardian_ignored_file = "${General::swroot}/guardian/ignored";
187
188 # Hash which will contain the settings of guardian.
189 my %guardiansettings;
190
191 # Check if the settings file of guardian is empty.
192 unless (-z $guardian_settings_file) {
193 # Read-in settings.
194 &General::readhash("$guardian_settings_file", \%guardiansettings);
195 }
196
197 # Check if guardian is not configured to take actions on snort events.
198 if ($guardiansettings{"GUARDIAN_MONITOR_SNORT"} eq "on") {
199 # Change the IDS into MONITOR_TRAFFIC_ONLY mode.
200 $idssettings{"MONITOR_TRAFFIC_ONLY"} = "off";
201 }
202
203 # Check if guardian has any white-listed hosts configured.
204 unless (-z $guardian_ignored_file) {
205 # Temporary hash to store the ignored hosts.
206 my %ignored_hosts;
207
208 # Read-in white-listed hosts and store them in the hash.
209 &General::readhasharray($guardian_ignored_file, \%ignored_hosts);
210
211 # Write-out the white-listed hosts for the IDS system.
212 &General::writehasharray($IDS::ignored_file, \%ignored_hosts);
213
214 # Call subfunction to generate the file for white-listing the hosts.
215 &IDS::generate_ignored_file();
216 }
217
218}
219
220#
cde7cab2 221## Step 5: Save IDS and rules settings.
5b0b4182
SS
222#
223
224# Write IDS settings.
225&General::writehash("$IDS::ids_settings_file", \%idssettings);
226
227# Write rules settings.
228&General::writehash("$IDS::rules_settings_file", \%rulessettings);
229
230#
cde7cab2 231## Step 6: Generate and write the file to modify the ruleset.
5b0b4182
SS
232#
233
5b0b4182 234# Call subfunction and pass the desired IDS action.
f1add9a8 235&IDS::write_modify_sids_file();
5b0b4182 236
5d7d8749
SS
237# Set correct ownership.
238&IDS::set_ownership("$IDS::modify_sids_file");
239
5b0b4182 240#
cde7cab2 241## Step 7: Move rulestarball to its new location.
5b0b4182
SS
242#
243
244# Check if a rulestarball has been downloaded yet.
245if (-f $snort_rules_tarball) {
246 # Load perl module which contains the move command.
247 use File::Copy;
248
249 # Move the rulestarball to the new location.
250 move($snort_rules_tarball, $IDS::rulestarball);
251
252 # Set correct ownership.
b09c13f1 253 &IDS::set_ownership("$IDS::rulestarball");
cc636c47
SS
254
255# In case no tarball is present, try to download the ruleset.
256} else {
257 # Check if enought disk space is available.
258 if(&IDS::checkdiskspace()) {
e4bc9b8b
SS
259 # Print error message.
260 print "Could not download ruleset - Not enough free diskspace available.\n";
261 } else {
cc636c47
SS
262 # Call the download function and grab the new ruleset.
263 &IDS::downloadruleset();
264 }
5b0b4182
SS
265}
266
267#
cde7cab2 268## Step 8: Call oinkmaster to extract and setup the rules structures.
5b0b4182
SS
269#
270
271# Check if a rulestarball is present.
272if (-f $IDS::rulestarball) {
273 # Launch oinkmaster by calling the subfunction.
274 &IDS::oinkmaster();
cc636c47
SS
275
276 # Set correct ownership for the rulesdir and files.
277 &IDS::set_ownership("$IDS::rulespath");
5b0b4182
SS
278}
279
280#
cde7cab2 281## Step 9: Generate file for the HOME Net.
ee82349a
SS
282#
283
284# Call subfunction to generate the file.
285&IDS::generate_home_net_file();
286
25d42438
SS
287# Set correct ownership for the homenet file.
288&IDS::set_ownership("$IDS::homenet_file");
289
ee82349a 290#
cde7cab2 291## Step 10: Generate file for the DNS servers.
bb2696da
SS
292#
293
294# Call subfunction to generate the file.
295&IDS::generate_dns_servers_file();
296
297# Set correct ownership for the dns_servers_file.
298&IDS::set_ownership("$IDS::dns_servers_file");
299
300#
e698090e
SS
301## Step 11: Generate file which contains the HTTP ports.
302#
303
304# Call subfunction to generate the file.
305&IDS::generate_http_ports_file();
306
307# Set correct ownership for the http_ports_file.
308&IDS::set_ownership("$IDS::http_ports_file");
309
310#
311## Step 12: Setup automatic ruleset updates.
ee82349a
SS
312#
313
314# Check if a ruleset is configured.
315if($rulessettings{"RULES"}) {
316 # Call suricatactrl and setup the periodic update mechanism.
317 &IDS::call_suricatactrl("cron", $rulessettings{'AUTOUPDATE_INTERVAL'});
318}
319
320#
e698090e 321## Step 13: Grab used ruleset files from snort config file and convert
5b0b4182
SS
322## them into the new format.
323#
324
325# Check if the snort config file exists.
326unless (-f $snort_config_file) {
327 print "$snort_config_file does not exist - Nothing to do. Exiting!\n";
328 exit(0);
329}
330
331# Array to store the enabled rules files.
332my @enabled_rule_files;
333
334# Open snort config file.
335open(SNORTCONF, $snort_config_file) or die "Could not open $snort_config_file. $!\n";
336
337# Loop through the file content.
338while (my $line = <SNORTCONF>) {
339 # Skip comments.
340 next if ($line =~ /\#/);
341
342 # Skip blank lines.
343 next if ($line =~ /^\s*$/);
344
345 # Remove newlines.
346 chomp($line);
347
348 # Check for a line with .rules
349 if ($line =~ /\.rules$/) {
350 # Parse out rule file name
351 my $rulefile = $line;
352 $rulefile =~ s/\$RULE_PATH\///i;
353 $rulefile =~ s/ ?include ?//i;
354
355 # Add the enabled rulefile to the array of enabled rule files.
356 push(@enabled_rule_files, $rulefile);
357 }
358}
359
360# Close filehandle.
361close(SNORTCONF);
362
363# Pass the array of enabled rule files to the subfunction and write the file.
364&IDS::write_used_rulefiles_file(@enabled_rule_files);
365
5b0b4182 366#
e698090e 367## Step 14: Start the IDS if enabled.
5b0b4182
SS
368#
369
370# Check if the IDS should be started.
371if($idssettings{"ENABLE_IDS"} eq "on") {
372 # Call suricatactrl and launch the IDS.
373 &IDS::call_suricatactrl("start");
374}