diff --git a/setup/start/cloudron-firewall.sh b/setup/start/cloudron-firewall.sh index c5f1bf745..23d29f421 100755 --- a/setup/start/cloudron-firewall.sh +++ b/setup/start/cloudron-firewall.sh @@ -6,9 +6,13 @@ echo "==> Setting up firewall" has_ipv6=$(cat /proc/net/if_inet6 >/dev/null 2>&1 && echo "yes" || echo "no") +# wait for 120 seconds for xtables lock, checking every 1 second +readonly iptables="iptables --wait 120 --wait-interval 1" +readonly ip6tables="ip6tables --wait 120 --wait-interval 1" + function ipxtables() { - iptables "$@" - [[ "${has_ipv6}" == "yes" ]] && ip6tables "$@" + $iptables "$@" + [[ "${has_ipv6}" == "yes" ]] && $ip6tables "$@" } ipxtables -t filter -N CLOUDRON || true @@ -20,16 +24,16 @@ ipset create cloudron_blocklist6 hash:net family inet6 || true /home/yellowtent/box/src/scripts/setblocklist.sh -iptables -t filter -A CLOUDRON -m set --match-set cloudron_blocklist src -j DROP +$iptables -t filter -A CLOUDRON -m set --match-set cloudron_blocklist src -j DROP # the DOCKER-USER chain is not cleared on docker restart -if ! iptables -t filter -C DOCKER-USER -m set --match-set cloudron_blocklist src -j DROP; then - iptables -t filter -I DOCKER-USER 1 -m set --match-set cloudron_blocklist src -j DROP +if ! $iptables -t filter -C DOCKER-USER -m set --match-set cloudron_blocklist src -j DROP; then + $iptables -t filter -I DOCKER-USER 1 -m set --match-set cloudron_blocklist src -j DROP fi -ip6tables -t filter -A CLOUDRON -m set --match-set cloudron_blocklist6 src -j DROP +$ip6tables -t filter -A CLOUDRON -m set --match-set cloudron_blocklist6 src -j DROP # there is no DOCKER-USER chain in ip6tables, bug? -ip6tables -D FORWARD -m set --match-set cloudron_blocklist6 src -j DROP || true -ip6tables -I FORWARD 1 -m set --match-set cloudron_blocklist6 src -j DROP +$ip6tables -D FORWARD -m set --match-set cloudron_blocklist6 src -j DROP || true +$ip6tables -I FORWARD 1 -m set --match-set cloudron_blocklist6 src -j DROP # allow related and establisted connections ipxtables -t filter -A CLOUDRON -m state --state RELATED,ESTABLISHED -j ACCEPT @@ -73,8 +77,8 @@ if [[ -f "${ldap_allowlist_json}" ]]; then # ldap server we expose 3004 and also redirect from standard ldaps port 636 ipxtables -t nat -I PREROUTING -p tcp --dport 636 -j REDIRECT --to-ports 3004 - iptables -t filter -A CLOUDRON -m set --match-set cloudron_ldap_allowlist src -p tcp --dport 3004 -j ACCEPT - ip6tables -t filter -A CLOUDRON -m set --match-set cloudron_ldap_allowlist6 src -p tcp --dport 3004 -j ACCEPT + $iptables -t filter -A CLOUDRON -m set --match-set cloudron_ldap_allowlist src -p tcp --dport 3004 -j ACCEPT + $ip6tables -t filter -A CLOUDRON -m set --match-set cloudron_ldap_allowlist6 src -p tcp --dport 3004 -j ACCEPT fi # turn and stun service @@ -83,12 +87,12 @@ ipxtables -t filter -A CLOUDRON -p udp -m multiport --dports 3478,5349 -j ACCEPT ipxtables -t filter -A CLOUDRON -p udp -m multiport --dports 50000:51000 -j ACCEPT # ICMPv6 is very fundamental to IPv6 connectivity unlike ICMPv4 -iptables -t filter -A CLOUDRON -p icmp --icmp-type echo-request -j ACCEPT -iptables -t filter -A CLOUDRON -p icmp --icmp-type echo-reply -j ACCEPT -ip6tables -t filter -A CLOUDRON -p ipv6-icmp -j ACCEPT +$iptables -t filter -A CLOUDRON -p icmp --icmp-type echo-request -j ACCEPT +$iptables -t filter -A CLOUDRON -p icmp --icmp-type echo-reply -j ACCEPT +$ip6tables -t filter -A CLOUDRON -p ipv6-icmp -j ACCEPT ipxtables -t filter -A CLOUDRON -p udp --sport 53 -j ACCEPT -iptables -t filter -A CLOUDRON -s 172.18.0.0/16 -j ACCEPT # required to accept any connections from apps to our IP: +$iptables -t filter -A CLOUDRON -s 172.18.0.0/16 -j ACCEPT # required to accept any connections from apps to our IP: ipxtables -t filter -A CLOUDRON -i lo -j ACCEPT # required for localhost connections (mysql) # log dropped incoming. keep this at the end of all the rules @@ -96,8 +100,8 @@ ipxtables -t filter -A CLOUDRON -m limit --limit 2/min -j LOG --log-prefix "Pack ipxtables -t filter -A CLOUDRON -j DROP # prepend our chain to the filter table -iptables -t filter -C INPUT -j CLOUDRON 2>/dev/null || iptables -t filter -I INPUT -j CLOUDRON -ip6tables -t filter -C INPUT -j CLOUDRON 2>/dev/null || ip6tables -t filter -I INPUT -j CLOUDRON +$iptables -t filter -C INPUT -j CLOUDRON 2>/dev/null || $iptables -t filter -I INPUT -j CLOUDRON +$ip6tables -t filter -C INPUT -j CLOUDRON 2>/dev/null || $ip6tables -t filter -I INPUT -j CLOUDRON # Setup rate limit chain (the recent info is at /proc/net/xt_recent) ipxtables -t filter -N CLOUDRON_RATELIMIT || true @@ -127,21 +131,21 @@ done # docker translates (dnat) 25, 587, 993, 4190 in the PREROUTING step for port in 2525 4190 9993; do - iptables -A CLOUDRON_RATELIMIT -p tcp --syn ! -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m connlimit --connlimit-above 50 -j CLOUDRON_RATELIMIT_LOG + $iptables -A CLOUDRON_RATELIMIT -p tcp --syn ! -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m connlimit --connlimit-above 50 -j CLOUDRON_RATELIMIT_LOG done # msa, ldap, imap, sieve, pop3 for port in 2525 3002 4190 9993 9995; do - iptables -A CLOUDRON_RATELIMIT -p tcp --syn -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m connlimit --connlimit-above 500 -j CLOUDRON_RATELIMIT_LOG + $iptables -A CLOUDRON_RATELIMIT -p tcp --syn -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m connlimit --connlimit-above 500 -j CLOUDRON_RATELIMIT_LOG done # cloudron docker network: mysql postgresql redis mongodb for port in 3306 5432 6379 27017; do - iptables -A CLOUDRON_RATELIMIT -p tcp --syn -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m connlimit --connlimit-above 5000 -j CLOUDRON_RATELIMIT_LOG + $iptables -A CLOUDRON_RATELIMIT -p tcp --syn -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m connlimit --connlimit-above 5000 -j CLOUDRON_RATELIMIT_LOG done -iptables -t filter -C INPUT -j CLOUDRON_RATELIMIT 2>/dev/null || iptables -t filter -I INPUT 1 -j CLOUDRON_RATELIMIT -ip6tables -t filter -C INPUT -j CLOUDRON_RATELIMIT 2>/dev/null || ip6tables -t filter -I INPUT 1 -j CLOUDRON_RATELIMIT +$iptables -t filter -C INPUT -j CLOUDRON_RATELIMIT 2>/dev/null || $iptables -t filter -I INPUT 1 -j CLOUDRON_RATELIMIT +$ip6tables -t filter -C INPUT -j CLOUDRON_RATELIMIT 2>/dev/null || $ip6tables -t filter -I INPUT 1 -j CLOUDRON_RATELIMIT # Workaround issue where Docker insists on adding itself first in FORWARD table ipxtables -D FORWARD -j CLOUDRON_RATELIMIT || true