Compare commits
No commits in common. "master" and "23.07" have entirely different histories.
|
@ -5,9 +5,6 @@ and this project **does not adhere to [Semantic Versioning](http://semver.org/sp
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
* safe-start and safe-restart
|
|
||||||
* Chain MINIFW-DOCKER-INPUT-MANUAL for more granular/manual filtering of incoming traffic to services inside docker
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
@ -16,8 +13,6 @@ and this project **does not adhere to [Semantic Versioning](http://semver.org/sp
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
* fix interactive mode detection
|
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
## [23.07] - 2023-07-04
|
## [23.07] - 2023-07-04
|
||||||
|
|
134
minifirewall
134
minifirewall
|
@ -111,10 +111,6 @@ STATE_FILE_DIFF='/var/run/minifirewall_state_diff'
|
||||||
ACTIVE_CONFIG='/var/run/minifirewall_active_config'
|
ACTIVE_CONFIG='/var/run/minifirewall_active_config'
|
||||||
ACTIVE_CONFIG_DIFF="${ACTIVE_CONFIG}.diff"
|
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)
|
LOGGER_BIN=$(command -v logger)
|
||||||
|
|
||||||
# No colors by default
|
# No colors by default
|
||||||
|
@ -127,10 +123,8 @@ CYAN=''
|
||||||
WHITE=''
|
WHITE=''
|
||||||
BOLD=''
|
BOLD=''
|
||||||
RESET=''
|
RESET=''
|
||||||
|
|
||||||
# check if stdout is a terminal...
|
# check if stdout is a terminal...
|
||||||
if [ -t 1 ]; then
|
if [ -t 1 ]; then
|
||||||
INTERACTIVE=1
|
|
||||||
|
|
||||||
# see if it supports colors...
|
# see if it supports colors...
|
||||||
ncolors=$(tput colors)
|
ncolors=$(tput colors)
|
||||||
|
@ -147,10 +141,7 @@ if [ -t 1 ]; then
|
||||||
BOLD=$(tput bold)
|
BOLD=$(tput bold)
|
||||||
RESET='\e[m'
|
RESET='\e[m'
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
INTERACTIVE=0
|
|
||||||
fi
|
fi
|
||||||
readonly INTERACTIVE
|
|
||||||
|
|
||||||
## pseudo dry-run :
|
## pseudo dry-run :
|
||||||
## Uncomment and call these functions instead of the real iptables and ip6tables commands
|
## Uncomment and call these functions instead of the real iptables and ip6tables commands
|
||||||
|
@ -164,9 +155,6 @@ readonly INTERACTIVE
|
||||||
# }
|
# }
|
||||||
## Beware that commands executed from included files are not modified by this trick.
|
## Beware that commands executed from included files are not modified by this trick.
|
||||||
|
|
||||||
is_interactive() {
|
|
||||||
test "${INTERACTIVE}" = "1"
|
|
||||||
}
|
|
||||||
remove_colors() {
|
remove_colors() {
|
||||||
sed -r 's/\x1B\[(;?[0-9]{1,3})+[mGK]//g'
|
sed -r 's/\x1B\[(;?[0-9]{1,3})+[mGK]//g'
|
||||||
}
|
}
|
||||||
|
@ -322,10 +310,10 @@ check_active_configuration() {
|
||||||
diff_bin=$(command -v diff)
|
diff_bin=$(command -v diff)
|
||||||
|
|
||||||
if [ -z "${cmp_bin}" ]; then
|
if [ -z "${cmp_bin}" ]; then
|
||||||
printf "${YELLOW}WARNING: Skipped active configuration check (Can't find cmp(1) command)${RESET}\n"
|
printf "${YELLOW}Skipped active configuration check (Can't find cmp(1) command)${RESET}\n"
|
||||||
rc=1
|
rc=1
|
||||||
elif [ -z "${diff_bin}" ]; then
|
elif [ -z "${diff_bin}" ]; then
|
||||||
printf "${YELLOW}WARNING: Skipped active configuration check (Can't find diff(1) command)${RESET}\n"
|
printf "${YELLOW}Skipped active configuration check (Can't find diff(1) command)${RESET}\n"
|
||||||
rc=1
|
rc=1
|
||||||
else
|
else
|
||||||
rm -f "${ACTIVE_CONFIG_DIFF}"
|
rm -f "${ACTIVE_CONFIG_DIFF}"
|
||||||
|
@ -338,15 +326,15 @@ check_active_configuration() {
|
||||||
|
|
||||||
if [ ${cmp_rc} -eq 0 ]; then
|
if [ ${cmp_rc} -eq 0 ]; then
|
||||||
# echo " config has not changed since latest start"
|
# echo " config has not changed since latest start"
|
||||||
printf "${GREEN}OK: Active configuration is up-to-date.${RESET}\n"
|
printf "${GREEN}Active configuration is up-to-date.${RESET}\n"
|
||||||
rc=0
|
rc=0
|
||||||
elif [ ${cmp_rc} -eq 1 ]; then
|
elif [ ${cmp_rc} -eq 1 ]; then
|
||||||
diff -u "${ACTIVE_CONFIG}" "${tmp_config_file}" > "${ACTIVE_CONFIG_DIFF}"
|
diff -u "${ACTIVE_CONFIG}" "${tmp_config_file}" > "${ACTIVE_CONFIG_DIFF}"
|
||||||
|
|
||||||
printf "${RED}CRITICAL: Active configuration is not up-to-date (minifirewall not restarted after config change?), check %s${RESET}\n" "${ACTIVE_CONFIG_DIFF}"
|
printf "${RED}Active configuration is not up-to-date (minifirewall not restarted after config change?), check %s${RESET}\n" "${ACTIVE_CONFIG_DIFF}"
|
||||||
rc=2
|
rc=2
|
||||||
else
|
else
|
||||||
printf "${RED}CRITICAL: Error while comparing rules:${RESET}\n"
|
printf "${RED}Error while comparing rules:${RESET}\n"
|
||||||
printf "${cmp_result}\n"
|
printf "${cmp_result}\n"
|
||||||
rc=2
|
rc=2
|
||||||
fi
|
fi
|
||||||
|
@ -354,7 +342,7 @@ check_active_configuration() {
|
||||||
rm -f "${tmp_config_file}"
|
rm -f "${tmp_config_file}"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
printf "${YELLOW}WARNING: Skipped active configuration check (missing file ${ACTIVE_CONFIG})${RESET}\n"
|
printf "${YELLOW}Skipped active configuration check (missing file ${ACTIVE_CONFIG})${RESET}\n"
|
||||||
rc=1
|
rc=1
|
||||||
fi
|
fi
|
||||||
exit ${rc}
|
exit ${rc}
|
||||||
|
@ -555,10 +543,6 @@ start() {
|
||||||
${IPT6} -A LOG_ACCEPT -j ACCEPT
|
${IPT6} -A LOG_ACCEPT -j ACCEPT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if is_docker_enabled; then
|
|
||||||
${IPT} -N MINIFW-DOCKER-INPUT-MANUAL
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Source additional rules and commands
|
# Source additional rules and commands
|
||||||
# * from legacy configuration file (/etc/default/minifirewall)
|
# * from legacy configuration file (/etc/default/minifirewall)
|
||||||
# * from configuration directory (/etc/minifirewall.d/*)
|
# * from configuration directory (/etc/minifirewall.d/*)
|
||||||
|
@ -667,10 +651,6 @@ start() {
|
||||||
${IPT} -A MINIFW-DOCKER-PUB -j MINIFW-DOCKER-PRIVILEGED
|
${IPT} -A MINIFW-DOCKER-PUB -j MINIFW-DOCKER-PRIVILEGED
|
||||||
${IPT} -A MINIFW-DOCKER-PUB -j RETURN
|
${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
|
# Flush DOCKER-USER if exist, create it if absent
|
||||||
if chain_exists 'DOCKER-USER'; then
|
if chain_exists 'DOCKER-USER'; then
|
||||||
${IPT} -F DOCKER-USER
|
${IPT} -F DOCKER-USER
|
||||||
|
@ -678,8 +658,8 @@ start() {
|
||||||
${IPT} -N DOCKER-USER
|
${IPT} -N DOCKER-USER
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
# Pipe new connection through MINIFW-DOCKER-INPUT-MANUAL
|
# Pipe new connection through MINIFW-DOCKER-PUB
|
||||||
${IPT} -A DOCKER-USER -i ${INT} -m state --state NEW -j MINIFW-DOCKER-INPUT-MANUAL
|
${IPT} -A DOCKER-USER -i ${INT} -m state --state NEW -j MINIFW-DOCKER-PUB
|
||||||
${IPT} -A DOCKER-USER -j RETURN
|
${IPT} -A DOCKER-USER -j RETURN
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -826,12 +806,12 @@ start() {
|
||||||
if is_ipv6 ${IP}; then
|
if is_ipv6 ${IP}; then
|
||||||
if is_ipv6_enabled; then
|
if is_ipv6_enabled; then
|
||||||
${IPT6} -A INPUT -p tcp ! --syn --sport 53 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
${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 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
|
${IPT6} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 53 --match state --state NEW -j ACCEPT
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
${IPT} -A INPUT -p tcp ! --syn --sport 53 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
${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 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
|
${IPT} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 53 --match state --state NEW -j ACCEPT
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
@ -951,10 +931,10 @@ start() {
|
||||||
if [ -n "${server_ip}" ] && [ -n "${server_port}" ]; then
|
if [ -n "${server_ip}" ] && [ -n "${server_port}" ]; then
|
||||||
if is_ipv6 ${server_ip}; then
|
if is_ipv6 ${server_ip}; then
|
||||||
if is_ipv6_enabled; 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
|
${IPT6} -A INPUT -p tcp --sport "${server_port}" --dport 1024:65535 -s "${server_ip}" -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
${IPT} -A INPUT -p tcp --sport "${server_port}" --dport 1024:65535 -s "${server_ip}" -m state --state ESTABLISHED -j ACCEPT
|
${IPT} -A INPUT -p tcp --sport "${server_port}" --dport 1024:65535 -s "${server_ip}" -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
printf "${RED}ERROR: unrecognized syntax for BACKUPSERVERS '%s\`. Use space-separated IP:PORT tuples.${RESET}\n" "${server}" >&2
|
printf "${RED}ERROR: unrecognized syntax for BACKUPSERVERS '%s\`. Use space-separated IP:PORT tuples.${RESET}\n" "${server}" >&2
|
||||||
|
@ -998,9 +978,9 @@ start() {
|
||||||
${IPT6} -A OUTPUT -o ${INT} -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
|
${IPT6} -A OUTPUT -o ${INT} -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${IPT} -A OUTPUT -p udp --match state --state ESTABLISHED -j ACCEPT
|
${IPT} -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
if is_ipv6_enabled; then
|
if is_ipv6_enabled; then
|
||||||
${IPT6} -A OUTPUT -p udp --match state --state ESTABLISHED -j ACCEPT
|
${IPT6} -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${IPT} -A OUTPUT -p udp -j DROP
|
${IPT} -A OUTPUT -p udp -j DROP
|
||||||
|
@ -1070,8 +1050,6 @@ stop() {
|
||||||
${IPT} -F DOCKER-USER
|
${IPT} -F DOCKER-USER
|
||||||
${IPT} -A DOCKER-USER -j RETURN
|
${IPT} -A DOCKER-USER -j RETURN
|
||||||
|
|
||||||
${IPT} -F MINIFW-DOCKER-INPUT-MANUAL
|
|
||||||
${IPT} -X MINIFW-DOCKER-INPUT-MANUAL
|
|
||||||
${IPT} -F MINIFW-DOCKER-PUB
|
${IPT} -F MINIFW-DOCKER-PUB
|
||||||
${IPT} -X MINIFW-DOCKER-PUB
|
${IPT} -X MINIFW-DOCKER-PUB
|
||||||
${IPT} -F MINIFW-DOCKER-PRIVILEGED
|
${IPT} -F MINIFW-DOCKER-PRIVILEGED
|
||||||
|
@ -1165,67 +1143,6 @@ reset() {
|
||||||
syslog_info "reset"
|
syslog_info "reset"
|
||||||
printf "${GREEN}${BOLD}${PROGNAME} reset${RESET}\n"
|
printf "${GREEN}${BOLD}${PROGNAME} reset${RESET}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
show_version() {
|
||||||
cat <<END
|
cat <<END
|
||||||
${PROGNAME} version ${VERSION}
|
${PROGNAME} version ${VERSION}
|
||||||
|
@ -1252,10 +1169,8 @@ Usage: ${PROGNAME} [COMMAND]
|
||||||
|
|
||||||
Commands
|
Commands
|
||||||
start Start minifirewall
|
start Start minifirewall
|
||||||
safe-start Start minifirewall, with baground safety checks
|
|
||||||
stop Stop minifirewall
|
stop Stop minifirewall
|
||||||
restart Stop then start minifirewall
|
restart Stop then start minifirewall
|
||||||
safe-restart Restart minifirewall, with background safety checks
|
|
||||||
status Print minifirewall status
|
status Print minifirewall status
|
||||||
reset Reset iptables tables
|
reset Reset iptables tables
|
||||||
check-active-config Check if active config is up-to-date with stored config
|
check-active-config Check if active config is up-to-date with stored config
|
||||||
|
@ -1272,13 +1187,6 @@ case "${1:-''}" in
|
||||||
start
|
start
|
||||||
;;
|
;;
|
||||||
|
|
||||||
safe-start)
|
|
||||||
source_configuration
|
|
||||||
check_unpersisted_state
|
|
||||||
|
|
||||||
safe_start
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop)
|
stop)
|
||||||
source_configuration
|
source_configuration
|
||||||
check_unpersisted_state
|
check_unpersisted_state
|
||||||
|
@ -1308,20 +1216,6 @@ case "${1:-''}" in
|
||||||
start
|
start
|
||||||
;;
|
;;
|
||||||
|
|
||||||
safe-restart)
|
|
||||||
source_configuration
|
|
||||||
check_unpersisted_state
|
|
||||||
|
|
||||||
stop
|
|
||||||
safe_start
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop-if-locked)
|
|
||||||
source_configuration
|
|
||||||
|
|
||||||
stop_if_locked
|
|
||||||
;;
|
|
||||||
|
|
||||||
check-active-config)
|
check-active-config)
|
||||||
check_active_configuration
|
check_active_configuration
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -24,7 +24,7 @@ INTLAN='192.0.2.1/32 2001:db8::1/128'
|
||||||
|
|
||||||
# Trusted IP addresses for private and semi-public services
|
# Trusted IP addresses for private and semi-public services
|
||||||
# TODO: add all our IPv6 adresses
|
# 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'
|
TRUSTEDIPS='31.170.9.129 2a01:9500:37:129::/64 31.170.8.4 2a01:9500::fada/128 82.65.34.85 54.37.106.210 51.210.84.146'
|
||||||
|
|
||||||
# Privilegied IP addresses for semi-public services
|
# Privilegied IP addresses for semi-public services
|
||||||
# (no need to add again TRUSTEDIPS)
|
# (no need to add again TRUSTEDIPS)
|
||||||
|
|
Loading…
Reference in a new issue