lauhub il y a 10 mois
Parent
commit
cb14c756e4
4 fichiers modifiés avec 240 ajouts et 48 suppressions
  1. 1 0
      .gitignore
  2. 9 3
      Makefile
  3. 218 45
      scripts/lfirewall
  4. 12 0
      systemd/lfirewall.service

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+.vscode/*

+ 9 - 3
Makefile

@@ -5,16 +5,22 @@ FIREWALL_ETC_DIR=/etc/lfirewall
 FIREWALL_CONF=lfirewall.conf
 PREFIX=
 INSTALL_DIR=$(PREFIX)/sbin
+SYSTEMD_INSTALL_DIR=$(PREFIX)/etc/systemd/system
+SERVICE_FILE=lfirewall.service
+SYSTEMD_SERVICE_FILE=$(SYSTEMD_INSTALL_DIR)/$(SERVICE_FILE)
 
 #SysVinit installation dir
 #INSTALL_DIR=/etc/init.d
 
-firewall: $(INSTALL_DIR)/lfirewall config
+firewall: $(INSTALL_DIR)/lfirewall config $(SYSTEMD_SERVICE_FILE)
 
 config: 
 	$(MKDIR) -p $(FIREWALL_ETC_DIR)
-	$(CP) etc/$(FIREWALL_CONF) $(FIREWALL_ETC_DIR)/
-	
+	@if [ ! -f $(FIREWALL_ETC_DIR)/$(FIREWALL_CONF) ] ; then $(CP) etc/$(FIREWALL_CONF) $(FIREWALL_ETC_DIR)/ ; else echo "The file $(FIREWALL_ETC_DIR)/$(FIREWALL_CONF) already exists" ; fi
+
 $(INSTALL_DIR)/lfirewall: scripts/lfirewall
 	$(CP) $< $@
 
+$(SYSTEMD_SERVICE_FILE): systemd/$(SERVICE_FILE)
+	$(CP) $< $@
+	

+ 218 - 45
scripts/lfirewall

@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 ### BEGIN INIT INFO
 # Provides:          firewall.sh
 # Required-Start:    $syslog $network
@@ -18,6 +18,84 @@
 # description: Activates/Deactivates the firewall at boot time
 #
 
+set -euo pipefail
+
+help_message_lfirewall(){
+cat <<-EOF
+  Light Firewall configuration script.
+
+  $(basename ${0}) [OPTIONS...] COMMAND
+
+	COMMANDS
+
+		start : starts the firewall
+		clear : stops the firewall (removes all IPTABLES rules and let all connections work)
+		stop  : stops all network connections (USE with CAUTION)
+		test	: tests the existing rules for 30 seconds
+
+	OPTIONS
+		-v --verbose	: verbose mode
+		-h --help			: display this help message
+		-l --logging	: enables logging (prefix: iptables-logging)
+
+	AUTHOR
+		Original author: Nicolargo
+		Modified by: Laurent Hubert
+EOF
+}
+
+options=$(getopt -l "help,verbose,logging" -o "hvl" -- "$@")
+
+if [[ $? != 0 ]] ; then
+	help_message_lfirewall
+	exit 1
+fi
+
+eval set -- "$options"
+
+IT_INPUT=INPUT
+IT_INPUT_LOG=LOGINPUT
+IT_OUTPUT=OUTPUT
+IT_OUTPUT_LOG=LOGOUTPUT
+
+verbose=0
+logging=" "
+
+while :
+do
+	if [[ ${verbose} = "1" ]] ; then
+		echo "$@"
+	fi
+
+	case "$1" in
+		-h|--help)
+			help_message_lfirewall
+			exit 0
+			;;
+		-v|--verbose)
+			verbose=$(( verbose + 1 ))
+			if [[ ${verbose} -gt 1 ]]
+			then
+				set -x
+			fi
+			if [[ ${verbose} -gt 2 ]]
+			then
+				set -v
+			fi
+			;;
+		-l|--logging)
+			logging="-j LOG --log-prefix 'iptables-logging'"
+			IT_INPUT=${IT_INPUT_LOG}
+			IT_OUTPUT=${IT_OUTPUT_LOG}
+			;;
+		--)
+			shift
+			break
+			;;
+	esac
+	shift
+done
+
 PATH=/bin:/sbin:/usr/bin:/usr/sbin
 
 #Defautl network interface
@@ -39,13 +117,16 @@ REMOTE_UDP_SERVICES="53" # DNS
 # management network but remove it from TCP_SERVICES
 SSH_PORT="22"
 
+# Default IP_TABLES command path
+IP_TABLES="/sbin/iptables"
+
 CONFIGURATION_FILE=/etc/lfirewall/lfirewall.conf
 if [ -f $CONFIGURATION_FILE ] ; then
+	set +u
 	. $CONFIGURATION_FILE
+	set -u
 fi
 
-IP_TABLES="/sbin/iptables"
-
 if ! [ -x $IP_TABLES ]; then
 	echo "$IP_TABLES is not executable or not present" >&2
 	exit 1
@@ -57,6 +138,66 @@ then
 	exit 2
 fi
 
+do_action=do_exec
+
+IPTABLES_CHECK=__iptables_check_action
+IPTABLES_ADD=__iptable_add_action
+IPTABLES_SET_POLICY=__iptable_set_policy_action
+
+do_exec () {
+	case $1 in
+		__iptable_add_action)
+			shift
+			iptables_option=-A
+		;;
+		__iptable_set_policy_action)
+			shift
+			iptables_option=-P
+		;;
+		*)
+			echo "Nothing to be done for $1"
+		;;
+	esac
+	if [[ ${verbose} -ge 1 ]] ; then
+		echo $IP_TABLES $iptables_option $*
+	fi
+	$IP_TABLES $iptables_option $*	
+}
+
+do_check () {
+	the_action=$1
+	shift
+	case $the_action in
+		__iptable_add_action)
+			iptables_option=-A
+		;;
+		__iptable_set_policy_action)
+			return 0
+		;;
+		*)
+			echo "Nothing to be done for $1"
+		;;
+	esac
+	default_option=-C
+	if [[ ${verbose} -ge 1 ]] ; then
+		echo $do_log "$the_action:" $IP_TABLES -C $*
+		echo $IP_TABLES -C $*
+	fi
+	$do_log "$the_action:" $IP_TABLES -C $*
+	$IP_TABLES -C $*
+	global_status=$((global_status+$?))
+}
+
+log_action () {
+	echo $*
+}
+
+do_not_log_action () {
+	return 0
+}
+
+do_log=do_not_log_action
+
 ##########################
 # Start the Firewall rules
 ##########################
@@ -67,83 +208,84 @@ fw_start () {
 	#**************************************************************************#
 
 	### Keep existing connections
-	$IP_TABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 	# Services
 	if [ -n "$TCP_SERVICES" ] ; then
 		for PORT in $TCP_SERVICES; do
-			$IP_TABLES -A INPUT -p tcp --dport ${PORT} -j ACCEPT
+			$do_action $IPTABLES_ADD $IT_INPUT -p tcp --dport ${PORT} -j ACCEPT
 		done
 	fi
 	if [ -n "$UDP_SERVICES" ] ; then
 		for PORT in $UDP_SERVICES; do
-			$IP_TABLES -A INPUT -p udp --dport ${PORT} -j ACCEPT
+			$do_action $IPTABLES_ADD $IT_INPUT -p udp --dport ${PORT} -j ACCEPT
 		done
 	fi
 	# Remote management
-	if [ -n "$NETWORK_MGMT" ] ; then
-		$IP_TABLES -A INPUT -p tcp --src ${NETWORK_MGMT} --dport ${SSH_PORT} -j ACCEPT
+	if [ "${NETWORK_MGMT:=UNBOUND_VARIABLE}" != "UNBOUND_VARIABLE" ] ; then
+		$do_action $IPTABLES_ADD $IT_INPUT -p tcp --src ${NETWORK_MGMT} --dport ${SSH_PORT} -j ACCEPT
 	else
-		$IP_TABLES -A INPUT -p tcp --dport ${SSH_PORT}  -j ACCEPT
+		$do_action $IPTABLES_ADD $IT_INPUT -p tcp --dport ${SSH_PORT}  -j ACCEPT
 	fi
 
 	#**************************************************************************#
 	# NGINX
 	#**************************************************************************#
-	$IP_TABLES -A INPUT -i lo -s localhost -d localhost -j ACCEPT
-	$IP_TABLES -A OUTPUT -o lo -s localhost -d localhost -j ACCEPT
-	$IP_TABLES -A INPUT  -p tcp --dport http -j ACCEPT
-        $IP_TABLES -A INPUT  -p tcp --dport https -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_INPUT -i lo -s localhost -d localhost -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_OUTPUT -o lo -s localhost -d localhost -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_INPUT  -p tcp --dport http -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_INPUT  -p tcp --dport https -j ACCEPT
 
 
 	# Remote testing
 	### Allows PING
-	$IP_TABLES -A INPUT -p icmp -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_INPUT -p icmp -j ACCEPT
+
 	### Allows LOOPBACK
-	$IP_TABLES -A INPUT -i lo -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_INPUT -i lo -j ACCEPT
 
-	$IP_TABLES -P INPUT DROP
-	$IP_TABLES -A INPUT -j LOG
+	$IP_TABLES -P $IT_INPUT DROP
+	$do_action $IPTABLES_ADD $IT_INPUT -j LOG
 
 	#**************************************************************************#
 	# Output:
 	#**************************************************************************#
 	### Allows LOOPBACK
-	$IP_TABLES -A OUTPUT -j ACCEPT -o lo
+	$do_action $IPTABLES_ADD $IT_OUTPUT -j ACCEPT -o lo
 
 	###
-	$IP_TABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 
 	# ICMP is permitted:
 	### Allows ping:
-	$IP_TABLES -A OUTPUT -p icmp -j ACCEPT
+	$do_action $IPTABLES_ADD $IT_OUTPUT -p icmp -j ACCEPT
 
 	# As well as the services we have defined:
 	if [ -n "$REMOTE_TCP_SERVICES" ] ; then
 		for PORT in $REMOTE_TCP_SERVICES; do
-			$IP_TABLES -A OUTPUT -p tcp --dport ${PORT} -j ACCEPT
+			$do_action $IPTABLES_ADD $IT_OUTPUT -p tcp --dport ${PORT} -j ACCEPT
 		done
 	fi
 	if [ -n "$REMOTE_UDP_SERVICES" ] ; then
 		for PORT in $REMOTE_UDP_SERVICES; do
-			$IP_TABLES -A OUTPUT -p udp --dport ${PORT} -j ACCEPT
+			$do_action $IPTABLES_ADD $IT_OUTPUT -p udp --dport ${PORT} -j ACCEPT
 		done
 	fi
 	# All other connections are registered in syslog
-	$IP_TABLES -A OUTPUT -j LOG
-	$IP_TABLES -A OUTPUT -j REJECT
-	$IP_TABLES -P OUTPUT DROP
+	$do_action $IPTABLES_ADD $IT_OUTPUT -j LOG
+	$do_action $IPTABLES_ADD $IT_OUTPUT -j REJECT
+	$do_action $IPTABLES_SET_POLICY $IT_OUTPUT DROP
 
-	$IP_TABLES -A FORWARD -j LOG
+	$do_action $IPTABLES_ADD FORWARD -j LOG
 
 	#**************************************************************************#
 	# DOS attack protection
 	#**************************************************************************#
 	# See http://rockdio.org/ayudatech/how-to-stop-small-ddos-attacks-some-basic-security-advice/
 	#
-	$IP_TABLES -I INPUT -p tcp --dport 80 -i $NETWORK_IF -m state --state NEW -m recent --set
-	$IP_TABLES -I INPUT -p tcp --dport 80 -i $NETWORK_IF -m state --state NEW -m recent --update --seconds 30 --hitcount 20 -j DROP
-	$IP_TABLES -I INPUT -p tcp --dport 443 -i $NETWORK_IF -m state --state NEW -m recent --set
-	$IP_TABLES -I INPUT -p tcp --dport 443 -i $NETWORK_IF -m state --state NEW -m recent --update --seconds 30 --hitcount 20 -j DROP
+	$IP_TABLES -I $IT_INPUT -p tcp --dport 80 -i $NETWORK_IF -m state --state NEW -m recent --set
+	$IP_TABLES -I $IT_INPUT -p tcp --dport 80 -i $NETWORK_IF -m state --state NEW -m recent --update --seconds 30 --hitcount 20 -j DROP
+	$IP_TABLES -I $IT_INPUT -p tcp --dport 443 -i $NETWORK_IF -m state --state NEW -m recent --set
+	$IP_TABLES -I $IT_INPUT -p tcp --dport 443 -i $NETWORK_IF -m state --state NEW -m recent --update --seconds 30 --hitcount 20 -j DROP
 
 	#**************************************************************************#
 	# Other network protections
@@ -163,8 +305,15 @@ fw_start () {
 	echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
 	echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
 
-	iptables -t filter -A OUTPUT -p tcp --dport 22 -j ACCEPT
-	iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT
+	iptables -t filter -A $IT_OUTPUT -p tcp --dport 22 -j ACCEPT
+	iptables -t filter -A $IT_INPUT -p tcp --dport 22 -j ACCEPT
+}
+
+do_this(){
+    if [[ ${verbose} -ge 1 ]] ; then
+      echo $*
+    fi
+    $*
 }
 
 ##########################
@@ -172,12 +321,12 @@ fw_start () {
 ##########################
 
 fw_stop () {
-	$IP_TABLES -F
-	$IP_TABLES -t nat -F
-	$IP_TABLES -t mangle -F
-	$IP_TABLES -P INPUT DROP
-	$IP_TABLES -P FORWARD DROP
-	$IP_TABLES -P OUTPUT ACCEPT
+	do_this $IP_TABLES -F
+	do_this $IP_TABLES -t nat -F
+	do_this $IP_TABLES -t mangle -F
+	do_this $IP_TABLES -P $IT_INPUT DROP
+	do_this $IP_TABLES -P FORWARD DROP
+	do_this $IP_TABLES -P $IT_OUTPUT ACCEPT
 }
 
 ##########################
@@ -185,13 +334,13 @@ fw_stop () {
 ##########################
 
 fw_clear () {
-	$IP_TABLES -F
-	$IP_TABLES -X
-	$IP_TABLES -t nat -F
-	$IP_TABLES -t mangle -F
-	$IP_TABLES -P INPUT ACCEPT
-	$IP_TABLES -P FORWARD ACCEPT
-	$IP_TABLES -P OUTPUT ACCEPT
+	do_this $IP_TABLES -F
+	do_this $IP_TABLES -t nat -F
+	do_this $IP_TABLES -t mangle -F
+	do_this $IP_TABLES -P $IT_INPUT ACCEPT
+	do_this $IP_TABLES -P FORWARD ACCEPT
+	do_this $IP_TABLES -P $IT_OUTPUT ACCEPT
+	do_this $IP_TABLES -X
 }
 
 ##########################
@@ -199,11 +348,19 @@ fw_clear () {
 ##########################
 
 fw_save () {
+  if [[ ${verbose} -ge 1 ]] ; then
+    echo "$IP_TABLES-save > /etc/iptables.backup"
+  fi
+
 	$IP_TABLES-save > /etc/iptables.backup
 }
 
 fw_restore () {
 	if [ -e /etc/iptables.backup ]; then
+	  if [[ ${verbose} -ge 1 ]] ; then
+	    echo "$IP_TABLES-save > /etc/iptables.backup"
+	  fi
+
 		$IP_TABLES-restore < /etc/iptables.backup
 	fi
 }
@@ -244,6 +401,22 @@ case "$1" in
 		fw_test
 		echo -n "Previous configuration will be restore in 30 seconds"
 	;;
+	status)
+		do_action=do_check
+		global_status=0
+		if [ "$2" = "-v" ] ; then
+			do_log=log_action
+		fi
+		# Start will not really start but exec the "check" action
+		fw_start
+		if [ 0 -eq "$global_status" ] ; then
+			echo "Firewall rules match configuration"
+			exit 0
+		else
+			echo "Some firewall rules are not set correctly"
+			exit $global_status
+		fi
+	;;
 	*)
 		echo "Usage: $0 {start|dropall|stop|restart|clear|test}"
 		echo "###############################################################"

+ 12 - 0
systemd/lfirewall.service

@@ -0,0 +1,12 @@
+[Unit]
+Description=Light Firewall
+
+[Service]
+Type=oneshot
+ExecStart=/sbin/lfirewall start
+ExecStop=/sbin/lfirewall clear
+ExecStartPost=/sbin/lfirewall status
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target