2017-03-29 02:18:38 -07:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
set -eu -o pipefail
|
|
|
|
|
|
|
|
|
|
echo "==> Setting up firewall"
|
2022-02-09 17:47:48 -08:00
|
|
|
|
2022-02-09 22:13:12 -08:00
|
|
|
has_ipv6=$(cat /proc/net/if_inet6 >/dev/null 2>&1 && echo "yes" || echo "no")
|
2022-02-09 17:47:48 -08:00
|
|
|
|
2022-02-20 17:42:20 -08:00
|
|
|
# wait for 120 seconds for xtables lock, checking every 1 second
|
2025-01-02 23:44:50 +01:00
|
|
|
readonly iptables="iptables --wait 120"
|
|
|
|
|
readonly ip6tables="ip6tables --wait 120"
|
2022-02-20 17:42:20 -08:00
|
|
|
|
2022-02-09 22:13:12 -08:00
|
|
|
function ipxtables() {
|
2022-02-20 17:42:20 -08:00
|
|
|
$iptables "$@"
|
|
|
|
|
[[ "${has_ipv6}" == "yes" ]] && $ip6tables "$@"
|
2022-02-09 22:13:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ipxtables -t filter -N CLOUDRON || true
|
|
|
|
|
ipxtables -t filter -F CLOUDRON # empty any existing rules
|
2017-03-29 02:18:38 -07:00
|
|
|
|
2023-12-07 22:39:36 +01:00
|
|
|
# first setup any user IP block lists . remove all references in iptables before destroying them
|
|
|
|
|
echo "==> Creating ipset cloudron_blocklist"
|
|
|
|
|
$iptables -t filter -D DOCKER-USER -m set --match-set cloudron_blocklist src -j DROP || true
|
|
|
|
|
sleep 1 # without this there is a race that iptables is still referencing the ipset
|
|
|
|
|
ipset destroy cloudron_blocklist || true
|
|
|
|
|
ipset create cloudron_blocklist hash:net maxelem 262144 || true # if you change the size, change network.js size check
|
|
|
|
|
|
|
|
|
|
echo "==> Creating ipset cloudron_blocklist6"
|
|
|
|
|
$ip6tables -D FORWARD -m set --match-set cloudron_blocklist6 src -j DROP || true
|
|
|
|
|
sleep 1 # without this there is a race that iptables is still referencing the ipset
|
|
|
|
|
ipset destroy cloudron_blocklist6 || true
|
|
|
|
|
ipset create cloudron_blocklist6 hash:net family inet6 maxelem 262144 || true # if you change the size, change network.js size check
|
2022-02-16 13:09:24 -08:00
|
|
|
|
2020-08-31 18:22:33 -07:00
|
|
|
/home/yellowtent/box/src/scripts/setblocklist.sh
|
|
|
|
|
|
2022-02-20 17:42:20 -08:00
|
|
|
$iptables -t filter -A CLOUDRON -m set --match-set cloudron_blocklist src -j DROP
|
2023-12-07 22:39:36 +01:00
|
|
|
$iptables -t filter -I DOCKER-USER 1 -m set --match-set cloudron_blocklist src -j DROP # the DOCKER-USER chain is not cleared on docker restart
|
2020-08-31 18:22:33 -07:00
|
|
|
|
2022-02-20 17:42:20 -08:00
|
|
|
$ip6tables -t filter -A CLOUDRON -m set --match-set cloudron_blocklist6 src -j DROP
|
2023-12-07 22:39:36 +01:00
|
|
|
$ip6tables -I FORWARD 1 -m set --match-set cloudron_blocklist6 src -j DROP # there is no DOCKER-USER chain in ip6tables, bug?
|
2022-02-16 13:09:24 -08:00
|
|
|
|
2020-08-31 21:55:45 -07:00
|
|
|
# allow related and establisted connections
|
2023-12-08 11:05:55 +01:00
|
|
|
echo "==> Opening standard ports"
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -t filter -A CLOUDRON -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
|
|
|
ipxtables -t filter -A CLOUDRON -p tcp -m tcp -m multiport --dports 22,80,202,443 -j ACCEPT # 202 is the alternate ssh port
|
2020-08-31 21:55:45 -07:00
|
|
|
|
2021-02-12 08:13:47 -08:00
|
|
|
# whitelist any user ports. we used to use --dports but it has a 15 port limit (XT_MULTI_PORTS)
|
2023-12-08 11:05:55 +01:00
|
|
|
echo "==> Opening up user specified ports"
|
2021-05-04 15:21:38 -07:00
|
|
|
ports_json="/home/yellowtent/platformdata/firewall/ports.json"
|
2022-02-22 00:54:51 -08:00
|
|
|
if allowed_tcp_ports=$(node -e "console.log(JSON.parse(fs.readFileSync('${ports_json}', 'utf8')).allowed_tcp_ports.join(' '))" 2>/dev/null); then
|
|
|
|
|
for p in $allowed_tcp_ports; do
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -A CLOUDRON -p tcp -m tcp --dport "${p}" -j ACCEPT
|
2021-02-12 15:56:19 +01:00
|
|
|
done
|
2020-08-31 21:55:45 -07:00
|
|
|
fi
|
|
|
|
|
|
2022-02-22 00:54:51 -08:00
|
|
|
if allowed_udp_ports=$(node -e "console.log(JSON.parse(fs.readFileSync('${ports_json}', 'utf8')).allowed_udp_ports.join(' '))" 2>/dev/null); then
|
|
|
|
|
for p in $allowed_udp_ports; do
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -A CLOUDRON -p udp -m udp --dport "${p}" -j ACCEPT
|
2021-02-12 15:56:19 +01:00
|
|
|
done
|
2020-11-30 10:26:39 -08:00
|
|
|
fi
|
|
|
|
|
|
2022-02-16 13:09:24 -08:00
|
|
|
# LDAP user directory allow list
|
2023-12-08 11:05:55 +01:00
|
|
|
echo "==> Configuring LDAP allow list"
|
2023-12-07 22:39:36 +01:00
|
|
|
if ! ipset list cloudron_ldap_allowlist >/dev/null 2>&1; then
|
|
|
|
|
echo "==> Creating the cloudron_ldap_allowlist ipset"
|
|
|
|
|
ipset create cloudron_ldap_allowlist hash:net
|
|
|
|
|
fi
|
2021-12-15 18:45:51 +01:00
|
|
|
ipset flush cloudron_ldap_allowlist
|
|
|
|
|
|
2023-12-07 22:39:36 +01:00
|
|
|
if ! ipset list cloudron_ldap_allowlist6 >/dev/null 2>&1; then
|
|
|
|
|
echo "==> Creating the cloudron_ldap_allowlist6 ipset"
|
|
|
|
|
ipset create cloudron_ldap_allowlist6 hash:net family inet6
|
|
|
|
|
fi
|
2022-02-16 13:09:24 -08:00
|
|
|
ipset flush cloudron_ldap_allowlist6
|
|
|
|
|
|
2024-01-13 12:29:00 +01:00
|
|
|
ldap_allowlist="/home/yellowtent/platformdata/firewall/ldap_allowlist.txt"
|
2022-03-21 12:25:18 -07:00
|
|
|
# delete any existing redirect rule
|
|
|
|
|
$iptables -t nat -D PREROUTING -p tcp --dport 636 -j REDIRECT --to-ports 3004 2>/dev/null || true
|
|
|
|
|
$ip6tables -t nat -D PREROUTING -p tcp --dport 636 -j REDIRECT --to-ports 3004 >/dev/null || true
|
2024-01-13 12:29:00 +01:00
|
|
|
if [[ -f "${ldap_allowlist}" ]]; then
|
2021-12-15 18:45:51 +01:00
|
|
|
# without the -n block, any last line without a new line won't be read it!
|
|
|
|
|
while read -r line || [[ -n "$line" ]]; do
|
|
|
|
|
[[ -z "${line}" ]] && continue # ignore empty lines
|
|
|
|
|
[[ "$line" =~ ^#.*$ ]] && continue # ignore lines starting with #
|
2022-02-16 13:09:24 -08:00
|
|
|
if [[ "$line" == *":"* ]]; then
|
|
|
|
|
ipset add -! cloudron_ldap_allowlist6 "${line}" # the -! ignore duplicates
|
|
|
|
|
else
|
|
|
|
|
ipset add -! cloudron_ldap_allowlist "${line}" # the -! ignore duplicates
|
|
|
|
|
fi
|
2024-01-13 12:29:00 +01:00
|
|
|
done < "${ldap_allowlist}"
|
2021-12-15 18:45:51 +01:00
|
|
|
|
|
|
|
|
# ldap server we expose 3004 and also redirect from standard ldaps port 636
|
2022-03-21 12:25:18 -07:00
|
|
|
$iptables -t nat -I PREROUTING -p tcp --dport 636 -j REDIRECT --to-ports 3004
|
2022-02-20 17:42:20 -08:00
|
|
|
$iptables -t filter -A CLOUDRON -m set --match-set cloudron_ldap_allowlist src -p tcp --dport 3004 -j ACCEPT
|
2022-03-21 12:25:18 -07:00
|
|
|
|
|
|
|
|
$ip6tables -t nat -I PREROUTING -p tcp --dport 636 -j REDIRECT --to-ports 3004
|
2022-02-20 17:42:20 -08:00
|
|
|
$ip6tables -t filter -A CLOUDRON -m set --match-set cloudron_ldap_allowlist6 src -p tcp --dport 3004 -j ACCEPT
|
2021-12-15 18:45:51 +01:00
|
|
|
fi
|
2021-11-22 21:10:36 +01:00
|
|
|
|
2020-03-28 23:33:44 +01:00
|
|
|
# turn and stun service
|
2023-12-08 11:05:55 +01:00
|
|
|
echo "==> Opening ports for TURN and STUN"
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -t filter -A CLOUDRON -p tcp -m multiport --dports 3478,5349 -j ACCEPT
|
|
|
|
|
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
|
2020-03-28 23:33:44 +01:00
|
|
|
|
2022-02-09 22:13:12 -08:00
|
|
|
# ICMPv6 is very fundamental to IPv6 connectivity unlike ICMPv4
|
2023-12-08 11:05:55 +01:00
|
|
|
echo "==> Allow ICMP"
|
2022-02-20 17:42:20 -08:00
|
|
|
$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
|
2025-04-29 22:05:07 +02:00
|
|
|
# NDP (546) and RA (547) portion of ICMPv6
|
|
|
|
|
$ip6tables -t filter -A CLOUDRON -p udp --sport 547 --dport 546 -j ACCEPT
|
2022-02-09 22:13:12 -08:00
|
|
|
|
|
|
|
|
ipxtables -t filter -A CLOUDRON -p udp --sport 53 -j ACCEPT
|
2025-01-03 21:14:19 +01:00
|
|
|
# for ldap,dockerproxy server (ipv4 only) to accept connections from apps. for connecting to addons and mail container ports, docker already has rules
|
|
|
|
|
$iptables -t filter -A CLOUDRON -p tcp -s 172.18.0.0/16 -d 172.18.0.1 -m multiport --dports 3002,3003 -j ACCEPT
|
2025-01-03 19:50:19 +01:00
|
|
|
$iptables -t filter -A CLOUDRON -p udp -s 172.18.0.0/16 --dport 53 -j ACCEPT # dns responses from docker (127.0.0.11)
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -t filter -A CLOUDRON -i lo -j ACCEPT # required for localhost connections (mysql)
|
2017-03-29 02:18:38 -07:00
|
|
|
|
|
|
|
|
# log dropped incoming. keep this at the end of all the rules
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -t filter -A CLOUDRON -m limit --limit 2/min -j LOG --log-prefix "Packet dropped: " --log-level 7
|
|
|
|
|
ipxtables -t filter -A CLOUDRON -j DROP
|
2017-03-29 02:18:38 -07:00
|
|
|
|
2022-02-09 22:13:12 -08:00
|
|
|
# prepend our chain to the filter table
|
2025-01-03 17:59:22 +01:00
|
|
|
echo "==> Adding cloudron filter chain"
|
2022-02-20 17:42:20 -08:00
|
|
|
$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
|
2017-03-29 02:18:38 -07:00
|
|
|
|
2025-01-02 23:33:59 +01:00
|
|
|
# masquerading rules for container ports to be accessible using public IP from other containers
|
2025-01-03 17:59:22 +01:00
|
|
|
echo "==> Adding cloudron postrouting chain"
|
|
|
|
|
ipxtables -t nat -N CLOUDRON_POSTROUTING || true
|
|
|
|
|
ipxtables -t nat -F CLOUDRON_POSTROUTING # empty any existing rules
|
2025-01-02 23:48:19 +01:00
|
|
|
|
2025-01-03 17:59:22 +01:00
|
|
|
$iptables -t nat -A CLOUDRON_POSTROUTING -s 172.18.0.0/16 -d 172.18.0.0/16 -j MASQUERADE
|
|
|
|
|
$ip6tables -t nat -A CLOUDRON_POSTROUTING -s fd00:c107:d509::/64 -d fd00:c107:d509::/64 -j MASQUERADE
|
|
|
|
|
|
|
|
|
|
$iptables -t nat -C POSTROUTING -j CLOUDRON_POSTROUTING 2>/dev/null || $iptables -t nat -I POSTROUTING -j CLOUDRON_POSTROUTING
|
|
|
|
|
$ip6tables -t nat -C POSTROUTING -j CLOUDRON_POSTROUTING 2>/dev/null || $ip6tables -t nat -I POSTROUTING -j CLOUDRON_POSTROUTING
|
2025-01-02 23:33:59 +01:00
|
|
|
|
2017-03-29 02:18:38 -07:00
|
|
|
# Setup rate limit chain (the recent info is at /proc/net/xt_recent)
|
2023-12-08 11:05:55 +01:00
|
|
|
echo "==> Setup rate limit chain"
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -t filter -N CLOUDRON_RATELIMIT || true
|
|
|
|
|
ipxtables -t filter -F CLOUDRON_RATELIMIT # empty any existing rules
|
2017-03-29 02:18:38 -07:00
|
|
|
|
|
|
|
|
# log dropped incoming. keep this at the end of all the rules
|
2023-12-08 11:05:55 +01:00
|
|
|
echo "==> Setup logging"
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -t filter -N CLOUDRON_RATELIMIT_LOG || true
|
|
|
|
|
ipxtables -t filter -F CLOUDRON_RATELIMIT_LOG # empty any existing rules
|
|
|
|
|
ipxtables -t filter -A CLOUDRON_RATELIMIT_LOG -m limit --limit 2/min -j LOG --log-prefix "IPTables RateLimit: " --log-level 7
|
|
|
|
|
ipxtables -t filter -A CLOUDRON_RATELIMIT_LOG -j DROP
|
2017-03-29 02:18:38 -07:00
|
|
|
|
2024-04-21 21:02:55 +02:00
|
|
|
# http https . 5000 requests per second per IP
|
2017-03-29 02:18:38 -07:00
|
|
|
for port in 80 443; do
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -A CLOUDRON_RATELIMIT -p tcp --syn --dport ${port} -m connlimit --connlimit-above 5000 -j CLOUDRON_RATELIMIT_LOG
|
2017-03-29 02:18:38 -07:00
|
|
|
done
|
|
|
|
|
|
2024-04-21 21:04:00 +02:00
|
|
|
# ssh and sftp. 5 connections per 10 seconds per IP
|
|
|
|
|
for port in 22 202 222; do
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -A CLOUDRON_RATELIMIT -p tcp --dport ${port} -m state --state NEW -m recent --set --name "public-${port}"
|
|
|
|
|
ipxtables -A CLOUDRON_RATELIMIT -p tcp --dport ${port} -m state --state NEW -m recent --update --name "public-${port}" --seconds 10 --hitcount 5 -j CLOUDRON_RATELIMIT_LOG
|
2017-03-29 02:18:38 -07:00
|
|
|
done
|
|
|
|
|
|
2021-11-23 11:49:57 +01:00
|
|
|
# ldaps
|
|
|
|
|
for port in 636 3004; do
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -A CLOUDRON_RATELIMIT -p tcp --syn --dport ${port} -m connlimit --connlimit-above 5000 -j CLOUDRON_RATELIMIT_LOG
|
2021-11-23 11:49:57 +01:00
|
|
|
done
|
|
|
|
|
|
2024-04-21 21:02:55 +02:00
|
|
|
# docker translates (dnat) 25, 587, 993, 4190 in the PREROUTING step . 50 connections per second per app
|
2017-03-29 02:18:38 -07:00
|
|
|
for port in 2525 4190 9993; do
|
2022-02-20 17:42:20 -08:00
|
|
|
$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
|
2017-03-29 02:18:38 -07:00
|
|
|
done
|
|
|
|
|
|
2024-04-21 21:02:55 +02:00
|
|
|
# msa, ldap, imap, sieve, pop3 . 500 connections per second per app
|
2021-10-07 21:53:43 -07:00
|
|
|
for port in 2525 3002 4190 9993 9995; do
|
2022-02-20 17:42:20 -08:00
|
|
|
$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
|
2017-03-29 02:18:38 -07:00
|
|
|
done
|
|
|
|
|
|
2024-04-21 21:02:55 +02:00
|
|
|
# cloudron docker network: mysql postgresql redis mongodb. 5000 connections per second per app
|
2017-03-29 16:03:08 -07:00
|
|
|
for port in 3306 5432 6379 27017; do
|
2022-02-20 17:42:20 -08:00
|
|
|
$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
|
2017-03-29 02:18:38 -07:00
|
|
|
done
|
|
|
|
|
|
2022-06-01 09:23:41 -07:00
|
|
|
# Add the rate limit chain to input chain
|
2022-02-20 17:42:20 -08:00
|
|
|
$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
|
2017-03-29 02:18:38 -07:00
|
|
|
|
2020-09-22 11:41:39 -07:00
|
|
|
# Workaround issue where Docker insists on adding itself first in FORWARD table
|
2022-02-09 22:13:12 -08:00
|
|
|
ipxtables -D FORWARD -j CLOUDRON_RATELIMIT || true
|
|
|
|
|
ipxtables -I FORWARD 1 -j CLOUDRON_RATELIMIT
|