diff --git a/setup/start.sh b/setup/start.sh index eab218fd5..5c2db2d4f 100755 --- a/setup/start.sh +++ b/setup/start.sh @@ -46,6 +46,7 @@ if [[ "${arg_provider}" == "caas" ]]; then else iptables -A CLOUDRON -p tcp -m tcp -m multiport --dports 25,80,22,443,587,993,4190 -j ACCEPT fi + 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 iptables -t filter -A CLOUDRON -p udp --sport 53 -j ACCEPT @@ -60,6 +61,58 @@ if ! iptables -t filter -C INPUT -j CLOUDRON 2>/dev/null; then iptables -t filter -I INPUT -j CLOUDRON fi +# Setup rate limit chain (the recent info is at /proc/net/xt_recent) +iptables -t filter -N CLOUDRON_RATELIMIT || true +iptables -t filter -F CLOUDRON_RATELIMIT # empty any existing rules + +# log dropped incoming. keep this at the end of all the rules +iptables -t filter -N CLOUDRON_RATELIMIT_LOG || true +iptables -t filter -F CLOUDRON_RATELIMIT_LOG # empty any existing rules +iptables -t filter -A CLOUDRON_RATELIMIT_LOG -m limit --limit 2/min -j LOG --log-prefix "IPTables RateLimit: " --log-level 7 +iptables -t filter -A CLOUDRON_RATELIMIT_LOG -j DROP + +# http https +for port in 80 443; do + iptables -A CLOUDRON_RATELIMIT -p tcp --dport ${port} -m state --state NEW -m recent --set --name "public-${port}" + iptables -A CLOUDRON_RATELIMIT -p tcp --dport ${port} -m state --state NEW -m recent --update --name "public-${port}" --seconds 5 --hitcount 250 -j CLOUDRON_RATELIMIT_LOG +done + +# ssh smtp ssh msa imap sieve +for port in 22 202; do + iptables -A CLOUDRON_RATELIMIT -p tcp --dport ${port} -m state --state NEW -m recent --set --name "public-${port}" + iptables -A CLOUDRON_RATELIMIT -p tcp --dport ${port} -m state --state NEW -m recent --update --name "public-${port}" --seconds 10 --hitcount 10 -j CLOUDRON_RATELIMIT_LOG +done + +# TODO: move docker platform rules to platform.js so it can be specialized to rate limit only when destination is the mail container + +# docker translates (dnat) 25, 587, 993, 4190 in the PREROUTING step +for port in 2525 4190 9993; do + iptables -A CLOUDRON_RATELIMIT -p tcp ! -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m state --state NEW -m recent --set --name "public-${port}" + iptables -A CLOUDRON_RATELIMIT -p tcp ! -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m state --state NEW -m recent --update --name "public-${port}" --seconds 10 --hitcount 10 -j CLOUDRON_RATELIMIT_LOG +done + +# ldap, imap, sieve +for port in 3002 4190 9993; do + iptables -A CLOUDRON_RATELIMIT -p tcp -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m state --state NEW -m recent --set --name "private-${port}" + iptables -A CLOUDRON_RATELIMIT -p tcp -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m state --state NEW -m recent --update --name "private-${port}" --seconds 10 --hitcount 10 -j CLOUDRON_RATELIMIT_LOG +done + +# cloudron docker network: smtp mysql postgresql redis mongodb +for port in 2525 3306 5432 6379 27017; do + iptables -A CLOUDRON_RATELIMIT -p tcp -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m state --state NEW -m recent --set --name "private-${port}" + iptables -A CLOUDRON_RATELIMIT -p tcp -s 172.18.0.0/16 -d 172.18.0.0/16 --dport ${port} -m state --state NEW -m recent --update --name "private-${port}" --seconds 5 --hitcount 250 -j CLOUDRON_RATELIMIT_LOG +done + +# For ssh, http, https +if ! iptables -t filter -C INPUT -j CLOUDRON_RATELIMIT 2>/dev/null; then + iptables -t filter -I INPUT 1 -j CLOUDRON_RATELIMIT +fi + +# For smtp, imap etc routed via docker/nat +if ! iptables -t filter -C FORWARD -j CLOUDRON_RATELIMIT 2>/dev/null; then + iptables -t filter -I FORWARD 1 -j CLOUDRON_RATELIMIT +fi + # so it gets restored across reboot mkdir -p /etc/iptables && iptables-save > /etc/iptables/rules.v4