Compare commits

..

1 commit
master ... dev

Author SHA1 Message Date
Victor LABORIE 4cce49988b Full IPv6 support 2019-08-08 15:22:34 +02:00
7 changed files with 366 additions and 2050 deletions

View file

@ -1,76 +0,0 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project **does not adhere to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)**.
## [Unreleased]
### Added
* safe-start and safe-restart
* Chain MINIFW-DOCKER-INPUT-MANUAL for more granular/manual filtering of incoming traffic to services inside docker
### Changed
### Deprecated
### Removed
### Fixed
* fix interactive mode detection
### Security
## [23.07] - 2023-07-04
### Added
* new "check-active-config" command to check if the active configuration is th e same as the one persisted to disk
### Changed
* capture cmp(1) error output
* early error if script is not run as root
* extract "include_files" function
* print help/usage with list of possible commands
## [23.02] - 2023-02-01
* Export status without colors (to keep clean diffs)
## [22.06] - 2022-06-06
### Changed
* Configure sysctl values to IPv6 when applicable
### Fixed
* status output (number of # in headers)
## [22.05] - 2022-05-10
#### Fixed
* status output (number of # in headers)
## [22.04] - 2022-04-28
### Added
* markers for each section of status output
* store and compare state between restart
* colorize output if terminal supports colors
* simple syslog logging
* "version" action
### Changed
* use long options in some places
* output is normalized
* source legacy config after macros but before DROP policy
* source configuration only for valid actions
* improve legacy config parsing
### Fixed
* force remove temporary files

View file

@ -8,40 +8,35 @@ See https://gitea.evolix.org/evolix/minifirewall
## Install
~~~
install --mode 0700 minifirewall /etc/init.d/minifirewall
install --mode 0600 minifirewall.conf /etc/default/minifirewall
mkdir --mode 0700 /etc/minifirewall.d
install -m 0700 minifirewall /etc/init.d/minifirewall
install -m 0600 minifirewall.conf /etc/default/minifirewall
~~~
## Config
Edit /etc/default/minifirewall file:
* If your interface is not `eth0`, change `INT` variable
* If you don't use IPv6, set `IPv6='off'`
* Modify `INTLAN` variable, probably with your `<IP>/32` or your local network if you trust it
* Set your trusted and privilegied IP addresses in `TRUSTEDIPS` and `PRIVILEGIEDIPS` variables
* Authorize your **public** services with `SERVICESTCP1` and `SERVICESUDP1` variables
* Authorize your **semi-public** services (only for `TRUSTEDIPS` and `PRIVILEGIEDIPS` ) with `SERVICESTCP2` and `SERVICESUDP2` variables
* Authorize your **private** services (only for `TRUSTEDIPS` ) with `SERVICESTCP3` and `SERVICESUDP3` variables
* If your interface is not _eth0_, change *INT* variable
* If you don't IPv6 : *IPv6=off*
* Modify *INTLAN* variable, probably with your *IP/32* or your local network if you trust it
* Set your trusted and privilegied IP addresses in *TRUSTEDIPS* and *PRIVILEGIEDIPS* variables
* Authorize your +public+ services with *SERVICESTCP1* and *SERVICESUDP1* variables
* Authorize your +semi-public+ services (only for *TRUSTEDIPS* and *PRIVILEGIEDIPS* ) with *SERVICESTCP2* and *SERVICESUDP2* variables
* Authorize your +private+ services (only for *TRUSTEDIPS* ) with *SERVICESTCP3* and *SERVICESUDP3* variables
* Configure your authorizations for external services : DNS, HTTP, HTTPS, SMTP, SSH, NTP
* Add your specific rules
### Docker
To use minifirewall with Docker you need to change the variable `DOCKER='on'`
Then, authorisation for public/semi-public/private ports will also work for dockerized services
**WARNING** : When the port mapping on the host is different than in the container (ie: listen on :8090 on the host, but the service in the container listen on :8080)
you need to use the port used by the container (ie: 8080) in the public/semi-public/private port list
## Usage
~~~
/etc/init.d/minifirewall start/stop/restart
~~~
If you want to add minifirewall in boot sequence, add the start command to `/usr/share/scripts/alert5`.
If you want to add minifirewall in boot sequence:
~~~
systemctl enable minifirewall
~~~
## License

20
Vagrantfile vendored
View file

@ -1,6 +1,8 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant::DEFAULT_SERVER_URL.replace('https://vagrantcloud.com')
# Load ~/.VagrantFile if exist, permit local config provider
vagrantfile = File.join("#{Dir.home}", '.VagrantFile')
load File.expand_path(vagrantfile) if File.exists?(vagrantfile)
@ -9,26 +11,16 @@ Vagrant.configure('2') do |config|
config.vm.synced_folder "./", "/vagrant", type: "rsync", rsync__exclude: [ '.vagrant', '.git' ]
config.ssh.shell="/bin/sh"
deps = <<SCRIPT
DEBIAN_FRONTEND=noninteractive apt-get -yq install iptables
SCRIPT
install = <<SCRIPT
$install = <<SCRIPT
DEBIAN_FRONTEND=noninteractive apt-get -yq install iptables
ln -fs /vagrant/minifirewall /etc/init.d/minifirewall
ln -fs /vagrant/minifirewall.conf /etc/default/minifirewall
mkdir -p /etc/minifirewall.d
SCRIPT
post = <<SCRIPT
sed -i "s|^TRUSTEDIPS='|TRUSTEDIPS='192.168.121.0/24 |" /etc/default/minifirewall
SCRIPT
config.vm.define "minifirewall" do |node|
node.vm.hostname = "minifirewall"
node.vm.box = "debian/bookworm64"
config.vm.provision "deps", type: "shell", inline: deps
config.vm.provision "install", type: "shell", inline: install
config.vm.provision "post", type: "shell", inline: post
node.vm.box = "debian/stretch64"
config.vm.provision "install", type: "shell", :inline => $install
end
end

View file

@ -1,11 +1,10 @@
#!/bin/sh
# shellcheck disable=SC2059
# minifirewall is a shell script for easy firewalling on a standalone server
# It uses netfilter/iptables http://netfilter.org/ designed for recent Linux kernel
# See https://gitea.evolix.org/evolix/minifirewall
# minifirewall is shellscripts for easy firewalling on a standalone server
# we used netfilter/iptables http://netfilter.org/ designed for recent Linux kernel
# See https://forge.evolix.org/projects/minifirewall
# Copyright (c) 2007-2023 Evolix
# Copyright (c) 2007-2015 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
@ -18,7 +17,7 @@
#
### BEGIN INIT INFO
# Provides: minifirewall
# Provides: minfirewall
# Required-Start:
# Required-Stop:
# Should-Start: $network $syslog $named
@ -29,39 +28,20 @@
# Description: Firewall designed for standalone server
### END INIT INFO
VERSION="23.07"
DESC="minifirewall"
NAME="minifirewall"
PROGNAME="minifirewall"
# shellcheck disable=SC2034
DESC="Firewall designed for standalone server"
set -u
if [ "$(id -u)" -ne "0" ] ; then
echo "${PROGNAME} must be run as root." >&2
exit 1
fi
# 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
IPT=/sbin/iptables
IPT6=/sbin/ip6tables
# TCP/IP variables
LOOPBACK='127.0.0.0/8'
LOOPBACK6='::1'
CLASSA='10.0.0.0/8'
CLASSB='172.16.0.0/12'
CLASSC='192.168.0.0/16'
@ -72,1273 +52,369 @@ BROAD='255.255.255.255'
PORTSROOT='0:1023'
PORTSUSER='1024:65535'
ipxtables() {
set +e
ip=$1
echo "$ip"|grep -q ":"
if [ $? -ne 0 ]; then
echo $IPT
else
echo $IPT6
fi
set -e
}
ipalltables() {
iptables $@
ip6tables $@
}
check_addr() {
set +e
addr=$1
echo $addr|grep -q "/"
if [ $? -eq 0 ]; then
echo $addr
else
host=$(host $addr)
if [ $? -ne 0 ]; then
echo "WARNING: $addr is invalid !" >&2
else
echo "$host"|grep -q "address"
if [ $? -eq 0 ]; then
echo "$host"|grep -v "mail"|awk '{ print $NF }'|while read ip; do
echo $ip
done
else
echo $addr
fi
fi
fi
set -e
}
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
########################
ipalltables -N LOG_DROP
ipalltables -A LOG_DROP -j LOG #--log-prefix '[IPTABLES DROP] : '
ipalltables -A LOG_DROP -j DROP
ipalltables -N LOG_ACCEPT
ipalltables -A LOG_ACCEPT -j LOG #--log-prefix '[IPTABLES ACCEPT] : '
ipalltables -A LOG_ACCEPT -j ACCEPT
# Configuration
oldconfigfile="/etc/firewall.rc"
configfile="/etc/default/minifirewall"
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'
STATE_FILE_LATEST='/var/run/minifirewall_state_latest'
STATE_FILE_CURRENT='/var/run/minifirewall_state_current'
STATE_FILE_PREVIOUS='/var/run/minifirewall_state_previous'
STATE_FILE_DIFF='/var/run/minifirewall_state_diff'
ACTIVE_CONFIG='/var/run/minifirewall_active_config'
ACTIVE_CONFIG_DIFF="${ACTIVE_CONFIG}.diff"
SAFETY_LOCK='/var/run/minifirewall_safety.lock'
SAFETY_OUTPUT='/var/run/minifirewall_safety.out'
SAFETY_TIMER=30
LOGGER_BIN=$(command -v logger)
# No colors by default
RED=''
GREEN=''
YELLOW=''
BLUE=''
MAGENTA=''
CYAN=''
WHITE=''
BOLD=''
RESET=''
# check if stdout is a terminal...
if [ -t 1 ]; then
INTERACTIVE=1
# see if it supports colors...
ncolors=$(tput colors)
# shellcheck disable=SC2086
if [ -n "${ncolors}" ] && [ ${ncolors} -ge 8 ]; then
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
WHITE=$(tput setaf 7)
BOLD=$(tput bold)
RESET='\e[m'
fi
else
INTERACTIVE=0
if test -f $oldconfigfile; then
echo "$oldconfigfile is deprecated, rename to $configfile" >&2
exit 1
fi
readonly INTERACTIVE
## 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.
is_interactive() {
test "${INTERACTIVE}" = "1"
}
remove_colors() {
sed -r 's/\x1B\[(;?[0-9]{1,3})+[mGK]//g'
}
syslog_info() {
if [ -x "${LOGGER_BIN}" ]; then
${LOGGER_BIN} -t "${PROGNAME}" -p daemon.info "$1"
fi
}
syslog_error() {
if [ -x "${LOGGER_BIN}" ]; then
${LOGGER_BIN} -t "${PROGNAME}" -p daemon.error "$1"
fi
}
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
syslog_info "sourcing \`${file}'"
printf "${BLUE}sourcing \`%s'${RESET}\n" "${file}"
tmpfile=$(mktemp --tmpdir=/tmp minifirewall.XXX)
. "${file}" 2>"${tmpfile}" >&2
if [ -s "${tmpfile}" ]; then
syslog_error "Error while sourcing ${file}"
printf "${RED}%s returns standard or error output (see below). Stopping.${RESET}\n" ${file} >&2
cat "${tmpfile}"
exit 1
fi
rm -f "${tmpfile}"
}
source_configuration() {
if ! test -f ${config_file}; then
printf "${RED}%s does not exist${RESET}\n" "${config_file}" >&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
printf "${YELLOW}%s is deprecated and ignored. Rename it to %s${RESET}\n" "${old_config_file}" "${config_file}" >&2
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
fi
rm $tmpfile
# If we find something other than a blank line, a comment or a variable assignment
if grep --quiet --extended-regexp --invert-match "^\s*(#|$|\w+=)" "${config_file}"; then
# Backward compatible mode
###########################
printf "${YELLOW}legacy config detected${RESET}\n"
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)
# get only variable assignments
grep -E "^\s*\w+=" "${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
}
include_files() {
if [ -d "${includes_dir}" ]; then
find ${includes_dir} -type f -readable -not -name '*.*' | sort -h
else
echo ""
fi
}
source_includes() {
if [ -d "${includes_dir}" ]; then
for include_file in $(include_files); do
source_file_or_error "${include_file}"
# Trusted ip addresses
ipalltables -N ONLYTRUSTED
ipalltables -A ONLYTRUSTED -j LOG_DROP
for addr in $TRUSTEDIPS; do
check_addr $addr|while read ip; do
$(ipxtables $ip) -I ONLYTRUSTED -s $ip -j ACCEPT
done
fi
}
filter_config_file() {
# Remove lines with:
# * empty or only whitespaces
# * comments
grep --extended-regexp --invert-match -e "^(\s*#)" -e "^\s*$" "${1}"
}
save_active_configuration() {
dest_file=${1}
rm -f "${dest_file}"
done
echo "# ${config_file}" >> "${dest_file}"
filter_config_file "${config_file}" >> "${dest_file}"
found_include_files=$(include_files)
if [ -n "${found_include_files}" ]; then
for include_file in ${found_include_files}; do
echo "# ${include_file}" >> "${dest_file}"
filter_config_file "${include_file}" >> "${dest_file}"
# Privilegied ip addresses
# (trusted ip addresses *are* privilegied)
ipalltables -N ONLYPRIVILEGIED
ipalltables -A ONLYPRIVILEGIED -j ONLYTRUSTED
for addr in $PRIVILEGIEDIPS; do
check_addr $addr|while read ip; do
$(ipxtables $ip) -I ONLYPRIVILEGIED -s $ip -j ACCEPT
done
fi
}
check_active_configuration() {
# NRPE-compatible return codes
# 0: OK
# 1: WARNING
# 2: CRITICAL
# 3: UNKNOWN
rc=0
done
if [ -f "${ACTIVE_CONFIG}" ]; then
cmp_bin=$(command -v cmp)
diff_bin=$(command -v diff)
# Chain for restrictions (blacklist IPs/ranges)
ipalltables -N NEEDRESTRICT
if [ -z "${cmp_bin}" ]; then
printf "${YELLOW}WARNING: Skipped active configuration check (Can't find cmp(1) command)${RESET}\n"
rc=1
elif [ -z "${diff_bin}" ]; then
printf "${YELLOW}WARNING: Skipped active configuration check (Can't find diff(1) command)${RESET}\n"
rc=1
else
rm -f "${ACTIVE_CONFIG_DIFF}"
# We allow all on loopback interface
ipalltables -A INPUT -i lo -j ACCEPT
# if OUTPUTDROP
ipalltables -A OUTPUT -o lo -j ACCEPT
tmp_config_file=$(mktemp --tmpdir=/tmp minifirewall.XXX)
save_active_configuration "${tmp_config_file}"
# We avoid "martians" packets, typical when W32/Blaster virus
# attacked windowsupdate.com and DNS was changed to 127.0.0.1
# ipalltables -t NAT -I PREROUTING -s $LOOPBACK -i ! lo -j DROP
$IPT -A INPUT -s $LOOPBACK ! -i lo -j DROP
$IPT6 -A INPUT -s $LOOPBACK6 ! -i lo -j DROP
cmp_result=$(cmp "${ACTIVE_CONFIG}" "${tmp_config_file}" 2>&1)
cmp_rc=$?
if [ ${cmp_rc} -eq 0 ]; then
# echo " config has not changed since latest start"
printf "${GREEN}OK: Active configuration is up-to-date.${RESET}\n"
rc=0
elif [ ${cmp_rc} -eq 1 ]; then
diff -u "${ACTIVE_CONFIG}" "${tmp_config_file}" > "${ACTIVE_CONFIG_DIFF}"
# Local services restrictions
#############################
printf "${RED}CRITICAL: Active configuration is not up-to-date (minifirewall not restarted after config change?), check %s${RESET}\n" "${ACTIVE_CONFIG_DIFF}"
rc=2
else
printf "${RED}CRITICAL: Error while comparing rules:${RESET}\n"
printf "${cmp_result}\n"
rc=2
fi
# Allow services for $INTLAN (local server or local network)
$IPT -A INPUT -s $INTLAN -j ACCEPT
rm -f "${tmp_config_file}"
fi
else
printf "${YELLOW}WARNING: Skipped active configuration check (missing file ${ACTIVE_CONFIG})${RESET}\n"
rc=1
fi
exit ${rc}
}
check_unpersisted_state() {
cmp_bin=$(command -v cmp)
diff_bin=$(command -v diff)
# Enable protection chain for sensible services
for x in $SERVICESTCP1p
do
ipalltables -A INPUT -p tcp --dport $x -j NEEDRESTRICT
done
if [ -z "${cmp_bin}" ]; then
printf "${YELLOW}skip state comparison (Can't find cmp command)${RESET}\n" >&2
elif [ -z "${diff_bin}" ]; then
printf "${YELLOW}skip state comparison (Can't find diff command)${RESET}\n" >&2
else
# store current state (without colors)
mkdir -p "$(dirname "${STATE_FILE_CURRENT}")"
status_without_numbers | remove_colors > "${STATE_FILE_CURRENT}"
for x in $SERVICESUDP1p
do
ipalltables -A INPUT -p udp --dport $x -j NEEDRESTRICT
done
# clean previous diff file
rm -f "${STATE_FILE_DIFF}"
# Public service
for x in $SERVICESTCP1
do
ipalltables -A INPUT -p tcp --dport $x -j ACCEPT
done
if [ -f "${STATE_FILE_LATEST}" ]; then
cmp_result=$(cmp "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}" 2>&1)
cmp_rc=$?
for x in $SERVICESUDP1
do
ipalltables -A INPUT -p udp --dport $x -j ACCEPT
done
if [ ${cmp_rc} -eq 0 ]; then
# echo " rules have not changed since latest start"
:
elif [ ${cmp_rc} -eq 1 ]; then
diff -u "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}" > "${STATE_FILE_DIFF}"
printf "${YELLOW}WARNING: current state is different than persisted state, check %s${RESET}\n" "${STATE_FILE_DIFF}" >&2
else
printf "${RED}ERROR comparing rules:${RESET}\n" >&2
echo "${cmp_result}" >&2
fi
fi
# cleanup
rm -f "${STATE_FILE_CURRENT}"
fi
}
report_state_changes() {
cmp_bin=$(command -v cmp)
diff_bin=$(command -v diff)
# Privilegied services
for x in $SERVICESTCP2
do
ipalltables -A INPUT -p tcp --dport $x -j ONLYPRIVILEGIED
done
if [ -z "${cmp_bin}" ]; then
printf "${YELLOW}skip state comparison (Can't find cmp command)${RESET}\n" >&2
return
elif [ -z "${diff_bin}" ]; then
printf "${YELLOW}skip state comparison (Can't find diff command)${RESET}\n" >&2
else
# If there is a known state
# let's compare it with the current state
if [ -f "${STATE_FILE_LATEST}" ]; then
check_unpersisted_state
fi
for x in $SERVICESUDP2
do
ipalltables -A INPUT -p udp --dport $x -j ONLYPRIVILEGIED
done
# Then reset the known state (without colors)
mkdir -p "$(dirname "${STATE_FILE_LATEST}")"
status_without_numbers | remove_colors > "${STATE_FILE_LATEST}"
# Private services
for x in $SERVICESTCP3
do
ipalltables -A INPUT -p tcp --dport $x -j ONLYTRUSTED
done
# But if there is a previous known state
# let's compare with the new known state
if [ -f "${STATE_FILE_PREVIOUS}" ]; then
cmp_result=$(cmp "${STATE_FILE_PREVIOUS}" "${STATE_FILE_LATEST}" 2>&1)
cmp_rc=$?
for x in $SERVICESUDP3
do
ipalltables -A INPUT -p udp --dport $x -j ONLYTRUSTED
done
if [ ${cmp_rc} -eq 0 ]; then
# echo "Rules have not changed since previous start"
:
elif [ ${cmp_rc} -eq 1 ]; then
diff -u "${STATE_FILE_PREVIOUS}" "${STATE_FILE_LATEST}" > "${STATE_FILE_DIFF}"
printf "${YELLOW}INFO: rules have changed since latest start, check %s${RESET}\n" "${STATE_FILE_DIFF}" >&2
else
printf "${RED}ERROR comparing rules:${RESET}\n" >&2
echo "${cmp_result}" >&2
fi
fi
fi
}
start() {
syslog_info "starting"
printf "${BOLD}${PROGNAME} starting${RESET}\n"
# External services
###################
# Stop and warn if error!
set -e
trap 'printf "${RED}${PROGNAME} failed : an error occured during startup.${RESET}\n"; syslog_error "failed" ' INT TERM EXIT
# DNS authorizations
for x in $DNSSERVEURS
do
ipalltables -A INPUT -p tcp ! --syn --sport 53 --dport $PORTSUSER -s $x -j ACCEPT
ipalltables -A INPUT -p udp --sport 53 --dport $PORTSUSER -s $x -m state --state ESTABLISHED,RELATED -j ACCEPT
ipalltables -A OUTPUT -o $INT -p udp -d $x --dport 53 --match state --state NEW -j ACCEPT
done
# 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
# Apparently not applicable to IPv6
else
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS" "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}" >&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
# Apparently not applicable to IPv6
else
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES" "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}" >&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}"
# HTTP (TCP/80) authorizations
for addr in $HTTPSITES
do
check_addr $addr|while read ip; do
$(ipxtables $ip) -A INPUT -p tcp ! --syn --sport 80 --dport $PORTSUSER -s $ip -j ACCEPT
done
if is_ipv6_enabled; then
for proc_sys_file in /proc/sys/net/ipv6/conf/*/accept_source_route; do
echo "${SYSCTL_ACCEPT_SOURCE_ROUTE}" > "${proc_sys_file}"
done
fi
else
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_ACCEPT_SOURCE_ROUTE" "${SYSCTL_ACCEPT_SOURCE_ROUTE}" >&2
exit 1
fi
done
if [ "${SYSCTL_TCP_SYNCOOKIES}" = "1" ] || [ "${SYSCTL_TCP_SYNCOOKIES}" = "0" ]; then
echo "${SYSCTL_TCP_SYNCOOKIES}" > /proc/sys/net/ipv4/tcp_syncookies
# Apparently not applicable to IPv6
else
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_TCP_SYNCOOKIES" "${SYSCTL_TCP_SYNCOOKIES}" >&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}"
# HTTPS (TCP/443) authorizations
for addr in $HTTPSSITES
do
check_addr $addr|while read ip; do
$(ipxtables $ip) -A INPUT -p tcp ! --syn --sport 443 --dport $PORTSUSER -s $ip -j ACCEPT
done
for proc_sys_file in /proc/sys/net/ipv4/conf/*/send_redirects; do
echo "${SYSCTL_ICMP_REDIRECTS}" > "${proc_sys_file}"
done
if is_ipv6_enabled; then
for proc_sys_file in /proc/sys/net/ipv6/conf/*/accept_redirects; do
echo "${SYSCTL_ICMP_REDIRECTS}" > "${proc_sys_file}"
done
fi
else
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_ICMP_REDIRECTS" "${SYSCTL_ICMP_REDIRECTS}" >&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
# Apparently not applicable to IPv6
else
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_RP_FILTER" "${SYSCTL_RP_FILTER}" >&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
# Apparently not applicable to IPv6
else
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_LOG_MARTIANS" "${SYSCTL_LOG_MARTIANS}" >&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
if is_docker_enabled; then
${IPT} -N MINIFW-DOCKER-INPUT-MANUAL
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
# FTP (so complex protocol...) authorizations
for x in $FTPSITES
do
# requests on Control connection
ipalltables -A INPUT -p tcp ! --syn --sport 21 --dport $PORTSUSER -s $x -j ACCEPT
# FTP port-mode on Data Connection
ipalltables -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
ipalltables -A INPUT -p tcp ! --syn --sport $PORTSUSER --dport $PORTSUSER -s $x -j ACCEPT
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
# Chain MINIFW-DOCKER-INPUT-MANUAL is created earlier, to allow usage in additionnal config/command files
${IPT} -A MINIFW-DOCKER-INPUT-MANUAL -j MINIFW-DOCKER-PUB
${IPT} -A MINIFW-DOCKER-INPUT-MANUAL -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-INPUT-MANUAL
${IPT} -A DOCKER-USER -i ${INT} -m state --state NEW -j MINIFW-DOCKER-INPUT-MANUAL
${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
# SSH authorizations
for x in $SSHOK
do
ipalltables -A INPUT -p tcp ! --syn --sport 22 -s $x -j ACCEPT
done
for dstport in ${SERVICESUDP1}; do
${IPT} -I MINIFW-DOCKER-PUB -p udp --dport "${dstport}" -j RETURN
# SMTP authorizations
for addr in $SMTPOK
do
check_addr $addr|while read ip; do
$(ipxtables $ip) -A INPUT -p tcp ! --syn --sport 25 --dport $PORTSUSER -s $ip -j ACCEPT
done
done
# secure SMTP (TCP/465 et TCP/587) authorizations
for addr in $SMTPSECUREOK
do
check_addr $addr|while read ip; do
$(ipxtables $ip) -A INPUT -p tcp ! --syn --sport 465 --dport $PORTSUSER -s $ip -j ACCEPT
$(ipxtables $ip) -A INPUT -p tcp ! --syn --sport 587 --dport $PORTSUSER -s $ip -j ACCEPT
done
done
# NTP authorizations
for x in $NTPOK
do
ipalltables -A INPUT -p udp --sport 123 -s $x -j ACCEPT
ipalltables -A OUTPUT -o $INT -p udp -d $x --dport 123 --match state --state NEW -j ACCEPT
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
# Always allow ICMP
ipalltables -A INPUT -p icmp -j ACCEPT
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
# IPTables policy
#################
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
# by default DROP INPUT packets
ipalltables -P INPUT DROP
# 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
# by default, no FORWARING (deprecated for Virtual Machines)
#echo 0 > /proc/sys/net/ipv4/ip_forward
#ipalltables -P FORWARD DROP
#ipalltables6 -P FORWARD DROP
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
# by default allow OUTPUT packets... but drop UDP packets (see OUTPUTDROP to drop OUTPUT packets)
ipalltables -P OUTPUT ACCEPT
ipalltables -A OUTPUT -o $INT -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
ipalltables -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT
ipalltables -A OUTPUT -p udp -j DROP
# External services
###################
trap - INT TERM EXIT
# 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 -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 -j ACCEPT
${IPT} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 53 --match state --state NEW -j ACCEPT
fi
done
echo "...starting IPTables rules is now finish : OK"
;;
# 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
stop)
# 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 -j ACCEPT
fi
else
${IPT} -A INPUT -p tcp --sport "${server_port}" --dport 1024:65535 -s "${server_ip}" -m state --state ESTABLISHED -j ACCEPT
fi
else
printf "${RED}ERROR: unrecognized syntax for BACKUPSERVERS '%s\`. Use space-separated IP:PORT tuples.${RESET}\n" "${server}" >&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
# source config file for remaining commands
if is_legacy_config; then
source_file_or_error "${config_file}"
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 -j ACCEPT
if is_ipv6_enabled; then
${IPT6} -A OUTPUT -p udp --match state --state ESTABLISHED -j ACCEPT
fi
${IPT} -A OUTPUT -p udp -j DROP
if is_ipv6_enabled; then
${IPT6} -A OUTPUT -p udp -j DROP
fi
# Finish
########################
trap - INT TERM EXIT
syslog_info "started"
printf "${GREEN}${BOLD}${PROGNAME} started${RESET}\n"
# No need to exit on error anymore
set +e
# save active configuration
save_active_configuration "${ACTIVE_CONFIG}"
report_state_changes
}
stop() {
syslog_info "stopping"
printf "${BOLD}${PROGNAME} stopping${RESET}\n"
printf "${BLUE}flushing all rules and accepting everything${RESET}\n"
# Save previous state (without colors)
mkdir -p "$(dirname "${STATE_FILE_PREVIOUS}")"
status_without_numbers | remove_colors > "${STATE_FILE_PREVIOUS}"
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-INPUT-MANUAL
${IPT} -X MINIFW-DOCKER-INPUT-MANUAL
${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
ipalltables -F INPUT
ipalltables -F OUTPUT
ipalltables -F LOG_DROP
ipalltables -F LOG_ACCEPT
ipalltables -F ONLYTRUSTED
ipalltables -F ONLYPRIVILEGIED
ipalltables -F NEEDRESTRICT
ipalltables -t nat -F
ipalltables -t mangle -F
# 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
ipalltables -P INPUT ACCEPT
ipalltables -P OUTPUT ACCEPT
#ipalltables -P FORWARD ACCEPT
#ipalltables -t nat -P PREROUTING ACCEPT
#ipalltables -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
ipalltables -X LOG_DROP
ipalltables -X LOG_ACCEPT
ipalltables -X ONLYPRIVILEGIED
ipalltables -X ONLYTRUSTED
ipalltables -X NEEDRESTRICT
rm -f "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}" "${ACTIVE_CONFIG}"
echo "...flushing IPTables rules is now finish : OK"
;;
syslog_info "stopped"
printf "${GREEN}${BOLD}${PROGNAME} stopped${RESET}\n"
}
status)
status() {
printf "${BLUE}#### iptables --list ###############################${RESET}\n"
${IPT} --list --numeric --verbose --line-numbers
printf "\n${BLUE}#### iptables --table nat --list ###################${RESET}\n"
${IPT} --table nat --list --numeric --verbose --line-numbers
printf "\n${BLUE}#### iptables --table mangle --list ################${RESET}\n"
${IPT} --table mangle --list --numeric --verbose --line-numbers
if is_ipv6_enabled; then
printf "\n${BLUE}#### ip6tables --list ##############################${RESET}\n"
${IPT6} --list --numeric --verbose --line-numbers
printf "\n${BLUE}#### ip6tables --table mangle --list ###############${RESET}\n"
${IPT6} --table mangle --list --numeric --verbose --line-numbers
fi
}
ipalltables -L -n -v --line-numbers
ipalltables -t nat -L -n -v --line-numbers
ipalltables -t mangle -L -n -v --line-numbers
;;
status_without_numbers() {
printf "${BLUE}#### iptables --list ###############################${RESET}\n"
${IPT} --list --numeric
printf "\n${BLUE}#### iptables --table nat --list ###################${RESET}\n"
${IPT} --table nat --list --numeric
printf "\n${BLUE}#### iptables --table mangle --list ################${RESET}\n"
${IPT} --table mangle --list --numeric
if is_ipv6_enabled; then
printf "\n${BLUE}#### ip6tables --list ##############################${RESET}\n"
${IPT6} --list --numeric
printf "\n${BLUE}#### ip6tables --table mangle --list ###############${RESET}\n"
${IPT6} --table mangle --list --numeric
fi
}
reset)
reset() {
syslog_info "resetting"
printf "${BOLD}${PROGNAME} resetting${RESET}\n"
echo "Reset all IPTables counters..."
${IPT} -Z
if is_ipv6_enabled; then
${IPT6} -Z
fi
ipalltables -Z
ipalltables -t nat -Z
ipalltables -t mangle -Z
${IPT} -t nat -Z
echo "...reseting IPTables counters is now finish : OK"
;;
${IPT} -t mangle -Z
if is_ipv6_enabled; then
${IPT6} -t mangle -Z
fi
restart)
syslog_info "reset"
printf "${GREEN}${BOLD}${PROGNAME} reset${RESET}\n"
}
$0 stop
$0 start
;;
safety_timer() {
if [ "${SAFETY_TIMER}" -le "0" ] || [ "${SAFETY_TIMER}" -gt "3600" ]; then
syslog_info "safety timer value '${SAFETY_TIMER}' is out of range (1 < 3600), reverted to default value of '30'."
SAFETY_TIMER=30
readonly SAFETY_TIMER
fi
echo "${SAFETY_TIMER}"
}
*)
stop_if_locked() {
count=0
while [ "${count}" -lt "$(safety_timer)" ] && [ -f "${SAFETY_LOCK}" ]; do
count=$(( count + 1 ))
sleep 1
done
if [ -f "${SAFETY_LOCK}" ]; then
syslog_error "safety lock is still here after $(safety_timer) seconds, we need to stop"
stop
syslog_info "remove safety lock"
rm -f "${SAFETY_LOCK}"
else
syslog_info "safety lock is not there anymore, life goes on"
fi
}
safe_start() {
# start the firewall
start
# create the lock file
syslog_info "add safety lock"
touch "${SAFETY_LOCK}"
# run the special background command
nohup "${0}" stop-if-locked > "${SAFETY_OUTPUT}" 2>&1 &
if is_interactive; then
syslog_info "safe-restart in interactive mode ; if safety lock (${SAFETY_LOCK}) is not removed in the next $(safety_timer) seconds, minifirewall will be stopped."
# Ask for input
confirm_default="I'm locked out, please stop the firewall"
# printf "If the restart has locked you out you might see this but you shouldn't be able to type anything.\n"
printf "Minifirewall will be stopped in $(safety_timer) seconds if you do nothing.\n"
printf "Remove \`${SAFETY_LOCK}' or type anything to keep minifirewall started: "
read -r confirm
if [ ! -f "${SAFETY_LOCK}" ]; then
printf "${YELLOW}Safety lock is not there anymore.\nYou've probably been rescued by the safety checks.\n${BOLD}Minifirewall is probably stopped.${RESET}\n"
elif [ "${confirm}" != "${confirm_default}" ]; then
rm -f "${SAFETY_LOCK}" && printf "${GREEN}OK. Safety lock is removed.${RESET}\n"
fi
else
syslog_info "safe-restart in non-interactive mode ; if safety lock (${SAFETY_LOCK}) is not removed in the next $(safety_timer) seconds, minifirewall will be stopped."
fi
}
show_version() {
cat <<END
${PROGNAME} version ${VERSION}
Copyright 2007-2023 Evolix <info@evolix.fr>.
${PROGNAME} comes with ABSOLUTELY NO WARRANTY.
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.
END
}
show_help() {
cat <<END
${PROGNAME} ${DESC}
END
show_usage
}
show_usage() {
cat <<END
Usage: ${PROGNAME} [COMMAND]
Commands
start Start minifirewall
safe-start Start minifirewall, with baground safety checks
stop Stop minifirewall
restart Stop then start minifirewall
safe-restart Restart minifirewall, with background safety checks
status Print minifirewall status
reset Reset iptables tables
check-active-config Check if active config is up-to-date with stored config
version Print version and exit
help Print this message and exit
END
}
case "${1:-''}" in
start)
source_configuration
check_unpersisted_state
start
;;
safe-start)
source_configuration
check_unpersisted_state
safe_start
;;
stop)
source_configuration
check_unpersisted_state
stop
;;
status)
source_configuration
check_unpersisted_state
status
;;
reset)
source_configuration
check_unpersisted_state
reset
;;
restart)
source_configuration
check_unpersisted_state
stop
start
;;
safe-restart)
source_configuration
check_unpersisted_state
stop
safe_start
;;
stop-if-locked)
source_configuration
stop_if_locked
;;
check-active-config)
check_active_configuration
;;
version)
show_version
;;
help)
show_help
;;
*)
printf "%s: %s: unknown option\n" "${PROGNAME}" "${1}"
show_usage
exit 128
;;
echo "Usage: $0 {start|stop|restart|status|reset|squid}"
exit 1
esac
exit 0

View file

@ -1,136 +1,93 @@
# Configuration for minifirewall : https://gitea.evolix.org/evolix/minifirewall
# Version 23.07
# shellcheck shell=sh disable=SC2034
# Configuration for minifirewall : https://forge.evolix.org/projects/minifirewall
# For fun, we keep last change from first CVS repository:
# version 0.1 - 12 juillet 2007 $Id: firewall.rc,v 1.2 2007/07/12 19:08:59 reg Exp $
# Main interface
INT='eth0'
# IPv6
IPV6='on'
# Trusted IPv4 local network
# ...will be often IP/32 if you don't trust anything
INTLAN='192.168.0.2/32'
# Docker Mode
# Changes the behaviour of minifirewall to not break the containers' network
# For instance, turning it on will disable nat table purge
# Also, we'll add the DOCKER-USER chain, in iptables
#
# WARNING : If the port mapping is different between the host and the container
# (ie: Listen on :8090 on host, but :8080 in container)
# then you need to give the port used inside the container
DOCKER='off'
# Trusted IPv4 addresses for private and semi-public services
TRUSTEDIPS='62.212.121.90 88.179.18.233 31.170.8.4 31.170.9.129 2a01:9500:37:129::/64'
# Trusted local network
# ...will be often IPv4/32 or IPv6/128 if you don't trust anything
INTLAN='192.0.2.1/32 2001:db8::1/128'
# Trusted IP addresses for private and semi-public services
# TODO: add all our IPv6 adresses
TRUSTEDIPS='31.170.9.129 2a01:9500:37:129::/64 31.170.8.4 2a01:9500::fada 82.65.34.85 2a01:e0a:571:2a10::1 54.37.106.210 51.210.84.146'
# Privilegied IP addresses for semi-public services
# Privilegied IPv4 addresses for semi-public services
# (no need to add again TRUSTEDIPS)
PRIVILEGIEDIPS=''
# Local services IP restrictions
# Local services IPv4/IPv6 restrictions
#######################################
# Protected services
# (add also in Public services if needed)
SERVICESTCP1p='22222'
SERVICESTCP1p='22'
SERVICESUDP1p=''
# Public services (IPv4/IPv6)
SERVICESTCP1='22222'
SERVICESUDP1=''
SERVICESTCP1='25 53 443 993 995 2222'
SERVICESUDP1='53'
# Semi-public services (IPv4)
SERVICESTCP2='22'
SERVICESTCP2='20 21 22 80 110 143'
SERVICESUDP2=''
# Private services (IPv4)
SERVICESTCP3='5666'
SERVICESUDP3=''
# Standard output IPv4/IPv6 access restrictions
# Standard output IPv4 access restrictions
##########################################
# DNS authorizations
# (if you have local DNS server, set 0.0.0.0/0)
DNSSERVEURS='0.0.0.0/0 ::/0'
DNSSERVEURS='0.0.0.0/0'
# HTTP authorizations
# (you can use DNS names but set cron to reload minifirewall regularly)
# (if you have HTTP proxy, set 0.0.0.0/0)
HTTPSITES='0.0.0.0/0 ::/0'
HTTPSITES='security.debian.org pub.evolix.net security-cdn.debian.org volatile.debian.org mirror.evolix.org backports.debian.org hwraid.le-vert.net antispam00.evolix.org spamassassin.apache.org sa-update.space-pro.be sa-update.secnap.net www.sa-update.pccc.com sa-update.dnswl.org ocsp.int-x3.letsencrypt.org'
# HTTPS authorizations
HTTPSSITES='0.0.0.0/0 ::/0'
HTTPSSITES='0.0.0.0/0'
# FTP authorizations
FTPSITES=''
# SSH authorizations
SSHOK='0.0.0.0/0 ::/0'
SSHOK='0.0.0.0/0'
# SMTP authorizations
SMTPOK='0.0.0.0/0 ::/0'
SMTPOK='0.0.0.0/0'
# SMTP secure authorizations (ports TCP/465 and TCP/587)
SMTPSECUREOK=''
# NTP authorizations
NTPOK='0.0.0.0/0 ::/0'
# Proxy (Squid)
PROXY='off'
# (proxy port)
PROXYPORT='8888'
# (destinations that bypass the proxy)
PROXYBYPASS="${INTLAN} 127.0.0.0/8 ::1/128"
# Backup servers
# (add IP:PORT for each one, example: '192.168.10.1:1234 192.168.10.2:5678')
BACKUPSERVERS=''
NTPOK='0.0.0.0/0'
# Includes
# IPv6 Specific rules
#####################
# Files in /etc/minifirewall.d/* (without "." in name)
# are automatically included in alphanumerical order.
#
# Within included files, you can use those helper functions :
# * is_ipv6_enabled: returns true if IPv6 is enabled, or false
# * is_docker_enabled: returns true if Docker mode is eabled, or false
# * is_proxy_enabled: returns true if Proxy mode is enabled , or false
# Example: allow input HTTP/HTTPS/SMTP/DNS traffic
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 80 --match state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 443 --match state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 25 --match state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/ip6tables -A INPUT -i $INT -p udp --sport 53 --match state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 53 --match state --state ESTABLISHED,RELATED -j ACCEPT
# Example: allow output DNS, NTP and traceroute traffic
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 53 --match state --state NEW -j ACCEPT
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 123 --match state --state NEW -j ACCEPT
#/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
# Custom sysctl values (advanced)
#################################
# Example: allow DHCPv6
/sbin/ip6tables -A INPUT -i $INT -p udp --dport 546 -d fe80::/64 -j ACCEPT
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 547 -j ACCEPT
# In most cases, the default values set by minifirewall are good.
# If you really know what you are doing,
# you can uncomment some lines and customize the values.
# IPv4 Specific rules
#####################
# 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)
# 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'
# /sbin/iptables ...

View file

@ -1,136 +0,0 @@
# Fichier de configuration
# pour minifirewall
# version 0.1 - 12 juillet 2007 $Id: firewall.rc,v 1.2 2007/07/12 19:08:59 reg Exp $
# Interface concernee
INT='eth0.11'
IPV6=on
# IP associee (plus utilisee dans les scripts)
# INTIP='192.168.0.2'
# reseau beneficiant d'acces privilegies
# (sera souvent IP/32)
INTLAN='192.0.2.1/32'
# trusted ip addresses
TRUSTEDIPS='62.212.121.90 62.212.111.216 88.179.18.233 85.118.59.4 85.118.59.50 31.170.8.4 31.170.9.129 82.65.34.85 54.37.106.210 51.210.84.146'
# privilegied ip addresses
# (trusted ip addresses *are* privilegied)
PRIVILEGIEDIPS='80.14.117.69 31.170.8.6 31.170.11.167 31.170.11.167 31.170.8.7 31.170.8.249 31.170.8.76 31.170.8.222 80.245.23.179 51.38.233.228'
# Services "protected"
# a mettre aussi en public si necessaire !!
SERVICESTCP1p=''
SERVICESUDP1p=''
# Services "publics"
SERVICESTCP1='21 80 443 2222'
SERVICESUDP1=''
# Services "semi-publics"
SERVICESTCP2='20 22 25'
SERVICESUDP2=''
# Services "prives"
SERVICESTCP3='5666'
SERVICESUDP3=''
################### SORTANTS
# DNS
# (Attention, si un serveur DNS est installe en local
# mettre 0.0.0.0/0)
DNSSERVEURS='0.0.0.0/0'
# HTTP : security.d.o x3, zidane, modsecurity www.debian.org
# /!\ Possibilite d'utiliser des noms de domaines
# mais il est conseiller de placer un rechargement
# du minifirewall en crontab
# (Attention, si un proxy HTTP est installe en local
# mettre 0.0.0.0/0)
HTTPSITES='0.0.0.0/0'
# HTTPS
# /!\ Possibilite d'utiliser des noms de domaines
# mais il est conseiller de placer un rechargement
# du minifirewall en crontab
HTTPSSITES='0.0.0.0/0'
# FTP
FTPSITES='0.0.0.0/0'
# SSH
SSHOK='0.0.0.0/0'
# SMTP
SMTPOK='0.0.0.0/0'
# SMTP secure (port 465 et 587)
SMTPSECUREOK='0.0.0.0/0'
# NTP
NTPOK='0.0.0.0/0'
################### IPv6 Specific rules
# /sbin/ip6tables ...
# Allow HTTP/HTTPS/SMTP traffic
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 80 --match state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 443 --match state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 25 --match state --state ESTABLISHED,RELATED -j ACCEPT
# Allow DNS, NTP and traceroute traffic
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 53 --match state --state NEW -j ACCEPT
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 123 --match state --state NEW -j ACCEPT
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
# Allow DHCPv6
/sbin/ip6tables -t filter -A INPUT -i $INT -p udp --dport 546 -d fe80::/64 -j ACCEPT
/sbin/ip6tables -t filter -A OUTPUT -o $INT -p udp --dport 547 -j ACCEPT
################### IPv4 Specific rules
# /sbin/iptables ...
# Allow DNS, NTP and traceroute traffic
/sbin/iptables -A OUTPUT -o $INT -p udp --dport 53 --match state --state NEW -j ACCEPT
/sbin/iptables -A OUTPUT -o $INT -p udp --dport 123 --match state --state NEW -j ACCEPT
/sbin/iptables -A OUTPUT -o $INT -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
# EvoBackup
# /sbin/iptables -A INPUT -p tcp --sport XXXX --dport 1024:65535 -s 85.118.59.1 -m state --state ESTABLISHED,RELATED -j ACCEPT
# /sbin/iptables -A INPUT -p tcp --sport XXXX --dport 1024:65535 -s 31.170.8.1 -m state --state ESTABLISHED,RELATED -j ACCEPT
# /sbin/iptables -A INPUT -p tcp --sport XXXX --dport 1024:65535 -s 178.32.100.48 -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A INPUT -p tcp --sport 2223 --dport 1024:65535 -s 62.210.209.17 -m state --state ESTABLISHED,RELATED -j ACCEPT
# FTP en mode passif
/sbin/iptables -A INPUT -p tcp --dport 60000:61000 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# EvoMaintenance
/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s 31.170.8.4 -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s 62.212.121.90 -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s 62.212.111.216 -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s 88.179.18.233 -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s 85.118.59.50 -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s 31.170.9.129 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Proxy
/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner proxy -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 31.170.8.7 -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 31.170.8.10 -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 31.170.8.217 -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 31.170.8.218 -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.1 -j ACCEPT
/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -j LOG --log-uid
/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8888
#43251
iptables -I INPUT -s 5.188.211.0/24 -p tcp --dport 80 -j DROP
iptables -I INPUT -s 5.188.211.0/24 -p tcp --dport 443 -j DROP
/sbin/iptables -A INPUT -p tcp --sport 2222 --dport 1024:65535 -s 31.170.11.167,31.170.8.7,31.170.8.249,31.170.8.76,31.170.8.222 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Ticket #52247 : Blocage git / Autorisation port 22 en IPv6
/sbin/ip6tables -A INPUT -p tcp ! --syn --sport 22 -s ::/0 -j ACCEPT

View file

@ -1,492 +0,0 @@
#!/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