#!/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-2022 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: minifirewall # 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 VERSION="22.03.5" NAME="minifirewall" # shellcheck disable=SC2034 DESC="Firewall designed for standalone server" set -u # Variables configuration ######################### config_file="/etc/default/minifirewall" includes_dir="/etc/minifirewall.d" # iptables paths IPT=$(command -v iptables) if [ -z "${IPT}" ]; then echo "Unable to find 'iptables\` command in PATH." >&2 exit 1 fi IPT6=$(command -v ip6tables) if [ -z "${IPT6}" ]; then echo "Unable to find 'ip6tables\` command in PATH." >&2 exit 1 fi # 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' # Configuration INT='' IPV6='' DOCKER='' INTLAN='' TRUSTEDIPS='' PRIVILEGIEDIPS='' SERVICESTCP1p='' SERVICESUDP1p='' SERVICESTCP1='' SERVICESUDP1='' SERVICESTCP2='' SERVICESUDP2='' SERVICESTCP3='' SERVICESUDP3='' DNSSERVEURS='' HTTPSITES='' HTTPSSITES='' FTPSITES='' SSHOK='' SMTPOK='' SMTPSECUREOK='' NTPOK='' PROXY='' PROXYBYPASS='' PROXYPORT='' BACKUPSERVERS='' LEGACY_CONFIG='off' ## pseudo dry-run : ## Uncomment and call these functions instead of the real iptables and ip6tables commands # IPT="fake_iptables" # IPT6="fake_ip6tables" # fake_iptables() { # printf "DRY-RUN iptables %s\n" "$*" # } # fake_ip6tables() { # printf "DRY-RUN ip6tables %s\n" "$*" # } ## Beware that commands executed from included files are not modified by this trick. sort_values() { echo "$*" | tr ' ' '\n' | sort -h } is_ipv6_enabled() { test "${IPV6}" != "off" } is_docker_enabled() { test "${DOCKER}" = "on" } is_proxy_enabled() { test "${PROXY}" = "on" } is_ipv6() { echo "$1" | grep -q ':' } is_legacy_config() { test "${LEGACY_CONFIG}" != "off" } chain_exists() { chain_name="$1" if [ $# -ge 2 ]; then intable="--table $2" else intable="" fi # shellcheck disable=SC2086 iptables ${intable} -nL "${chain_name}" >/dev/null 2>&1 } source_file_or_error() { file=$1 echo "...sourcing '${file}\`" tmpfile=$(mktemp --tmpdir=/tmp minifirewall.XXX) . "${file}" 2>"${tmpfile}" >&2 if [ -s "${tmpfile}" ]; then echo "${file} returns standard or error output (see below). Stopping." >&2 cat "${tmpfile}" exit 1 fi rm -f "${tmpfile}" } source_configuration() { if ! test -f ${config_file}; then echo "${config_file} does not exist" >&2 ## We still want to deal with this really old configuration file ## even if it has been deprecated since Debian 8 old_config_file="/etc/firewall.rc" if test -f ${old_config_file}; then echo "${old_config_file} is deprecated. Rename it to ${config_file}" >&2 fi exit 1 fi if grep -e "iptables" -e "ip6tables" "${config_file}" | grep -qvE "^#"; then # Backward compatible mode ########################### echo "Legacy config detected" LEGACY_CONFIG='on' # Non-backward compatible mode ############################### # If we ever want to remove the backward compatible mode # we can remove the two lines above and uncomment the lines below. # They break if any iptables/ip6tables command is found in the configuration file # echo "iptables/ip6tables commands found in ${config_file}." >&2 # echo "Move them in included files (in ${includes_dir})." >&2 # exit 1 fi if is_legacy_config; then # In this mode, we extract all variable definitions # to a temporary file that we can source. # It allow iptables/ip6tables commands to remain in the configuration file # and not interfere with the configuration step. tmp_config_file=$(mktemp --tmpdir=/tmp minifirewall.XXX) grep -E "^\s*[_a-zA-Z0-9]+=" "${config_file}" > "${tmp_config_file}" source_file_or_error "${tmp_config_file}" rm -f "${tmp_config_file}" else source_file_or_error "${config_file}" fi } source_includes() { if [ -d "${includes_dir}" ]; then include_files=$(find ${includes_dir} -type f -readable -not -name '*.*' | sort -h) for include_file in ${include_files}; do source_file_or_error "${include_file}" done fi } 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 ################################## # Set 1 to ignore broadcast pings (default) : "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS:=1}" # Set 1 to ignore bogus ICMP responses (default) : "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES:=1}" # Set 0 to disable source routing (default) : "${SYSCTL_ACCEPT_SOURCE_ROUTE:=0}" # Set 1 to enable TCP SYN cookies (default) # cf http://cr.yp.to/syncookies.html : "${SYSCTL_TCP_SYNCOOKIES:=1}" # Set 0 to disable ICMP redirects (default) : "${SYSCTL_ICMP_REDIRECTS:=0}" # Set 1 to enable Reverse Path filtering (default) # Set 0 if VRRP is used : "${SYSCTL_RP_FILTER:=1}" # Set 1 to log packets with inconsistent address (default) : "${SYSCTL_LOG_MARTIANS:=1}" if [ "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}" = "1" ] || [ "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}" = "0" ]; then echo "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts else echo "Invalid SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS value '${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}', must be '0' or '1'." >&2 exit 1 fi if [ "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}" = "1" ] || [ "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}" = "0" ]; then echo "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses else echo "Invalid SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES value '${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}', must be '0' or '1'." >&2 exit 1 fi if [ "${SYSCTL_ACCEPT_SOURCE_ROUTE}" = "1" ] || [ "${SYSCTL_ACCEPT_SOURCE_ROUTE}" = "0" ]; then for proc_sys_file in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo "${SYSCTL_ACCEPT_SOURCE_ROUTE}" > "${proc_sys_file}" done else echo "Invalid SYSCTL_ACCEPT_SOURCE_ROUTE value '${SYSCTL_ACCEPT_SOURCE_ROUTE}', must be '0' or '1'." >&2 exit 1 fi if [ "${SYSCTL_TCP_SYNCOOKIES}" = "1" ] || [ "${SYSCTL_TCP_SYNCOOKIES}" = "0" ]; then echo "${SYSCTL_TCP_SYNCOOKIES}" > /proc/sys/net/ipv4/tcp_syncookies else echo "Invalid SYSCTL_TCP_SYNCOOKIES value '${SYSCTL_TCP_SYNCOOKIES}', must be '0' or '1'." >&2 exit 1 fi if [ "${SYSCTL_ICMP_REDIRECTS}" = "1" ] || [ "${SYSCTL_ICMP_REDIRECTS}" = "0" ]; then for proc_sys_file in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo "${SYSCTL_ICMP_REDIRECTS}" > "${proc_sys_file}" done for proc_sys_file in /proc/sys/net/ipv4/conf/*/send_redirects; do echo "${SYSCTL_ICMP_REDIRECTS}" > "${proc_sys_file}" done else echo "Invalid SYSCTL_ICMP_REDIRECTS value '${SYSCTL_ICMP_REDIRECTS}', must be '0' or '1'." >&2 exit 1 fi if [ "${SYSCTL_RP_FILTER}" = "1" ] || [ "${SYSCTL_RP_FILTER}" = "0" ]; then for proc_sys_file in /proc/sys/net/ipv4/conf/*/rp_filter; do echo "${SYSCTL_RP_FILTER}" > "${proc_sys_file}" done else echo "Invalid SYSCTL_RP_FILTER value '${SYSCTL_RP_FILTER}', must be '0' or '1'." >&2 exit 1 fi if [ "${SYSCTL_LOG_MARTIANS}" = "1" ] || [ "${SYSCTL_LOG_MARTIANS}" = "0" ]; then for proc_sys_file in /proc/sys/net/ipv4/conf/*/log_martians; do echo "${SYSCTL_LOG_MARTIANS}" > "${proc_sys_file}" done else echo "Invalid SYSCTL_LOG_MARTIANS value '${SYSCTL_LOG_MARTIANS}', must be '0' or '1'." >&2 exit 1 fi # 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 is_ipv6_enabled; then ${IPT6} -N LOG_DROP ${IPT6} -A LOG_DROP -j LOG --log-prefix '[IPTABLES DROP] : ' ${IPT6} -A LOG_DROP -j DROP ${IPT6} -N LOG_ACCEPT ${IPT6} -A LOG_ACCEPT -j LOG --log-prefix '[IPTABLES ACCEPT] : ' ${IPT6} -A LOG_ACCEPT -j ACCEPT fi # Source additional rules and commands # * from legacy configuration file (/etc/default/minifirewall) # * from configuration directory (/etc/minifirewall.d/*) source_includes # IP/ports lists are sorted to have consistent ordering # You can disable this feature by simply commenting the following lines LOOPBACK=$(sort_values ${LOOPBACK}) INTLAN=$(sort_values ${INTLAN}) TRUSTEDIPS=$(sort_values ${TRUSTEDIPS}) PRIVILEGIEDIPS=$(sort_values ${PRIVILEGIEDIPS}) SERVICESTCP1p=$(sort_values ${SERVICESTCP1p}) SERVICESUDP1p=$(sort_values ${SERVICESUDP1p}) SERVICESTCP1=$(sort_values ${SERVICESTCP1}) SERVICESUDP1=$(sort_values ${SERVICESUDP1}) SERVICESTCP2=$(sort_values ${SERVICESTCP2}) SERVICESUDP2=$(sort_values ${SERVICESUDP2}) SERVICESTCP3=$(sort_values ${SERVICESTCP3}) SERVICESUDP3=$(sort_values ${SERVICESUDP3}) DNSSERVEURS=$(sort_values ${DNSSERVEURS}) HTTPSITES=$(sort_values ${HTTPSITES}) HTTPSSITES=$(sort_values ${HTTPSSITES}) FTPSITES=$(sort_values ${FTPSITES}) SSHOK=$(sort_values ${SSHOK}) SMTPOK=$(sort_values ${SMTPOK}) SMTPSECUREOK=$(sort_values ${SMTPSECUREOK}) NTPOK=$(sort_values ${NTPOK}) PROXYBYPASS=$(sort_values ${PROXYBYPASS}) BACKUPSERVERS=$(sort_values ${BACKUPSERVERS}) # Trusted ip addresses ${IPT} -N ONLYTRUSTED ${IPT} -A ONLYTRUSTED -j LOG_DROP if is_ipv6_enabled; then ${IPT6} -N ONLYTRUSTED ${IPT6} -A ONLYTRUSTED -j LOG_DROP fi for ip in ${TRUSTEDIPS}; do if is_ipv6 ${ip}; then if is_ipv6_enabled; then ${IPT6} -I ONLYTRUSTED -s ${ip} -j ACCEPT fi else ${IPT} -I ONLYTRUSTED -s ${ip} -j ACCEPT fi done # Privilegied ip addresses # (trusted ip addresses *are* privilegied) ${IPT} -N ONLYPRIVILEGIED ${IPT} -A ONLYPRIVILEGIED -j ONLYTRUSTED if is_ipv6_enabled; then ${IPT6} -N ONLYPRIVILEGIED ${IPT6} -A ONLYPRIVILEGIED -j ONLYTRUSTED fi for ip in ${PRIVILEGIEDIPS}; do if is_ipv6 ${ip}; then if is_ipv6_enabled; then ${IPT6} -I ONLYPRIVILEGIED -s ${ip} -j ACCEPT fi else ${IPT} -I ONLYPRIVILEGIED -s ${ip} -j ACCEPT fi done # Chain for restrictions (blacklist IPs/ranges) ${IPT} -N NEEDRESTRICT if is_ipv6_enabled; then ${IPT6} -N NEEDRESTRICT fi # We allow all on loopback interface ${IPT} -A INPUT -i lo -j ACCEPT if is_ipv6_enabled; then ${IPT6} -A INPUT -i lo -j ACCEPT fi # if OUTPUTDROP ${IPT} -A OUTPUT -o lo -j ACCEPT if is_ipv6_enabled; then ${IPT6} -A OUTPUT -o lo -j ACCEPT fi # 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 for IP in ${LOOPBACK}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -s ${IP} ! -i lo -j DROP fi else ${IPT} -A INPUT -s ${IP} ! -i lo -j DROP fi done if is_docker_enabled; then # WARN: IPv6 not yet supported for Docker rules ${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) for IP in ${INTLAN}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -s ${IP} -j ACCEPT fi else ${IPT} -A INPUT -s ${IP} -j ACCEPT fi done # Enable protection chain for sensible services for port in ${SERVICESTCP1p}; do ${IPT} -A INPUT -p tcp --dport ${port} -j NEEDRESTRICT if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp --dport ${port} -j NEEDRESTRICT fi done for port in ${SERVICESUDP1p}; do ${IPT} -A INPUT -p udp --dport ${port} -j NEEDRESTRICT if is_ipv6_enabled; then ${IPT6} -A INPUT -p udp --dport ${port} -j NEEDRESTRICT fi done # Public service for port in ${SERVICESTCP1}; do ${IPT} -A INPUT -p tcp --dport ${port} -j ACCEPT if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp --dport ${port} -j ACCEPT fi done for port in ${SERVICESUDP1}; do ${IPT} -A INPUT -p udp --dport ${port} -j ACCEPT if is_ipv6_enabled; then ${IPT6} -A INPUT -p udp --dport ${port} -j ACCEPT fi done # Privilegied services for port in ${SERVICESTCP2}; do ${IPT} -A INPUT -p tcp --dport ${port} -j ONLYPRIVILEGIED if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp --dport ${port} -j ONLYPRIVILEGIED fi done for port in ${SERVICESUDP2}; do ${IPT} -A INPUT -p udp --dport ${port} -j ONLYPRIVILEGIED if is_ipv6_enabled; then ${IPT6} -A INPUT -p udp --dport ${port} -j ONLYPRIVILEGIED fi done # Private services for port in ${SERVICESTCP3}; do ${IPT} -A INPUT -p tcp --dport ${port} -j ONLYTRUSTED if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp --dport ${port} -j ONLYTRUSTED fi done for port in ${SERVICESUDP3}; do ${IPT} -A INPUT -p udp --dport ${port} -j ONLYTRUSTED if is_ipv6_enabled; then ${IPT6} -A INPUT -p udp --dport ${port} -j ONLYTRUSTED fi done if is_docker_enabled; then # WARN: IPv6 not yet supported # 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 if ! is_ipv6 ${srcip}; then ${IPT} -I MINIFW-DOCKER-PRIVILEGED -p tcp -s "${srcip}" --dport "${dstport}" -j RETURN fi done for srcip in ${TRUSTEDIPS}; do if ! is_ipv6 ${srcip}; then ${IPT} -I MINIFW-DOCKER-PRIVILEGED -p tcp -s "${srcip}" --dport "${dstport}" -j RETURN fi done done for dstport in ${SERVICESUDP2}; do for srcip in ${PRIVILEGIEDIPS}; do if ! is_ipv6 ${srcip}; then ${IPT} -I MINIFW-DOCKER-PRIVILEGED -p udp -s "${srcip}" --dport "${dstport}" -j RETURN fi done for srcip in ${TRUSTEDIPS}; do if ! is_ipv6 ${srcip}; then ${IPT} -I MINIFW-DOCKER-PRIVILEGED -p udp -s "${srcip}" --dport "${dstport}" -j RETURN fi done done # Trusted services (accessible from trusted IPs) for dstport in ${SERVICESTCP3}; do for srcip in ${TRUSTEDIPS}; do if ! is_ipv6 ${srcip}; then ${IPT} -I MINIFW-DOCKER-TRUSTED -p tcp -s "${srcip}" --dport "${dstport}" -j RETURN fi done done for dstport in ${SERVICESUDP3}; do for srcip in ${TRUSTEDIPS}; do if ! is_ipv6 ${srcip}; then ${IPT} -I MINIFW-DOCKER-TRUSTED -p udp -s "${srcip}" --dport "${dstport}" -j RETURN fi done done fi # External services ################### # DNS authorizations for IP in ${DNSSERVEURS}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp ! --syn --sport 53 --dport ${PORTSUSER} -s ${IP} -j ACCEPT ${IPT6} -A INPUT -p udp --sport 53 --dport ${PORTSUSER} -s ${IP} -m state --state ESTABLISHED,RELATED -j ACCEPT ${IPT6} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 53 --match state --state NEW -j ACCEPT fi else ${IPT} -A INPUT -p tcp ! --syn --sport 53 --dport ${PORTSUSER} -s ${IP} -j ACCEPT ${IPT} -A INPUT -p udp --sport 53 --dport ${PORTSUSER} -s ${IP} -m state --state ESTABLISHED,RELATED -j ACCEPT ${IPT} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 53 --match state --state NEW -j ACCEPT fi done # HTTP (TCP/80) authorizations for IP in ${HTTPSITES}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp ! --syn --sport 80 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi else ${IPT} -A INPUT -p tcp ! --syn --sport 80 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi done # HTTPS (TCP/443) authorizations for IP in ${HTTPSSITES}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp ! --syn --sport 443 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi else ${IPT} -A INPUT -p tcp ! --syn --sport 443 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi done # FTP (so complex protocol...) authorizations for IP in ${FTPSITES}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then # requests on Control connection ${IPT6} -A INPUT -p tcp ! --syn --sport 21 --dport ${PORTSUSER} -s ${IP} -j ACCEPT # FTP port-mode on Data Connection ${IPT6} -A INPUT -p tcp --sport 20 --dport ${PORTSUSER} -s ${IP} -j ACCEPT # FTP passive-mode on Data Connection # WARNING, this allow all connections on TCP ports > 1024 ${IPT6} -A INPUT -p tcp ! --syn --sport ${PORTSUSER} --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi else # requests on Control connection ${IPT} -A INPUT -p tcp ! --syn --sport 21 --dport ${PORTSUSER} -s ${IP} -j ACCEPT # FTP port-mode on Data Connection ${IPT} -A INPUT -p tcp --sport 20 --dport ${PORTSUSER} -s ${IP} -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 ${IP} -j ACCEPT fi done # SSH authorizations for IP in ${SSHOK}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp ! --syn --sport 22 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi else ${IPT} -A INPUT -p tcp ! --syn --sport 22 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi done # SMTP authorizations for IP in ${SMTPOK}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp ! --syn --sport 25 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi else ${IPT} -A INPUT -p tcp ! --syn --sport 25 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi done # secure SMTP (TCP/465 et TCP/587) authorizations for IP in ${SMTPSECUREOK}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp ! --syn --sport 465 --dport ${PORTSUSER} -s ${IP} -j ACCEPT ${IPT6} -A INPUT -p tcp ! --syn --sport 587 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi else ${IPT} -A INPUT -p tcp ! --syn --sport 465 --dport ${PORTSUSER} -s ${IP} -j ACCEPT ${IPT} -A INPUT -p tcp ! --syn --sport 587 --dport ${PORTSUSER} -s ${IP} -j ACCEPT fi done # NTP authorizations for IP in ${NTPOK}; do if is_ipv6 ${IP}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -p udp --sport 123 -s ${IP} -j ACCEPT ${IPT6} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 123 --match state --state NEW -j ACCEPT fi else ${IPT} -A INPUT -p udp --sport 123 -s ${IP} -j ACCEPT ${IPT} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 123 --match state --state NEW -j ACCEPT fi done # Proxy (Squid) if is_proxy_enabled; then # WARN: Squid only listen on IPv4 yet # TODO: verify that the pattern used for IPv4 is relevant with IPv6 ${IPT} -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner proxy -j ACCEPT for dstip in ${PROXYBYPASS}; do if ! is_ipv6 ${dstip}; then ${IPT} -t nat -A OUTPUT -p tcp --dport 80 -d "${dstip}" -j ACCEPT fi done ${IPT} -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port "${PROXYPORT:-'8888'}" fi # Output for backup servers for server in ${BACKUPSERVERS}; do server_port=$(echo "${server}" | awk -F : '{print $(NF)}') server_ip=$(echo "${server}" | sed -e "s/:${server_port}$//") if [ -n "${server_ip}" ] && [ -n "${server_port}" ]; then if is_ipv6 ${server_ip}; then if is_ipv6_enabled; then ${IPT6} -A INPUT -p tcp --sport "${server_port}" --dport 1024:65535 -s "${server_ip}" -m state --state ESTABLISHED,RELATED -j ACCEPT fi else ${IPT} -A INPUT -p tcp --sport "${server_port}" --dport 1024:65535 -s "${server_ip}" -m state --state ESTABLISHED,RELATED -j ACCEPT fi else echo "Unrecognized syntax for BACKUPSERVERS '${server}\`. Use space-separated IP:PORT tuples." >&2 exit 1 fi done # Always allow ICMP ${IPT} -A INPUT -p icmp -j ACCEPT if is_ipv6_enabled; then ${IPT6} -A INPUT -p icmpv6 -j ACCEPT fi # IPTables policy ################# # by default DROP INPUT packets ${IPT} -P INPUT DROP if is_ipv6_enabled; then ${IPT6} -P INPUT DROP fi # by default, no FORWARDING (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 if is_ipv6_enabled; then ${IPT6} -P OUTPUT ACCEPT fi ${IPT} -A OUTPUT -o ${INT} -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT if is_ipv6_enabled; then ${IPT6} -A OUTPUT -o ${INT} -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT fi ${IPT} -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT if is_ipv6_enabled; then ${IPT6} -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT fi ${IPT} -A OUTPUT -p udp -j DROP if is_ipv6_enabled; then ${IPT6} -A OUTPUT -p udp -j DROP fi if is_legacy_config; then source_file_or_error "${config_file}" fi 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 if is_ipv6_enabled; then ${IPT6} -F INPUT fi ${IPT} -F OUTPUT if is_ipv6_enabled; then ${IPT6} -F OUTPUT fi ${IPT} -F LOG_DROP ${IPT} -F LOG_ACCEPT ${IPT} -F ONLYTRUSTED ${IPT} -F ONLYPRIVILEGIED ${IPT} -F NEEDRESTRICT if is_ipv6_enabled; then ${IPT6} -F LOG_DROP ${IPT6} -F LOG_ACCEPT ${IPT6} -F ONLYTRUSTED ${IPT6} -F ONLYPRIVILEGIED ${IPT6} -F NEEDRESTRICT fi ${IPT} -t mangle -F if is_ipv6_enabled; then ${IPT6} -t mangle -F fi if is_docker_enabled; then # WARN: IPv6 not yet supported ${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 else ${IPT} -t nat -F fi # Accept all ${IPT} -P INPUT ACCEPT if is_ipv6_enabled; then ${IPT6} -P INPUT ACCEPT fi ${IPT} -P OUTPUT ACCEPT if is_ipv6_enabled; then ${IPT6} -P OUTPUT ACCEPT fi #${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 if is_ipv6_enabled; then ${IPT6} -X LOG_DROP ${IPT6} -X LOG_ACCEPT ${IPT6} -X ONLYPRIVILEGIED ${IPT6} -X ONLYTRUSTED ${IPT6} -X NEEDRESTRICT fi echo "...flushing IPTables rules is now finish : OK" } status() { printf "#### iptables --list ###############################\n" ${IPT} --list --numeric --verbose --line-numbers printf "\n### iptables --table nat --list ####################\n" ${IPT} --table nat --list --numeric --verbose --line-numbers printf "\n#### iptables --table mangle --list ################\n" ${IPT} --table mangle --list --numeric --verbose --line-numbers if is_ipv6_enabled; then printf "\n#### ip6tables --list ##############################\n" ${IPT6} --list --numeric --verbose --line-numbers printf "\n#### ip6tables --table mangle --list ###############\n" ${IPT6} --table mangle --list --numeric --verbose --line-numbers fi } fi } reset() { echo "Reset all IPTables counters..." ${IPT} -Z if is_ipv6_enabled; then ${IPT6} -Z fi ${IPT} -t nat -Z ${IPT} -t mangle -Z if is_ipv6_enabled; then ${IPT6} -t mangle -Z fi echo "...reseting IPTables counters is now finish : OK" } echo "${NAME} version ${VERSION}" source_configuration case "${1:-''}" in start) start ;; stop) stop ;; status) status ;; reset) reset ;; restart) stop start ;; *) echo "Usage: $0 {start|stop|restart|status|reset}" exit 1 ;; esac exit 0