From bc16bfdcd201e34878dee0e92bebb589e34a08b1 Mon Sep 17 00:00:00 2001 From: Sebastian Schmittner Date: Fri, 21 Jun 2024 10:43:08 +0200 Subject: [PATCH 1/5] important ddos script fix: do not always enter test mode Signed-off-by: Sebastian Schmittner --- run/add_ddos_protection_iptables_rule.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/run/add_ddos_protection_iptables_rule.sh b/run/add_ddos_protection_iptables_rule.sh index 64674c9..03cabb4 100755 --- a/run/add_ddos_protection_iptables_rule.sh +++ b/run/add_ddos_protection_iptables_rule.sh @@ -142,7 +142,7 @@ if [ $# -lt 2 ]; then usage fi -if [ -n ${TEST_MODE} ]; then +if [ -n "${TEST_MODE}" ]; then print_settings exit 0 fi @@ -163,13 +163,14 @@ else fi # Make sure the previous default logging rule is removed. It causes too much CPU overhead under load. -RULE="${LOG_CHAIN} -j LOG --log-level warning --log-prefix \"connlimit: \"" +RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix connlimit:" delete_rule ${RULE} # Append a rule that sets log level and log prefix # Default to no logging unless a logging level is explicitly supplied. if [ -n ${CONN_LOGGING_LEVEL} ]; then - RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix \"connlimit: \"" + # RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix \"connlimit: \"" + RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix connlimit:" ${OPERATION} ${RULE} fi @@ -186,7 +187,7 @@ RULE="${IP_TABLES_CHAIN} -p tcp -m tcp --dport ${DPORT} --tcp-flags FIN,SYN,RST, ${OPERATION} ${RULE} # Append rules to rate limit connections -if ((CONN_RATE_LIMIT_LIMIT} > 0)) && ((CONN_RATE_LIMIT_PERIOD > 0)); then +if [ "${CONN_RATE_LIMIT_LIMIT}" -gt "0" ] && [ "${CONN_RATE_LIMIT_PERIOD}" -gt "0" ]; then echo "Including settings for rate limiting ..." RULE="${IP_TABLES_CHAIN} -p tcp -m tcp --dport ${DPORT} -m conntrack --ctstate NEW -m recent --set --name DEFAULT --mask 255.255.255.255 --rsource" ${OPERATION} ${RULE} From 26d5b1d37ec412cb545b204b471a5bcd27f5524f Mon Sep 17 00:00:00 2001 From: Sebastian Schmittner Date: Fri, 21 Jun 2024 10:47:06 +0200 Subject: [PATCH 2/5] cleanup and fixing similarly missing quotes Signed-off-by: Sebastian Schmittner --- run/add_ddos_protection_iptables_rule.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/run/add_ddos_protection_iptables_rule.sh b/run/add_ddos_protection_iptables_rule.sh index 03cabb4..f3a32e5 100755 --- a/run/add_ddos_protection_iptables_rule.sh +++ b/run/add_ddos_protection_iptables_rule.sh @@ -97,7 +97,7 @@ CONN_LOGGING_LEVEL=${6} source ./ip_tables_utils.sh add() { - if [ -z ${DELETE} ]; then + if [ -z "${DELETE}" ]; then return 0 else return 1 @@ -105,7 +105,7 @@ add() { } delete() { - if [ -n ${DELETE} ]; then + if [ -n "${DELETE}" ]; then return 0 else return 1 @@ -163,14 +163,13 @@ else fi # Make sure the previous default logging rule is removed. It causes too much CPU overhead under load. -RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix connlimit:" +RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix 'connlimit:'" delete_rule ${RULE} # Append a rule that sets log level and log prefix # Default to no logging unless a logging level is explicitly supplied. -if [ -n ${CONN_LOGGING_LEVEL} ]; then - # RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix \"connlimit: \"" - RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix connlimit:" +if [ -n "${CONN_LOGGING_LEVEL}" ]; then + RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix 'connlimit:'" ${OPERATION} ${RULE} fi From d1f98de124ebf20f6ad44782e6eded1bb38159fb Mon Sep 17 00:00:00 2001 From: Jens Schedel Date: Fri, 21 Jun 2024 15:17:28 +0200 Subject: [PATCH 3/5] Make shellcheck happy Signed-off-by: Jens Schedel --- run/add_ddos_protection_iptables_rule.sh | 28 +++++++++--------- run/ip_tables_utils.sh | 36 ++++++++++++------------ run/set_iptables.sh | 12 ++++---- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/run/add_ddos_protection_iptables_rule.sh b/run/add_ddos_protection_iptables_rule.sh index f3a32e5..69ec1f0 100755 --- a/run/add_ddos_protection_iptables_rule.sh +++ b/run/add_ddos_protection_iptables_rule.sh @@ -163,35 +163,35 @@ else fi # Make sure the previous default logging rule is removed. It causes too much CPU overhead under load. -RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix 'connlimit:'" -delete_rule ${RULE} +RULE=("${LOG_CHAIN}" -j LOG --log-level "${CONN_LOGGING_LEVEL}" --log-prefix "connlimit: ") +delete_rule "${RULE[@]}" # Append a rule that sets log level and log prefix # Default to no logging unless a logging level is explicitly supplied. if [ -n "${CONN_LOGGING_LEVEL}" ]; then - RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix 'connlimit:'" - ${OPERATION} ${RULE} + RULE=("${LOG_CHAIN}" -j LOG --log-level "${CONN_LOGGING_LEVEL}" --log-prefix "connlimit: ") + ${OPERATION} "${RULE[@]}" fi # Append a rule that finally rejects connection -RULE="${LOG_CHAIN} -p tcp -j REJECT --reject-with tcp-reset" -make_last_rule ${RULE} +RULE=("${LOG_CHAIN}" -p tcp -j REJECT --reject-with tcp-reset) +make_last_rule "${RULE[@]}" # Append a rule to limit the total number of simultaneous client connections -RULE="${IP_TABLES_CHAIN} -p tcp --syn --dport ${DPORT} -m connlimit --connlimit-above ${OVER_ALL_CONN_LIMIT} --connlimit-mask 0 -j ${LOG_CHAIN}" -${OPERATION} ${RULE} +RULE=("${IP_TABLES_CHAIN}" -p tcp --syn --dport "${DPORT}" -m connlimit --connlimit-above "${OVER_ALL_CONN_LIMIT}" --connlimit-mask 0 -j "${LOG_CHAIN}") +${OPERATION} "${RULE[@]}" # Append a rule to limit the number connections per IP address -RULE="${IP_TABLES_CHAIN} -p tcp -m tcp --dport ${DPORT} --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above ${CONN_LIMIT_PER_IP} --connlimit-mask 32 --connlimit-saddr -j ${LOG_CHAIN}" -${OPERATION} ${RULE} +RULE=("${IP_TABLES_CHAIN}" -p tcp -m tcp --dport "${DPORT}" --tcp-flags "FIN,SYN,RST,ACK" SYN -m connlimit --connlimit-above "${CONN_LIMIT_PER_IP}" --connlimit-mask 32 --connlimit-saddr -j "${LOG_CHAIN}") +${OPERATION} "${RULE[@]}" # Append rules to rate limit connections if [ "${CONN_RATE_LIMIT_LIMIT}" -gt "0" ] && [ "${CONN_RATE_LIMIT_PERIOD}" -gt "0" ]; then echo "Including settings for rate limiting ..." - RULE="${IP_TABLES_CHAIN} -p tcp -m tcp --dport ${DPORT} -m conntrack --ctstate NEW -m recent --set --name DEFAULT --mask 255.255.255.255 --rsource" - ${OPERATION} ${RULE} - RULE="${IP_TABLES_CHAIN} -p tcp -m tcp --dport ${DPORT} -m conntrack --ctstate NEW -m recent --update --seconds ${CONN_RATE_LIMIT_PERIOD} --hitcount ${CONN_RATE_LIMIT_LIMIT} --name DEFAULT --mask 255.255.255.255 --rsource -j ${LOG_CHAIN}" - ${OPERATION} ${RULE} + RULE=("${IP_TABLES_CHAIN}" -p tcp -m tcp --dport "${DPORT}" -m conntrack --ctstate NEW -m recent --set --name DEFAULT --mask 255.255.255.255 --rsource) + ${OPERATION} "${RULE[@]}" + RULE=("${IP_TABLES_CHAIN}" -p tcp -m tcp --dport "${DPORT}" -m conntrack --ctstate NEW -m recent --update --seconds "${CONN_RATE_LIMIT_PERIOD}" --hitcount "${CONN_RATE_LIMIT_LIMIT}" --name DEFAULT --mask 255.255.255.255 --rsource -j "${LOG_CHAIN}") + ${OPERATION} "${RULE[@]}" else echo "Rate limiting is disabled, skipping settings for rate limiting ..." fi diff --git a/run/ip_tables_utils.sh b/run/ip_tables_utils.sh index 335b6d9..89084f9 100644 --- a/run/ip_tables_utils.sh +++ b/run/ip_tables_utils.sh @@ -2,39 +2,39 @@ # skip existing rules to avoid duplicates add_new_rule() { - RULE="$@" + RULE=("$@") - if rule_exists ${RULE}; then - echo "[skip] $RULE already exists" - elif [[ "$RULE" == *"DROP"* ]] || [[ "$RULE" == *"RETURN"* ]] || [[ "$RULE" == *"REJECT"* ]]; then - iptables -A $RULE - echo "[OK] $RULE added to the end of the chain" + if rule_exists "${RULE[@}]}"; then + echo "[skip] ${RULE[*]} already exists" + elif [[ "${RULE[*]}" =~ "DROP" ]] || [[ "${RULE[*]}" =~ "RETURN" ]] || [[ "${RULE[*]}" =~ "REJECT" ]]; then + iptables -A "${RULE[@]}" + echo "[OK] ${RULE[*]} added to the end of the chain" else - iptables -I $RULE - echo "[OK] $RULE added to the beginning of the chain" + iptables -I "${RULE[@]}" + echo "[OK] ${RULE[*]} added to the beginning of the chain" fi } make_last_rule() { - RULE="$@" - delete_rule ${RULE} - iptables -A $RULE - echo "[OK] $RULE added to the end of the chain" + RULE=("$@") + delete_rule "${RULE[@]}" + iptables -A "${RULE[@]}" + echo "[OK] ${RULE[*]} added to the end of the chain" } rule_exists() { - RULE="$@" - if iptables -C ${RULE} 2>/dev/null 1>&2; then + RULE=("$@") + if iptables -C "${RULE[@]}" 2>/dev/null 1>&2; then return 0 fi return 1 } delete_rule() { - RULE="$@" - while rule_exists ${RULE}; do - iptables -D $RULE - echo "[OK] $RULE deleted" + RULE=("$@") + while rule_exists "${RULE[@]}"; do + iptables -D "${RULE[@]}" + echo "[OK] ${RULE[*]} deleted" done } diff --git a/run/set_iptables.sh b/run/set_iptables.sh index 790e10a..ecaab59 100755 --- a/run/set_iptables.sh +++ b/run/set_iptables.sh @@ -34,8 +34,8 @@ INTERFACE=$1 echo "INTERFACE=${INTERFACE:=ens18}" # check if INTERFACE is set to an inet facing interface -if ! ip a | grep inet | grep "$INTERFACE" >/dev/null; then - echo "[ERROR] interface '$INTERFACE' does not seem to be an internet facing interface" +if ! ip a | grep inet | grep "${INTERFACE}" >/dev/null; then + echo "[ERROR] interface '${INTERFACE}' does not seem to be an internet facing interface" usage exit 1 fi @@ -61,17 +61,17 @@ echo echo "[...] Setting up iptables white list for ips that may access port ${INTERNAL_PORT} from file ${IP_FILE}" # 9701 whitelist approach: drop all others INCOMING (-i) connections -add_new_rule $CHAIN -p tcp -i $INTERFACE --dport $INTERNAL_PORT -j DROP +add_new_rule "${CHAIN}" -p tcp -i "${INTERFACE}" --dport "${INTERNAL_PORT}" -j DROP # 9701 create IP whitelist from file while read -r IP; do if [[ "$IP" != "#"* ]] && [[ "$IP" != "" ]]; then - add_new_rule $CHAIN -p tcp --dport $INTERNAL_PORT -s "$IP" -j ACCEPT + add_new_rule "${CHAIN}" -p tcp --dport "${INTERNAL_PORT}" -s "$IP" -j ACCEPT fi done <"$IP_FILE" # make sure, RETURN ist the last rule -make_last_rule $CHAIN -j RETURN +make_last_rule "${CHAIN}" -j RETURN echo "[OK] Connections to ${INTERNAL_PORT} only allowed from white listed ips." echo @@ -80,7 +80,7 @@ echo "[...] Setting DOS protection on port ${CLI_PORT} via ${CLI_PORT_PROTECTION $CLI_PORT_PROTECTION_SCRIPT "${CLI_PORT}" "${OVER_ALL_CONN_LIMIT}" "${CONN_LIMIT_PER_IP}" "${CONN_RATE_LIMIT_LIMIT}" "${CONN_RATE_LIMIT_PERIOD}" debug # make sure, RETURN ist the last rule -make_last_rule $CHAIN -j RETURN +make_last_rule "${CHAIN}" -j RETURN echo "[OK] Rules for connections on port ${CLI_PORT} set." From 071f40c1aba2cb620dc0050f1484b77e0eb0bd4b Mon Sep 17 00:00:00 2001 From: Jens <32765639+jens-mp@users.noreply.github.com> Date: Mon, 24 Jun 2024 10:27:01 +0200 Subject: [PATCH 4/5] Fix syntax error Signed-off-by: Jens <32765639+jens-mp@users.noreply.github.com> --- run/ip_tables_utils.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run/ip_tables_utils.sh b/run/ip_tables_utils.sh index 89084f9..6f506cf 100644 --- a/run/ip_tables_utils.sh +++ b/run/ip_tables_utils.sh @@ -4,7 +4,7 @@ add_new_rule() { RULE=("$@") - if rule_exists "${RULE[@}]}"; then + if rule_exists "${RULE[@]}"; then echo "[skip] ${RULE[*]} already exists" elif [[ "${RULE[*]}" =~ "DROP" ]] || [[ "${RULE[*]}" =~ "RETURN" ]] || [[ "${RULE[*]}" =~ "REJECT" ]]; then iptables -A "${RULE[@]}" From a4147813fcf06bef699f127c2992db79d459ae46 Mon Sep 17 00:00:00 2001 From: Jens Schedel Date: Mon, 24 Jun 2024 10:48:33 +0200 Subject: [PATCH 5/5] Check if iptables-persistent is installed with dpkg The command iptables-save is part of the iptables package and NOT of the iptables-persistent package. Signed-off-by: Jens Schedel --- run/ip_tables_utils.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run/ip_tables_utils.sh b/run/ip_tables_utils.sh index 6f506cf..7657032 100644 --- a/run/ip_tables_utils.sh +++ b/run/ip_tables_utils.sh @@ -46,7 +46,7 @@ ip_tables_installed() { } ip_tables_persistent_installed() { - if which iptables-save 2>/dev/null 1>&2; then + if dpkg-query -W --showformat='${Status}' iptables-persistent | grep "install ok installed" 2>/dev/null 1>&2; then return 0 fi return 1