ip6t-firewall-server,ipt-firewall-server: HTTP limits only for local webserver; fix several bugs.
- HTTP(S) connection limits are only created if 'http_server_ips' is set.
The global SYN rate limit no longer ACCEPTs packets (which opened ports
80/443 on every host) - it now only drops packets above the limit
(hashlimit without '--hashlimit-mode'). Ports are opened exclusively by
the rules for 'http_server_ips'.
- Use '$http_ports' instead of hard coded '80,443' for the limits.
- ipt-firewall-server: use '--connlimit-mask 32' instead of 128. With the
nf_tables backend mask 128 ended up as mask 0, so the limit applied to
all clients together instead of per IP. Rename hashlimit 'http_v6' -> 'http_v4'.
- Log rules use their own hashlimit tables ('*_log'), otherwise each packet
is counted twice when logging is enabled.
- SYN-Overflow log rule now logs packets above (not below) the limit.
- ip6t-firewall-server: clamp TCP MSS for HTTPS on all external interfaces
instead of hard coded 'eth0'.
- Quote test for 'mm_tcp_ports_in' ('[ -n ${mm_tcp_ports_in} ]' was always true).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+42
-31
@@ -736,10 +736,12 @@ if $throttle_tcp6_mss_for_https ; then
|
||||
tcp6_mss_for_https_val=$min_tcp6_mss_for_https_val
|
||||
fi
|
||||
|
||||
$ip6t -t mangle -A PREROUTING -i eth0 \
|
||||
-p tcp --dport 443 \
|
||||
--tcp-flags SYN,RST SYN \
|
||||
-j TCPMSS --set-mss $tcp6_mss_for_https_val
|
||||
for _dev in ${ext_if_arr[@]} ; do
|
||||
$ip6t -t mangle -A PREROUTING -i $_dev \
|
||||
-p tcp --dport 443 \
|
||||
--tcp-flags SYN,RST SYN \
|
||||
-j TCPMSS --set-mss $tcp6_mss_for_https_val
|
||||
done
|
||||
|
||||
echo_done
|
||||
|
||||
@@ -2169,9 +2171,15 @@ echo_done
|
||||
# ---
|
||||
|
||||
echo ""
|
||||
|
||||
# Note:
|
||||
# The following rules only DROP/REJECT excess connections - they never ACCEPT.
|
||||
# Ports are opened exclusively by the rules for 'http_server_ips' below.
|
||||
# Without local webserver (empty 'http_server_ips') no rules are created.
|
||||
#
|
||||
echononl "\t\tA maximum number new connections per second per IP"
|
||||
|
||||
if $set_max_new_http_conn_per_ip_per_second ; then
|
||||
if [[ ${#http_server_ip_arr[@]} -gt 0 ]] && $set_max_new_http_conn_per_ip_per_second ; then
|
||||
|
||||
if [[ -z "$max_http_new_conn_per_ip_per_second" || ! "$max_http_new_conn_per_ip_per_second" =~ ^[0-9]+$ ]]; then
|
||||
|
||||
@@ -2182,8 +2190,8 @@ if $set_max_new_http_conn_per_ip_per_second ; then
|
||||
burst_http_new_conn_per_ip_per_second=$((max_http_new_conn_per_ip_per_second * 2))
|
||||
|
||||
if $log_rejected || $log_all ; then
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW \
|
||||
-m hashlimit --hashlimit-name http_v6 --hashlimit-mode srcip \
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports $http_ports -m conntrack --ctstate NEW \
|
||||
-m hashlimit --hashlimit-name http_v6_log --hashlimit-mode srcip \
|
||||
--hashlimit-above ${max_http_new_conn_per_ip_per_second}/second \
|
||||
--hashlimit-burst $burst_http_new_conn_per_ip_per_second \
|
||||
--hashlimit-htable-expire 600000 \
|
||||
@@ -2192,9 +2200,9 @@ if $set_max_new_http_conn_per_ip_per_second ; then
|
||||
fi
|
||||
|
||||
# HTTP/HTTPS: neue Verbindungen pro Quell-IP begrenzen
|
||||
# Über 30 neue Verbindungen/s pro IP werden gedroppt
|
||||
# Über 'max_http_new_conn_per_ip_per_second' neue Verbindungen/s pro IP werden gedroppt
|
||||
# Eintrag wird nach 600000 ms = 10 Minuten gelöscht (--hashlimit-htable-expire 600000).
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW \
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports $http_ports -m conntrack --ctstate NEW \
|
||||
-m hashlimit --hashlimit-name http_v6 --hashlimit-mode srcip \
|
||||
--hashlimit-above ${max_http_new_conn_per_ip_per_second}/second \
|
||||
--hashlimit-burst $burst_http_new_conn_per_ip_per_second \
|
||||
@@ -2211,8 +2219,7 @@ fi
|
||||
|
||||
echononl "\t\tA maximum number of concurrent TCP connections per IP"
|
||||
|
||||
|
||||
if $set_max_concurrent_http_conn_per_ip ; then
|
||||
if [[ ${#http_server_ip_arr[@]} -gt 0 ]] && $set_max_concurrent_http_conn_per_ip ; then
|
||||
|
||||
if [[ -z "$max_concurrent_http_conn_per_ip" || ! "$max_concurrent_http_conn_per_ip" =~ ^[0-9]+$ ]]; then
|
||||
|
||||
@@ -2221,17 +2228,17 @@ if $set_max_concurrent_http_conn_per_ip ; then
|
||||
fi
|
||||
|
||||
if $log_rejected || $log_all ; then
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports 80,443 --syn \
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports $http_ports --syn \
|
||||
-m connlimit --connlimit-above $max_concurrent_http_conn_per_ip --connlimit-mask 128 \
|
||||
-m limit --limit 10/second --limit-burst 20 \
|
||||
-j $LOG_TARGET $tag_log_prefix "$log_prefix more then $max_concurrent_http_conn_per_ip concurrent connections per IP."
|
||||
fi
|
||||
|
||||
# HTTP/HTTPS: gleichzeitige Verbindungen pro IP begrenzen
|
||||
# Mehr als 50 parallele TCP-Verbindungen pro IP ablehnen
|
||||
# Mehr als 'max_concurrent_http_conn_per_ip' parallele TCP-Verbindungen pro IP ablehnen
|
||||
#
|
||||
# Limit gilt pro einzelner IPv4-Adresse (--connlimit-mask 128) (z.bsp. 2a01:599:108:40b0:e1a9:170b:ba18:fd58/128)
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports 80,443 --syn \
|
||||
# Limit gilt pro einzelner IPv6-Adresse (--connlimit-mask 128) (z.bsp. 2a01:599:108:40b0:e1a9:170b:ba18:fd58/128)
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports $http_ports --syn \
|
||||
-m connlimit --connlimit-above $max_concurrent_http_conn_per_ip --connlimit-mask 128 \
|
||||
-j REJECT --reject-with tcp-reset
|
||||
|
||||
@@ -2244,10 +2251,9 @@ else
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echononl "\t\tA maximum number of new TCP handshakes per second."
|
||||
|
||||
if $set_max_new_http_conn_per_second ; then
|
||||
if [[ ${#http_server_ip_arr[@]} -gt 0 ]] && $set_max_new_http_conn_per_second ; then
|
||||
|
||||
if [[ -z "$max_new_http_conn_per_second" || ! "$max_new_http_conn_per_second" =~ ^[0-9]+$ ]]; then
|
||||
|
||||
@@ -2257,23 +2263,28 @@ if $set_max_new_http_conn_per_second ; then
|
||||
|
||||
burst_max_new_http_conn_per_second=$((2 * max_new_http_conn_per_second))
|
||||
|
||||
# SYN-Rate begrenzen
|
||||
# SYN-Rate begrenzen (global, alle Quell-IPs zusammen)
|
||||
#
|
||||
# Kurzfristig auch bis zu 400 syn pakete erlaubt. --limit-burst 400 - Danach greift das Limit."
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports 80,443 \
|
||||
--syn \
|
||||
-m limit --limit ${max_new_http_conn_per_second}/second --limit-burst $burst_max_new_http_conn_per_second \
|
||||
-j ACCEPT
|
||||
|
||||
# hashlimit ohne '--hashlimit-mode' verwendet einen einzigen Bucket für alle
|
||||
# Pakete. SYN-Pakete oberhalb des Limits werden gedroppt; alles darunter
|
||||
# läuft weiter zu den Regeln für 'http_server_ips' (kein ACCEPT hier!).
|
||||
#
|
||||
# Kurzfristig auch bis zu 'burst_max_new_http_conn_per_second' SYN-Pakete erlaubt.
|
||||
if $log_rejected || $log_all ; then
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports 80,443 \
|
||||
--syn \
|
||||
-m limit --limit ${max_new_http_conn_per_second}/second --limit-burst $burst_max_new_http_conn_per_second \
|
||||
-j $LOG_TARGET $tag_log_prefix "$log_prefix SYN-Overflow."
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports $http_ports \
|
||||
--syn \
|
||||
-m hashlimit --hashlimit-name http_v6_syn_log \
|
||||
--hashlimit-above ${max_new_http_conn_per_second}/second \
|
||||
--hashlimit-burst $burst_max_new_http_conn_per_second \
|
||||
-m limit --limit 10/second --limit-burst 20 \
|
||||
-j $LOG_TARGET $tag_log_prefix "$log_prefix SYN-Overflow."
|
||||
fi
|
||||
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports 80,443 \
|
||||
$ip6t -A INPUT -p tcp -m multiport --dports $http_ports \
|
||||
--syn \
|
||||
-m hashlimit --hashlimit-name http_v6_syn \
|
||||
--hashlimit-above ${max_new_http_conn_per_second}/second \
|
||||
--hashlimit-burst $burst_max_new_http_conn_per_second \
|
||||
-j DROP
|
||||
|
||||
echo_done
|
||||
@@ -2319,7 +2330,7 @@ if [[ ${#mm_server_ip_arr[@]} -gt 0 ]] || [[ ${#forward_mm_server_ip_arr[@]} -gt
|
||||
if [[ ${#mm_server_ip_arr[@]} -gt 0 ]] ; then
|
||||
for _ip in ${mm_server_ip_arr[@]} ; do
|
||||
$ip6t -A INPUT -p udp -d $_ip -m multiport --dports $mm_udp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
if [ -n ${mm_tcp_ports_in} ] ; then
|
||||
if [[ -n "$mm_tcp_ports_in" ]] ; then
|
||||
$ip6t -A INPUT -p tcp -d $_ip -m multiport --dports $mm_tcp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
else
|
||||
$ip6t -A INPUT -p tcp -d $_ip -m multiport --dports $mm_udp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
@@ -2330,7 +2341,7 @@ if [[ ${#mm_server_ip_arr[@]} -gt 0 ]] || [[ ${#forward_mm_server_ip_arr[@]} -gt
|
||||
if [[ ${#forward_mm_server_ip_arr[@]} -gt 0 ]] && $kernel_forward_between_interfaces ; then
|
||||
for _ip in ${forward_mm_server_ip_arr[@]} ; do
|
||||
$ip6t -A FORWARD -p udp -d $_ip -m multiport --dports $mm_udp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
if [ -n ${mm_tcp_ports_in} ] ; then
|
||||
if [[ -n "$mm_tcp_ports_in" ]] ; then
|
||||
$ip6t -A FORWARD -p tcp -d $_ip -m multiport --dports $mm_tcp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
else
|
||||
$ip6t -A FORWARD -p tcp -d $_ip -m multiport --dports $mm_udp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
|
||||
+39
-28
@@ -2247,9 +2247,15 @@ echo_done
|
||||
# ---
|
||||
|
||||
echo ""
|
||||
|
||||
# Note:
|
||||
# The following rules only DROP/REJECT excess connections - they never ACCEPT.
|
||||
# Ports are opened exclusively by the rules for 'http_server_ips' below.
|
||||
# Without local webserver (empty 'http_server_ips') no rules are created.
|
||||
#
|
||||
echononl "\t\tA maximum number new connections per second per IP"
|
||||
|
||||
if $set_max_new_http_conn_per_ip_per_second ; then
|
||||
if [[ ${#http_server_ip_arr[@]} -gt 0 ]] && $set_max_new_http_conn_per_ip_per_second ; then
|
||||
|
||||
if [[ -z "$max_http_new_conn_per_ip_per_second" || ! "$max_http_new_conn_per_ip_per_second" =~ ^[0-9]+$ ]]; then
|
||||
|
||||
@@ -2260,8 +2266,8 @@ if $set_max_new_http_conn_per_ip_per_second ; then
|
||||
burst_http_new_conn_per_ip_per_second=$((max_http_new_conn_per_ip_per_second * 2))
|
||||
|
||||
if $log_rejected || $log_all ; then
|
||||
$ipt -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW \
|
||||
-m hashlimit --hashlimit-name http_v6 --hashlimit-mode srcip \
|
||||
$ipt -A INPUT -p tcp -m multiport --dports $http_ports -m conntrack --ctstate NEW \
|
||||
-m hashlimit --hashlimit-name http_v4_log --hashlimit-mode srcip \
|
||||
--hashlimit-above ${max_http_new_conn_per_ip_per_second}/second \
|
||||
--hashlimit-burst $burst_http_new_conn_per_ip_per_second \
|
||||
--hashlimit-htable-expire 600000 \
|
||||
@@ -2270,10 +2276,10 @@ if $set_max_new_http_conn_per_ip_per_second ; then
|
||||
fi
|
||||
|
||||
# HTTP/HTTPS: neue Verbindungen pro Quell-IP begrenzen
|
||||
# Über 30 neue Verbindungen/s pro IP werden gedroppt
|
||||
# Über 'max_http_new_conn_per_ip_per_second' neue Verbindungen/s pro IP werden gedroppt
|
||||
# Eintrag wird nach 600000 ms = 10 Minuten gelöscht (--hashlimit-htable-expire 600000).
|
||||
$ipt -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW \
|
||||
-m hashlimit --hashlimit-name http_v6 --hashlimit-mode srcip \
|
||||
$ipt -A INPUT -p tcp -m multiport --dports $http_ports -m conntrack --ctstate NEW \
|
||||
-m hashlimit --hashlimit-name http_v4 --hashlimit-mode srcip \
|
||||
--hashlimit-above ${max_http_new_conn_per_ip_per_second}/second \
|
||||
--hashlimit-burst $burst_http_new_conn_per_ip_per_second \
|
||||
--hashlimit-htable-expire 600000 -j DROP
|
||||
@@ -2289,7 +2295,7 @@ fi
|
||||
|
||||
echononl "\t\tA maximum number of concurrent TCP connections per IP"
|
||||
|
||||
if $set_max_concurrent_http_conn_per_ip ; then
|
||||
if [[ ${#http_server_ip_arr[@]} -gt 0 ]] && $set_max_concurrent_http_conn_per_ip ; then
|
||||
|
||||
if [[ -z "$max_concurrent_http_conn_per_ip" || ! "$max_concurrent_http_conn_per_ip" =~ ^[0-9]+$ ]]; then
|
||||
|
||||
@@ -2298,18 +2304,18 @@ if $set_max_concurrent_http_conn_per_ip ; then
|
||||
fi
|
||||
|
||||
if $log_rejected || $log_all ; then
|
||||
$ipt -A INPUT -p tcp -m multiport --dports 80,443 --syn \
|
||||
-m connlimit --connlimit-above $max_concurrent_http_conn_per_ip --connlimit-mask 128 \
|
||||
$ipt -A INPUT -p tcp -m multiport --dports $http_ports --syn \
|
||||
-m connlimit --connlimit-above $max_concurrent_http_conn_per_ip --connlimit-mask 32 \
|
||||
-m limit --limit 10/second --limit-burst 20 \
|
||||
-j $LOG_TARGET $tag_log_prefix "$log_prefix more then $max_concurrent_http_conn_per_ip concurrent connections per IP."
|
||||
fi
|
||||
|
||||
# HTTP/HTTPS: gleichzeitige Verbindungen pro IP begrenzen
|
||||
# Mehr als 50 parallele TCP-Verbindungen pro IP ablehnen
|
||||
# Mehr als 'max_concurrent_http_conn_per_ip' parallele TCP-Verbindungen pro IP ablehnen
|
||||
#
|
||||
# Limit gilt pro einzelner IPv4-Adresse (--connlimit-mask 128) (z.bsp. 2a01:599:108:40b0:e1a9:170b:ba18:fd58/128)
|
||||
$ipt -A INPUT -p tcp -m multiport --dports 80,443 --syn \
|
||||
-m connlimit --connlimit-above $max_concurrent_http_conn_per_ip --connlimit-mask 128 \
|
||||
# Limit gilt pro einzelner IPv4-Adresse (--connlimit-mask 32)
|
||||
$ipt -A INPUT -p tcp -m multiport --dports $http_ports --syn \
|
||||
-m connlimit --connlimit-above $max_concurrent_http_conn_per_ip --connlimit-mask 32 \
|
||||
-j REJECT --reject-with tcp-reset
|
||||
|
||||
echo_done
|
||||
@@ -2323,7 +2329,7 @@ fi
|
||||
|
||||
echononl "\t\tA maximum number of new TCP handshakes per second."
|
||||
|
||||
if $set_max_new_http_conn_per_second ; then
|
||||
if [[ ${#http_server_ip_arr[@]} -gt 0 ]] && $set_max_new_http_conn_per_second ; then
|
||||
|
||||
if [[ -z "$max_new_http_conn_per_second" || ! "$max_new_http_conn_per_second" =~ ^[0-9]+$ ]]; then
|
||||
|
||||
@@ -2333,23 +2339,28 @@ if $set_max_new_http_conn_per_second ; then
|
||||
|
||||
burst_max_new_http_conn_per_second=$((2 * max_new_http_conn_per_second))
|
||||
|
||||
# SYN-Rate begrenzen
|
||||
# SYN-Rate begrenzen (global, alle Quell-IPs zusammen)
|
||||
#
|
||||
# Kurzfristig auch bis zu 400 syn pakete erlaubt. --limit-burst 400 - Danach greift das Limit."
|
||||
$ipt -A INPUT -p tcp -m multiport --dports 80,443 \
|
||||
--syn \
|
||||
-m limit --limit ${max_new_http_conn_per_second}/second --limit-burst $burst_max_new_http_conn_per_second \
|
||||
-j ACCEPT
|
||||
|
||||
# hashlimit ohne '--hashlimit-mode' verwendet einen einzigen Bucket für alle
|
||||
# Pakete. SYN-Pakete oberhalb des Limits werden gedroppt; alles darunter
|
||||
# läuft weiter zu den Regeln für 'http_server_ips' (kein ACCEPT hier!).
|
||||
#
|
||||
# Kurzfristig auch bis zu 'burst_max_new_http_conn_per_second' SYN-Pakete erlaubt.
|
||||
if $log_rejected || $log_all ; then
|
||||
$ipt -A INPUT -p tcp -m multiport --dports 80,443 \
|
||||
--syn \
|
||||
-m limit --limit ${max_new_http_conn_per_second}/second --limit-burst $burst_max_new_http_conn_per_second \
|
||||
-j $LOG_TARGET $tag_log_prefix "$log_prefix SYN-Overflow."
|
||||
$ipt -A INPUT -p tcp -m multiport --dports $http_ports \
|
||||
--syn \
|
||||
-m hashlimit --hashlimit-name http_v4_syn_log \
|
||||
--hashlimit-above ${max_new_http_conn_per_second}/second \
|
||||
--hashlimit-burst $burst_max_new_http_conn_per_second \
|
||||
-m limit --limit 10/second --limit-burst 20 \
|
||||
-j $LOG_TARGET $tag_log_prefix "$log_prefix SYN-Overflow."
|
||||
fi
|
||||
|
||||
$ipt -A INPUT -p tcp -m multiport --dports 80,443 \
|
||||
$ipt -A INPUT -p tcp -m multiport --dports $http_ports \
|
||||
--syn \
|
||||
-m hashlimit --hashlimit-name http_v4_syn \
|
||||
--hashlimit-above ${max_new_http_conn_per_second}/second \
|
||||
--hashlimit-burst $burst_max_new_http_conn_per_second \
|
||||
-j DROP
|
||||
|
||||
echo_done
|
||||
@@ -2395,7 +2406,7 @@ if [[ ${#mm_server_ip_arr[@]} -gt 0 ]] || [[ ${#forward_mm_server_ip_arr[@]} -gt
|
||||
if [[ ${#mm_server_ip_arr[@]} -gt 0 ]] ; then
|
||||
for _ip in ${mm_server_ip_arr[@]} ; do
|
||||
$ipt -A INPUT -p udp -d $_ip -m multiport --dports $mm_udp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
if [ -n ${mm_tcp_ports_in} ] ; then
|
||||
if [[ -n "$mm_tcp_ports_in" ]] ; then
|
||||
$ipt -A INPUT -p tcp -d $_ip -m multiport --dports $mm_tcp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
else
|
||||
$ipt -A INPUT -p tcp -d $_ip -m multiport --dports $mm_udp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
@@ -2406,7 +2417,7 @@ if [[ ${#mm_server_ip_arr[@]} -gt 0 ]] || [[ ${#forward_mm_server_ip_arr[@]} -gt
|
||||
if [[ ${#forward_mm_server_ip_arr[@]} -gt 0 ]] && $kernel_activate_forwarding ; then
|
||||
for _ip in ${forward_mm_server_ip_arr[@]} ; do
|
||||
$ipt -A FORWARD -p udp -d $_ip -m multiport --dports $mm_udp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
if [ -n ${mm_tcp_ports_in} ] ; then
|
||||
if [[ -n "$mm_tcp_ports_in" ]] ; then
|
||||
$ipt -A FORWARD -p tcp -d $_ip -m multiport --dports $mm_tcp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
else
|
||||
$ipt -A FORWARD -p tcp -d $_ip -m multiport --dports $mm_udp_ports_in -m conntrack --ctstate NEW -j ACCEPT
|
||||
|
||||
Reference in New Issue
Block a user