]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - config/firewall/rules.pl
core186: ship header.pl
[ipfire-2.x.git] / config / firewall / rules.pl
index 50feafa3bee11d5d3f3f0b217851ca7724ed6dca..a47c260a152647ab9c740578d4e3c0f27beb0d0a 100644 (file)
@@ -2,7 +2,7 @@
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2007-2020  IPFire Team  <info@ipfire.org>                     #
+# Copyright (C) 2007-2024  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        #
@@ -55,6 +55,7 @@ my @PRIVATE_NETWORKS = (
        "172.16.0.0/12",
        "192.168.0.0/16",
        "100.64.0.0/10",
+       "224.0.0.0/4",
 );
 
 # MARK masks
@@ -401,6 +402,9 @@ sub buildrules {
                                        $source = "";
                                }
 
+                               # Make sure that $source is properly defined
+                               next unless (defined $source);
+
                                my $source_intf = @$src[1];
 
                                foreach my $dst (@destinations) {
@@ -722,8 +726,8 @@ sub drop_hostile_networks () {
        &ipset_restore($HOSTILE_CCODE);
 
        # Check traffic in incoming/outgoing direction and drop if it matches
-       run("$IPTABLES -A HOSTILE -i $RED_DEV -m set --match-set $HOSTILE_CCODE src -j HOSTILE_DROP");
-       run("$IPTABLES -A HOSTILE -o $RED_DEV -m set --match-set $HOSTILE_CCODE dst -j HOSTILE_DROP");
+       run("$IPTABLES -A HOSTILE -i $RED_DEV -m set --match-set $HOSTILE_CCODE src -j HOSTILE_DROP_IN");
+       run("$IPTABLES -A HOSTILE -o $RED_DEV -m set --match-set $HOSTILE_CCODE dst -j HOSTILE_DROP_OUT");
 }
 
 sub ipblocklist () {
@@ -731,35 +735,56 @@ sub ipblocklist () {
        run("$IPTABLES -F BLOCKLISTIN");
        run("$IPTABLES -F BLOCKLISTOUT");
 
-       # If the blocklist feature is disabled we are finished here.
-       if($blocklistsettings{'ENABLE'} ne "on") {
-               # Bye.
-               return;
+       # Check if the blocklist feature is enabled.
+       if($blocklistsettings{'ENABLE'} eq "on") {
+               # Loop through the array of private networks.
+               foreach my $private_network (@PRIVATE_NETWORKS) {
+                       # Create firewall rules to never block private networks.
+                       run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -s $private_network -j RETURN");
+                       run("$IPTABLES -A BLOCKLISTOUT -p ALL -o $RED_DEV -d $private_network -j RETURN");
+               }
        }
 
        # Loop through the array of blocklists.
        foreach my $blocklist (@blocklists) {
-               # Skip disabled blocklists.
-               next unless($blocklistsettings{$blocklist}) && ($blocklistsettings{$blocklist} eq "on"));
+               # Check if the blocklist feature and the current processed blocklist is enabled.
+               if(($blocklistsettings{'ENABLE'} eq "on") && ($blocklistsettings{$blocklist}) && ($blocklistsettings{$blocklist} eq "on")) {
+                       # Call function to load the blocklist.
+                       &ipset_restore($blocklist);
+
+                       # Call function to check if the corresponding iptables drop chain already has been created.
+                       if(&firewall_chain_exists("${blocklist}_DROP")) {
+                               # Create iptables chain.
+                               run("$IPTABLES -N ${blocklist}_DROP");
+                       } else {
+                               # Flush the chain.
+                               run("$IPTABLES -F ${blocklist}_DROP");
+                       }
 
-               # Call function to load the blocklist.
-               &ipset_restore($blocklist);
+                       # Check if logging is enabled.
+                       if(($blocklistsettings{'LOGGING'}) && ($blocklistsettings{'LOGGING'} eq "on")) {
+                               # Create logging rule.
+                               run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist \"");
+                       }
 
-               # Create iptables chain.
-               run("$IPTABLES -N ${blocklist}_DROP");
+                       # Create Drop rule.
+                       run("$IPTABLES -A ${blocklist}_DROP -j DROP");
 
-               # Check if logging is enables.
-               if($blocklistsettings{'LOGGING'} eq "on") {
-                       # Create logging rule.
-                       run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist\" ");
-               }
+                       # Add the rules to check against the set
+                       run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -m set --match-set $blocklist src -j ${blocklist}_DROP");
+                       run("$IPTABLES -A BLOCKLISTOUT -p ALL -o $RED_DEV -m set --match-set $blocklist dst -j ${blocklist}_DROP");
 
-               # Create Drop rule.
-               run("$IPTABLES A ${blocklist}_DROP -j DROP");
+               # IP blocklist or the blocklist is disabled.
+               } else {
+                       # Check if the blocklist related iptables drop chain exits.
+                       unless(&firewall_chain_exists("${blocklist}_DROP")) {
+                               # Flush the chain.
+                               run("$IPTABLES -F ${blocklist}_DROP");
 
-               # Add the rules to check against the set
-               run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -m set --match-set $blocklist src -j ${blocklist}_DROP");
-               run("$IPTABLES -A BLOCKLISTOUT -p ALL -o $RED_DEV -m set --match-set $blocklist dst -j ${blocklist}_DROP");
+                               # Drop the chain.
+                               run("$IPTABLES -X ${blocklist}_DROP");
+                       }
+               }
        }
 }
 
@@ -976,6 +1001,14 @@ sub firewall_is_in_subnet {
        return 0;
 }
 
+sub firewall_chain_exists ($) {
+       my ($chain) = @_;
+
+       my $ret = &General::system("iptables", "--wait", "-n", "-L", "$chain");
+
+       return $ret;
+}
+
 sub ipset_get_sets () {
        my @sets;
 
@@ -1044,11 +1077,23 @@ sub ipset_restore ($) {
 
        # Check if the given set name is a blocklist.
        } elsif ($set ~~ @blocklists) {
+               # IPblocklist sets contains v4 as setname extension.
+               my $set_name = "$set" . "v4";
+
                # Get the database file for the given blocklist.
                my $db_file = &IPblocklist::get_ipset_db_file($set);
 
                # Call function to restore/load the set.
                &ipset_call_restore($db_file);
+
+               # Check if the set is already loaded (has been used before).
+               if ($set ~~ @ipset_used_sets) {
+                       # Swap the sets.
+                       run("$IPSET swap $set_name $set");
+               } else {
+                       # Rename the set to proper use it.
+                       run("$IPSET rename $set_name $set");
+               }
        }
 
        # Store the restored set to the hash to prevent from loading it again.