#!/bin/sh # minifirewall is shellscripts for easy firewalling on a standalone server # we used netfilter/iptables http://netfilter.org/ designed for recent Linux kernel # See https://gitea.evolix.org/evolix/minifirewall # Copyright (c) 2007-2020 Evolix # 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 the Free Software Foundation; either version 3 # of the License. # Description # script for standalone server # Start or stop minifirewall # ### BEGIN INIT INFO # Provides: minfirewall # Required-Start: # Required-Stop: # Should-Start: $network $syslog $named # Should-Stop: $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop the firewall # Description: Firewall designed for standalone server ### END INIT INFO DESC="minifirewall" NAME="minifirewall" # Variables configuration ######################### # iptables paths IPT=/sbin/iptables IPT6=/sbin/ip6tables # TCP/IP variables LOOPBACK='127.0.0.0/8' CLASSA='10.0.0.0/8' CLASSB='172.16.0.0/12' CLASSC='192.168.0.0/16' CLASSD='224.0.0.0/4' CLASSE='240.0.0.0/5' ALL='0.0.0.0' BROAD='255.255.255.255' PORTSROOT='0:1023' PORTSUSER='1024:65535' chain_exists() { local chain_name="$1" ; shift [ $# -eq 1 ] && local intable="--table $1" iptables $intable -nL "$chain_name" >/dev/null 2>&1 } # Configuration oldconfigfile="/etc/firewall.rc" configfile="/etc/default/minifirewall" IPV6=$(grep "IPV6=" /etc/default/minifirewall | awk -F '=' -F "'" '{print $2}') DOCKER=$(grep "DOCKER=" /etc/default/minifirewall | awk -F '=' -F "'" '{print $2}') INT=$(grep "INT=" /etc/default/minifirewall | awk -F '=' -F "'" '{print $2}') case "$1" in start) echo "Start IPTables rules..." # Stop and warn if error! set -e trap 'echo "ERROR in minifirewall configuration (fix it now!) or script manipulation (fix yourself)." ' INT TERM EXIT # sysctl network security settings ################################## # Don't answer to broadcast pings echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # Ignore bogus ICMP responses echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses # Disable Source Routing for i in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $i done # Enable TCP SYN cookies to avoid TCP-SYN-FLOOD attacks # cf http://cr.yp.to/syncookies.html echo 1 > /proc/sys/net/ipv4/tcp_syncookies # Disable ICMP redirects for i in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $i done for i in /proc/sys/net/ipv4/conf/*/send_redirects; do echo 0 > $i done # Enable Reverse Path filtering : verify if responses use same network interface for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $i done # log des paquets avec adresse incoherente for i in /proc/sys/net/ipv4/conf/*/log_martians; do echo 1 > $i done # IPTables configuration ######################## $IPT -N LOG_DROP $IPT -A LOG_DROP -j LOG --log-prefix '[IPTABLES DROP] : ' $IPT -A LOG_DROP -j DROP $IPT -N LOG_ACCEPT $IPT -A LOG_ACCEPT -j LOG --log-prefix '[IPTABLES ACCEPT] : ' $IPT -A LOG_ACCEPT -j ACCEPT if test -f $oldconfigfile; then echo "$oldconfigfile is deprecated, rename to $configfile" >&2 exit 1 fi if ! test -f $configfile; then echo "$configfile does not exist" >&2 exit 1 fi tmpfile=`mktemp` . $configfile 2>$tmpfile >&2 if [ -s $tmpfile ]; then echo "$configfile returns standard or error output (see below). Stopping." >&2 cat $tmpfile exit 1 fi rm $tmpfile # Trusted ip addresses $IPT -N ONLYTRUSTED $IPT -A ONLYTRUSTED -j LOG_DROP for x in $TRUSTEDIPS do $IPT -I ONLYTRUSTED -s $x -j ACCEPT done # Privilegied ip addresses # (trusted ip addresses *are* privilegied) $IPT -N ONLYPRIVILEGIED $IPT -A ONLYPRIVILEGIED -j ONLYTRUSTED for x in $PRIVILEGIEDIPS do $IPT -I ONLYPRIVILEGIED -s $x -j ACCEPT done # Chain for restrictions (blacklist IPs/ranges) $IPT -N NEEDRESTRICT # We allow all on loopback interface $IPT -A INPUT -i lo -j ACCEPT [ "$IPV6" != "off" ] && $IPT6 -A INPUT -i lo -j ACCEPT # if OUTPUTDROP $IPT -A OUTPUT -o lo -j ACCEPT [ "$IPV6" != "off" ] && $IPT6 -A OUTPUT -o lo -j ACCEPT # We avoid "martians" packets, typical when W32/Blaster virus # attacked windowsupdate.com and DNS was changed to 127.0.0.1 # $IPT -t NAT -I PREROUTING -s $LOOPBACK -i ! lo -j DROP $IPT -A INPUT -s $LOOPBACK ! -i lo -j DROP if [ "$DOCKER" = "on" ]; then $IPT -N MINIFW-DOCKER-TRUSTED $IPT -A MINIFW-DOCKER-TRUSTED -j DROP $IPT -N MINIFW-DOCKER-PRIVILEGED $IPT -A MINIFW-DOCKER-PRIVILEGED -j MINIFW-DOCKER-TRUSTED $IPT -A MINIFW-DOCKER-PRIVILEGED -j RETURN $IPT -N MINIFW-DOCKER-PUB $IPT -A MINIFW-DOCKER-PUB -j MINIFW-DOCKER-PRIVILEGED $IPT -A MINIFW-DOCKER-PUB -j RETURN # Flush DOCKER-USER if exist, create it if absent if chain_exists 'DOCKER-USER'; then $IPT -F DOCKER-USER else $IPT -N DOCKER-USER fi; # Pipe new connection through MINIFW-DOCKER-PUB $IPT -A DOCKER-USER -i $INT -m state --state NEW -j MINIFW-DOCKER-PUB $IPT -A DOCKER-USER -j RETURN fi # Local services restrictions ############################# # Allow services for $INTLAN (local server or local network) $IPT -A INPUT -s $INTLAN -j ACCEPT # Enable protection chain for sensible services for x in $SERVICESTCP1p do $IPT -A INPUT -p tcp --dport $x -j NEEDRESTRICT done for x in $SERVICESUDP1p do $IPT -A INPUT -p udp --dport $x -j NEEDRESTRICT done # Public service for x in $SERVICESTCP1 do $IPT -A INPUT -p tcp --dport $x -j ACCEPT [ "$IPV6" != "off" ] && $IPT6 -A INPUT -p tcp --dport $x -j ACCEPT done for x in $SERVICESUDP1 do $IPT -A INPUT -p udp --dport $x -j ACCEPT [ "$IPV6" != "off" ] && $IPT6 -A INPUT -p udp --dport $x -j ACCEPT done # Privilegied services for x in $SERVICESTCP2 do $IPT -A INPUT -p tcp --dport $x -j ONLYPRIVILEGIED done for x in $SERVICESUDP2 do $IPT -A INPUT -p udp --dport $x -j ONLYPRIVILEGIED done # Private services for x in $SERVICESTCP3 do $IPT -A INPUT -p tcp --dport $x -j ONLYTRUSTED done for x in $SERVICESUDP3 do $IPT -A INPUT -p udp --dport $x -j ONLYTRUSTED done if [ "$DOCKER" = "on" ]; then # Public services defined in SERVICESTCP1 & SERVICESUDP1 for dstport in $SERVICESTCP1 do $IPT -I MINIFW-DOCKER-PUB -p tcp --dport "$dstport" -j RETURN done for dstport in $SERVICESUDP1 do $IPT -I MINIFW-DOCKER-PUB -p udp --dport "$dstport" -j RETURN done # Privileged services (accessible from privileged & trusted IPs) for dstport in $SERVICESTCP2 do for srcip in $PRIVILEGIEDIPS do $IPT -I MINIFW-DOCKER-PRIVILEGED -p tcp -s "$srcip" --dport "$dstport" -j RETURN done for srcip in $TRUSTEDIPS do $IPT -I MINIFW-DOCKER-PRIVILEGED -p tcp -s "$srcip" --dport "$dstport" -j RETURN done done for dstport in $SERVICESUDP2 do for srcip in $PRIVILEGIEDIPS do $IPT -I MINIFW-DOCKER-PRIVILEGED -p udp -s "$srcip" --dport "$dstport" -j RETURN done for srcip in $TRUSTEDIPS do $IPT -I MINIFW-DOCKER-PRIVILEGED -p udp -s "$srcip" --dport "$dstport" -j RETURN done done # Trusted services (accessible from trusted IPs) for dstport in $SERVICESTCP3 do for srcip in $TRUSTEDIPS do $IPT -I MINIFW-DOCKER-TRUSTED -p tcp -s "$srcip" --dport "$dstport" -j RETURN done done for dstport in $SERVICESUDP3 do for srcip in $TRUSTEDIPS do $IPT -I MINIFW-DOCKER-TRUSTED -p udp -s "$srcip" --dport "$dstport" -j RETURN done done fi # External services ################### # DNS authorizations for x in $DNSSERVEURS do $IPT -A INPUT -p tcp ! --syn --sport 53 --dport $PORTSUSER -s $x -j ACCEPT $IPT -A INPUT -p udp --sport 53 --dport $PORTSUSER -s $x -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A OUTPUT -o $INT -p udp -d $x --dport 53 --match state --state NEW -j ACCEPT done # HTTP (TCP/80) authorizations for x in $HTTPSITES do $IPT -A INPUT -p tcp ! --syn --sport 80 --dport $PORTSUSER -s $x -j ACCEPT done # HTTPS (TCP/443) authorizations for x in $HTTPSSITES do $IPT -A INPUT -p tcp ! --syn --sport 443 --dport $PORTSUSER -s $x -j ACCEPT done # FTP (so complex protocol...) authorizations for x in $FTPSITES do # requests on Control connection $IPT -A INPUT -p tcp ! --syn --sport 21 --dport $PORTSUSER -s $x -j ACCEPT # FTP port-mode on Data Connection $IPT -A INPUT -p tcp --sport 20 --dport $PORTSUSER -s $x -j ACCEPT # FTP passive-mode on Data Connection # WARNING, this allow all connections on TCP ports > 1024 $IPT -A INPUT -p tcp ! --syn --sport $PORTSUSER --dport $PORTSUSER -s $x -j ACCEPT done # SSH authorizations for x in $SSHOK do $IPT -A INPUT -p tcp ! --syn --sport 22 -s $x -j ACCEPT done # SMTP authorizations for x in $SMTPOK do $IPT -A INPUT -p tcp ! --syn --sport 25 --dport $PORTSUSER -s $x -j ACCEPT done # secure SMTP (TCP/465 et TCP/587) authorizations for x in $SMTPSECUREOK do $IPT -A INPUT -p tcp ! --syn --sport 465 --dport $PORTSUSER -s $x -j ACCEPT $IPT -A INPUT -p tcp ! --syn --sport 587 --dport $PORTSUSER -s $x -j ACCEPT done # NTP authorizations for x in $NTPOK do $IPT -A INPUT -p udp --sport 123 -s $x -j ACCEPT $IPT -A OUTPUT -o $INT -p udp -d $x --dport 123 --match state --state NEW -j ACCEPT done # Always allow ICMP $IPT -A INPUT -p icmp -j ACCEPT [ "$IPV6" != "off" ] && $IPT6 -A INPUT -p icmpv6 -j ACCEPT # IPTables policy ################# # by default DROP INPUT packets $IPT -P INPUT DROP [ "$IPV6" != "off" ] && $IPT6 -P INPUT DROP # by default, no FORWARING (deprecated for Virtual Machines) #echo 0 > /proc/sys/net/ipv4/ip_forward #$IPT -P FORWARD DROP #$IPT6 -P FORWARD DROP # by default allow OUTPUT packets... but drop UDP packets (see OUTPUTDROP to drop OUTPUT packets) $IPT -P OUTPUT ACCEPT [ "$IPV6" != "off" ] && $IPT6 -P OUTPUT ACCEPT $IPT -A OUTPUT -o $INT -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT $IPT -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A OUTPUT -p udp -j DROP [ "$IPV6" != "off" ] && $IPT6 -A OUTPUT -o $INT -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT [ "$IPV6" != "off" ] && $IPT6 -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT [ "$IPV6" != "off" ] && $IPT6 -A OUTPUT -p udp -j DROP trap - INT TERM EXIT echo "...starting IPTables rules is now finish : OK" ;; stop) echo "Flush all rules and accept everything..." # Delete all rules $IPT -F INPUT $IPT -F OUTPUT $IPT -F LOG_DROP $IPT -F LOG_ACCEPT $IPT -F ONLYTRUSTED $IPT -F ONLYPRIVILEGIED $IPT -F NEEDRESTRICT [ "$DOCKER" = "off" ] && $IPT -t nat -F $IPT -t mangle -F [ "$IPV6" != "off" ] && $IPT6 -F INPUT [ "$IPV6" != "off" ] && $IPT6 -F OUTPUT if [ "$DOCKER" = "on" ]; then $IPT -F DOCKER-USER $IPT -A DOCKER-USER -j RETURN $IPT -F MINIFW-DOCKER-PUB $IPT -X MINIFW-DOCKER-PUB $IPT -F MINIFW-DOCKER-PRIVILEGED $IPT -X MINIFW-DOCKER-PRIVILEGED $IPT -F MINIFW-DOCKER-TRUSTED $IPT -X MINIFW-DOCKER-TRUSTED fi # Accept all $IPT -P INPUT ACCEPT $IPT -P OUTPUT ACCEPT [ "$IPV6" != "off" ] && $IPT6 -P INPUT ACCEPT [ "$IPV6" != "off" ] && $IPT6 -P OUTPUT ACCEPT #$IPT -P FORWARD ACCEPT #$IPT -t nat -P PREROUTING ACCEPT #$IPT -t nat -P POSTROUTING ACCEPT # Delete non-standard chains $IPT -X LOG_DROP $IPT -X LOG_ACCEPT $IPT -X ONLYPRIVILEGIED $IPT -X ONLYTRUSTED $IPT -X NEEDRESTRICT echo "...flushing IPTables rules is now finish : OK" ;; status) $IPT -L -n -v --line-numbers $IPT -t nat -L -n -v --line-numbers $IPT -t mangle -L -n -v --line-numbers $IPT6 -L -n -v --line-numbers $IPT6 -t mangle -L -n -v --line-numbers ;; reset) echo "Reset all IPTables counters..." $IPT -Z $IPT -t nat -Z $IPT -t mangle -Z [ "$IPV6" != "off" ] && $IPT6 -Z [ "$IPV6" != "off" ] && $IPT6 -t mangle -Z echo "...reseting IPTables counters is now finish : OK" ;; restart) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart|status|reset|squid}" exit 1 esac exit 0