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