convert-snort: Re-order steps at end of script
[ipfire-2.x.git] / config / suricata / convert-snort
1 #!/usr/bin/perl
2 ###############################################################################
3 #                                                                             #
4 # IPFire.org - A linux based firewall                                         #
5 # Copyright (C) 2019 IPFire Development Team <info@ipfire.org>                #
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
22 use strict;
23
24 require '/var/ipfire/general-functions.pl';
25 require "${General::swroot}/ids-functions.pl";
26
27 # Snort settings file, which contains the settings from the WUI.
28 my $snort_settings_file = "${General::swroot}/snort/settings";
29
30 # Main snort config file.
31 my $snort_config_file = "/etc/snort/snort.conf";
32
33 # Snort rules tarball.
34 my $snort_rules_tarball = "/var/tmp/snortrules.tar.gz";
35
36 #
37 ## Step 1: Setup directory and file layout, if not present and set correct
38 ##         ownership. The converter runs as a privileged user, but the files
39 ##         needs to be full access-able by the WUI user and group (nobody:nobody).
40 #
41
42 # Check if the settings directory exists.
43 unless (-d $IDS::settingsdir) {
44         # Create the directory.
45         mkdir($IDS::settingsdir);
46 }
47
48 # Check if the rules directory exists.
49 unless (-d $IDS::rulespath) {
50         # Create the directory.
51         mkdir($IDS::rulespath);
52 }
53
54 # Create file layout, if not exists yet.
55 &IDS::check_and_create_filelayout();
56
57 # Set correct ownership for settingsdir and rulespath.
58 &IDS::set_ownership("$IDS::settingsdir");
59 &IDS::set_ownership("$IDS::rulespath");
60
61 # Check if a snort settings file exists.
62 unless( -f "$snort_settings_file") {
63         print "$snort_settings_file not found - Nothing to do. Exiting!\n";
64         exit(0);
65 }
66
67 # Check if the snort settings file is empty.
68 if (-z "$snort_settings_file") {
69         print "$snort_settings_file is empty - Nothing to do. Exiting!\n";
70         exit(0);
71 }
72
73 #
74 ## Step 2: Import snort settings and convert to the required format for the new IDS
75 ##         (suricata).
76 #
77
78 # Hash which contains the "old" snort settings.
79 my %snortsettings;
80
81 # Hash which contains the IDS (suricata) settings.
82 #
83 # Add default value for MONITOR_TRAFFIC_ONLY which will be "on"
84 # when migrating from snort to the new IDS.
85 my %idssettings = (
86         "MONITOR_TRAFFIC_ONLY" => "on",
87 );
88
89 # Hash which contains the RULES settings.
90 #
91 # Set default value for UPDATE_INTERVAL to weekly.
92 my %rulessettings = (
93         "AUTOUPDATE_INTERVAL" => "weekly",
94 );
95
96 # Get all available network zones.
97 my @network_zones = &IDS::get_available_network_zones();
98
99 # Read-in snort settings file.
100 &General::readhash("$snort_settings_file", \%snortsettings);
101
102 # Loop through the array of network zones.
103 foreach my $zone (@network_zones) {
104         # Convert current zone into upper case.
105         my $zone_upper = uc($zone);
106
107         # Check if the current network zone is "red".
108         if($zone eq "red") {
109                 # Check if snort was enabled and enabled on red.
110                 if ($snortsettings{"ENABLE_SNORT"} eq "on") {
111                         # Enable the IDS.
112                         $idssettings{"ENABLE_IDS"} = "on";
113
114                         # Enable the IDS on RED.
115                         $idssettings{"ENABLE_IDS_$zone_upper"} = "on";
116                 }
117         } else {
118                 # Check if snort was enabled on the current zone.
119                 if ($snortsettings{"ENABLE_SNORT_$zone_upper"} eq "on") {
120                         # Enable the IDS on this zone too.
121                         $idssettings{"ENABLE_IDS_$zone_upper"} = "on";
122                 }
123         }
124 }
125
126 # Grab the choosen ruleset from snort settings hash and store it in the rules
127 # settings hash.
128 $rulessettings{"RULES"} = $snortsettings{"RULES"};
129
130 # Check if an oinkcode has been provided.
131 if($snortsettings{"OINKCODE"}) {
132         # Take the oinkcode from snort settings hash and store it in the rules
133         # settings hash.
134         $rulessettings{"OINKCODE"} = $snortsettings{"OINKCODE"};
135 }
136
137 #
138 ## Step 3: Import guardian settings and whitelist if the addon is installed.
139 #
140
141 # Pakfire meta file for owncloud.
142 # (File exists when the addon is installed.)
143 my $guardian_meta = "/opt/pakfire/db/installed/meta-guardian";
144
145 # Check if the guardian addon is installed.
146 if (-f $guardian_meta) {
147         # File which contains the taken setting for guardian.
148         my $guardian_settings_file = "${General::swroot}/guardian/settings";
149
150         # File which contains the white-listed hosts.
151         my $guardian_ignored_file = "${General::swroot}/guardian/ignored";
152
153         # Hash which will contain the settings of guardian.
154         my %guardiansettings;
155
156         # Check if the settings file of guardian is empty.
157         unless (-z $guardian_settings_file) {
158                 # Read-in settings.
159                 &General::readhash("$guardian_settings_file", \%guardiansettings);
160         }
161
162         # Check if guardian is not configured to take actions on snort events.
163         if ($guardiansettings{"GUARDIAN_MONITOR_SNORT"} eq "on") {
164                 # Change the IDS into MONITOR_TRAFFIC_ONLY mode.
165                 $idssettings{"MONITOR_TRAFFIC_ONLY"} = "off";
166         }
167
168         # Check if guardian has any white-listed hosts configured.
169         unless (-z $guardian_ignored_file) {
170                 # Temporary hash to store the ignored hosts.
171                 my %ignored_hosts;
172
173                 # Read-in white-listed hosts and store them in the hash.
174                 &General::readhasharray($guardian_ignored_file, \%ignored_hosts);
175
176                 # Write-out the white-listed hosts for the IDS system.
177                 &General::writehasharray($IDS::ignored_file, \%ignored_hosts);
178
179                 # Call subfunction to generate the file for white-listing the hosts.
180                 &IDS::generate_ignored_file();
181         }
182
183 }
184
185 #
186 ## Step 4: Save IDS and rules settings.
187 #
188
189 # Write IDS settings.
190 &General::writehash("$IDS::ids_settings_file", \%idssettings);
191
192 # Write rules settings.
193 &General::writehash("$IDS::rules_settings_file", \%rulessettings);
194
195 #
196 ## Step 5: Generate and write the file to modify the ruleset.
197 #
198
199 # Converters default is to only monitor the traffic, so set the IDS action to
200 # "alert".
201 my $IDS_action = "alert";
202
203 # Check if the traffic only should be monitored.
204 if ($idssettings{"MONITOR_TRAFFIC_ONLY"} eq "off") {
205         # Swith IDS action to alert only.
206         $IDS_action = "drop";
207 }
208
209 # Call subfunction and pass the desired IDS action.
210 &IDS::write_modify_sids_file($IDS_action);
211
212 # Set correct ownership.
213 &IDS::set_ownership("$IDS::modify_sids_file");
214
215 #
216 ## Step 6: Move rulestarball to its new location.
217 #
218
219 # Check if a rulestarball has been downloaded yet.
220 if (-f $snort_rules_tarball) {
221         # Load perl module which contains the move command.
222         use File::Copy;
223
224         # Move the rulestarball to the new location.
225         move($snort_rules_tarball, $IDS::rulestarball);
226
227         # Set correct ownership.
228         &IDS::set_ownership("$IDS::rulestarball");
229
230 # In case no tarball is present, try to download the ruleset.
231 } else {
232         # Check if enought disk space is available.
233         if(&IDS::checkdiskspace()) {
234                 # Print error message.
235                 print "Could not download ruleset - Not enough free diskspace available.\n";
236         } else {
237                 # Call the download function and grab the new ruleset.
238                 &IDS::downloadruleset();
239         }
240 }
241
242 #
243 ## Step 7: Call oinkmaster to extract and setup the rules structures.
244 #
245
246 # Check if a rulestarball is present.
247 if (-f $IDS::rulestarball) {
248         # Launch oinkmaster by calling the subfunction.
249         &IDS::oinkmaster();
250
251         # Set correct ownership for the rulesdir and files.
252         &IDS::set_ownership("$IDS::rulespath");
253 }
254
255 #
256 ## Step 8: Generate file for the HOME Net.
257 #
258
259 # Call subfunction to generate the file.
260 &IDS::generate_home_net_file();
261
262 #
263 ## Step 9: Setup automatic ruleset updates.
264 #
265
266 # Check if a ruleset is configured.
267 if($rulessettings{"RULES"}) {
268         # Call suricatactrl and setup the periodic update mechanism.
269         &IDS::call_suricatactrl("cron", $rulessettings{'AUTOUPDATE_INTERVAL'});
270 }
271
272 #
273 ## Step 10: Grab used ruleset files from snort config file and convert
274 ##         them into the new format.
275 #
276
277 # Check if the snort config file exists.
278 unless (-f $snort_config_file) {
279         print "$snort_config_file does not exist - Nothing to do. Exiting!\n";
280         exit(0);
281 }
282
283 # Array to store the enabled rules files.
284 my @enabled_rule_files;
285
286 # Open snort config file.
287 open(SNORTCONF, $snort_config_file) or die "Could not open $snort_config_file. $!\n";
288
289 # Loop through the file content.
290 while (my $line = <SNORTCONF>) {
291         # Skip comments.
292         next if ($line =~ /\#/);
293
294         # Skip blank  lines.
295         next if ($line =~ /^\s*$/);
296
297         # Remove newlines.
298         chomp($line);
299
300         # Check for a line with .rules
301         if ($line =~ /\.rules$/) {
302                 # Parse out rule file name
303                 my $rulefile = $line;
304                 $rulefile =~ s/\$RULE_PATH\///i;
305                 $rulefile =~ s/ ?include ?//i;
306
307                 # Add the enabled rulefile to the array of enabled rule files.
308                 push(@enabled_rule_files, $rulefile);
309         }
310 }
311
312 # Close filehandle.
313 close(SNORTCONF);
314
315 # Pass the array of enabled rule files to the subfunction and write the file.
316 &IDS::write_used_rulefiles_file(@enabled_rule_files);
317
318 #
319 ## Step 11: Start the IDS if enabled.
320 #
321
322 # Check if the IDS should be started.
323 if($idssettings{"ENABLE_IDS"} eq "on") {
324         # Call suricatactrl and launch the IDS.
325         &IDS::call_suricatactrl("start");
326 }