[2/3] suricata: Handle ipset based whitelist in initscript.

Message ID 20220406191245.4218-2-stefan.schantl@ipfire.org
State Superseded
Headers
Series [1/3] ids-functions.pl: Generate ipset based whitelist. |

Commit Message

Stefan Schantl April 6, 2022, 7:12 p.m. UTC
  Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
---
 src/initscripts/system/suricata | 42 +++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
  

Patch

diff --git a/src/initscripts/system/suricata b/src/initscripts/system/suricata
index 938ea66de..5ede405ce 100644
--- a/src/initscripts/system/suricata
+++ b/src/initscripts/system/suricata
@@ -44,6 +44,15 @@  enabled_ips_zones=()
 # PID file of suricata.
 PID_FILE="/var/run/suricata.pid"
 
+# File which contains the ipset of whitelisted hosts.
+WHITELIST_FILE="/var/ipfire/suricata/whitelist.conf"
+
+# Name of the ipset set
+IPSET_SET="IPSWHITELIST"
+
+IPS_BYPASS_MARK="0x40000000"
+IPS_BYPASS_MASK="0x40000000"
+
 # Function to get the amount of CPU cores of the system.
 function get_cpu_count {
 	CPUCOUNT=0
@@ -135,16 +144,44 @@  function generate_fw_rules {
 	# Flush the firewall chains.
 	flush_fw_chain
 
+	if [ -s "$WHITELIST_FILE" ]; then
+		# Load the whitelist file.
+		ipset restore -f "$WHITELIST_FILE"
+	fi
+
 	# Check if the array of enabled_ips_zones contains any elements.
 	if [[ ${enabled_ips_zones[@]} ]]; then
 		# Loop through the array and create firewall rules.
 		for enabled_ips_zone in "${enabled_ips_zones[@]}"; do
+			# Check if the whitelist file is not empty.
+			if [ -s "$WHITELIST_FILE" ]; then
+				# Create rules to handle whitelisted hosts.
+				iptables -w -A "$IPS_INPUT_CHAIN" -i "$enabled_ips_zone" -m set --match-set $IPSET_SET src -j CONNMARK --set-xmark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK
+				iptables -w -A "$IPS_INPUT_CHAIN" -i "$enabled_ips_zone" -m set --match-set $IPSET_SET dst -j CONNMARK --set-xmark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK
+				iptables -w -A "$IPS_INPUT_CHAIN" -i "$enabled_ips_zone" -m connmark --mark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK -j RETURN
+
+				iptables -w -A "$IPS_OUTPUT_CHAIN" -o "$enabled_ips_zone" -m set --match-set $IPSET_SET src -j CONNMARK --set-xmark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK
+				iptables -w -A "$IPS_OUTPUT_CHAIN" -o "$enabled_ips_zone" -m set --match-set $IPSET_SET src -j CONNMARK --set-xmark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK
+				iptables -w -A "$IPS_OUTPUT_CHAIN" -o "$enabled_ips_zone" -m connmark --mark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK -j RETURN
+			fi
+
 			# Create rules queue input and output related traffic and pass it to the IPS.
 			iptables -w -A "$IPS_INPUT_CHAIN" -i "$enabled_ips_zone" -j NFQUEUE $NFQ_OPTIONS
 			iptables -w -A "$IPS_OUTPUT_CHAIN" -o "$enabled_ips_zone" -j NFQUEUE $NFQ_OPTIONS
 
 			# Create rules which are required to handle forwarded traffic.
 			for enabled_ips_zone_forward in "${enabled_ips_zones[@]}"; do
+				# Check if the whetelist file is not empty.
+				if [ -s "$WHITELIST_FILE" ]; then
+					# Create rules to handle whitelisted hosts.
+					iptables -w -A "$IPS_FORWARD_CHAIN" -i "$enabled_ips_zone" -o "$enabled_ips_zone_forward" \
+						-m set --match-set $IPSET_SET src -j CONNMARK --set-xmark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK
+					iptables -w -A "$IPS_FORWARD_CHAIN" -i "$enabled_ips_zone" -o "$enabled_ips_zone_forward" \
+						-m set --match-set $IPSET_SET dst -j CONNMARK --set-xmark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK
+					iptables -w -A "$IPS_FORWARD_CHAIN" -i "$enabled_ips_zone" -o "$enabled_ips_zone_forward" \
+						-m connmark --mark $IPS_BYPASS_MARK/$IPS_BYPASS_MASK
+				fi
+
 				iptables -w -A "$IPS_FORWARD_CHAIN" -i "$enabled_ips_zone" -o "$enabled_ips_zone_forward" -j NFQUEUE $NFQ_OPTIONS
 			done
 		done
@@ -188,6 +225,11 @@  case "$1" in
 		# Flush firewall chain.
 		flush_fw_chain
 
+		# Unload the ipset set.
+		if [ -s "$WHITELIST_FILE" ]; then
+			ipset destroy $IPSET_SET 2>/dev/null
+		fi
+
 		# Sometimes suricata not correct shutdown. So killall.
 		killall -KILL /usr/bin/suricata 2>/dev/null