From 551962389c201a32aa44d5af8b9a47ac66253d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=8C?= Date: Wed, 18 Mar 2026 20:59:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=98=B2=E7=81=AB=E5=A2=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup-relay.sh | 188 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 1 deletion(-) diff --git a/setup-relay.sh b/setup-relay.sh index c344520..2ac2ffc 100644 --- a/setup-relay.sh +++ b/setup-relay.sh @@ -545,4 +545,190 @@ for i in "${!RELAY_DOMAINS[@]}"; do fi echo "" done -success "Setup complete! ๐ŸŽ‰" \ No newline at end of file +success "Setup complete! ๐ŸŽ‰" + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# STEP 6 โ€“ Firewall (optional) +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +header "Step 6 ยท Firewall Configuration (optional)" + +$DRY_RUN && { warn "DRY-RUN: skipping firewall step."; exit 0; } + +if ! ask_yn "Configure firewall rules now?" "y"; then + info "Skipped. Remember to open the ports listed above manually." + exit 0 +fi + +# โ”€โ”€ Detect firewall โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +detect_firewall() { + if systemctl is-active --quiet firewalld 2>/dev/null; then + echo "firewalld" + elif systemctl is-active --quiet ufw 2>/dev/null || command -v ufw &>/dev/null && ufw status 2>/dev/null | grep -q "Status: active"; then + echo "ufw" + elif command -v nft &>/dev/null && nft list ruleset 2>/dev/null | grep -q "table"; then + echo "nftables" + elif command -v iptables &>/dev/null; then + echo "iptables" + else + echo "none" + fi +} + +FW="$(detect_firewall)" + +case "$FW" in + firewalld) info "Detected: firewalld" ;; + ufw) info "Detected: ufw" ;; + nftables) info "Detected: nftables" ;; + iptables) info "Detected: iptables" ;; + none) warn "No supported firewall detected (firewalld / ufw / nftables / iptables)." + info "Open the ports listed in Step 5 manually." + exit 0 ;; +esac + +# โ”€โ”€ Collect all ports to open across all relays โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +declare -a FW_TCP=() +declare -a FW_UDP=() + +for i in "${!RELAY_DOMAINS[@]}"; do + LP="${RELAY_LISTEN_PORTS[$i]}" + TM="${RELAY_TLS_MODES[$i]}" + ES="${RELAY_ENABLE_STUN[$i]}" + SP="${RELAY_STUN_PORTS_LIST[$i]}" + + # TCP: relay port + FW_TCP+=("$LP") + # TCP: port 80 for Let's Encrypt + [[ "$TM" == "1" ]] && FW_TCP+=("80") + # UDP: STUN ports + if [[ "$ES" == "true" ]] && [[ -n "$SP" ]]; then + IFS=',' read -ra _SP <<< "$SP" + for _P in "${_SP[@]}"; do + FW_UDP+=("${_P// /}") + done + fi +done + +# Deduplicate +mapfile -t FW_TCP < <(printf '%s\n' "${FW_TCP[@]}" | sort -un) +mapfile -t FW_UDP < <(printf '%s\n' "${FW_UDP[@]}" | sort -un) + +echo "" +echo -e "${BOLD}Ports to open:${RESET}" +for p in "${FW_TCP[@]}"; do echo " ${p}/tcp"; done +for p in "${FW_UDP[@]}"; do echo " ${p}/udp"; done +echo "" + +if ! ask_yn "Apply these rules?" "y"; then + info "Skipped." + exit 0 +fi + +# โ”€โ”€ Apply rules โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +apply_firewall_rules() { + local fw="$1" + + case "$fw" in + + firewalld) + for p in "${FW_TCP[@]}"; do + firewall-cmd --permanent --add-port="${p}/tcp" && \ + success " firewalld: opened ${p}/tcp" || \ + error " firewalld: failed to open ${p}/tcp" + done + for p in "${FW_UDP[@]}"; do + firewall-cmd --permanent --add-port="${p}/udp" && \ + success " firewalld: opened ${p}/udp" || \ + error " firewalld: failed to open ${p}/udp" + done + firewall-cmd --reload && success " firewalld: reloaded" || error " firewalld: reload failed" + ;; + + ufw) + for p in "${FW_TCP[@]}"; do + ufw allow "${p}/tcp" && \ + success " ufw: allowed ${p}/tcp" || \ + error " ufw: failed to allow ${p}/tcp" + done + for p in "${FW_UDP[@]}"; do + ufw allow "${p}/udp" && \ + success " ufw: allowed ${p}/udp" || \ + error " ufw: failed to allow ${p}/udp" + done + ;; + + nftables) + # Add rules to the first inet/ip filter input chain found, or create one + _NFT_TABLE="filter" + _NFT_CHAIN="input" + # Check if table/chain exist + if ! nft list chain inet "${_NFT_TABLE}" "${_NFT_CHAIN}" &>/dev/null; then + nft add table inet "${_NFT_TABLE}" + nft add chain inet "${_NFT_TABLE}" "${_NFT_CHAIN}" \ + '{ type filter hook input priority 0 ; policy accept ; }' + info " nftables: created table inet ${_NFT_TABLE} chain ${_NFT_CHAIN}" + fi + for p in "${FW_TCP[@]}"; do + nft add rule inet "${_NFT_TABLE}" "${_NFT_CHAIN}" tcp dport "${p}" accept && \ + success " nftables: accepted ${p}/tcp" || \ + error " nftables: failed ${p}/tcp" + done + for p in "${FW_UDP[@]}"; do + nft add rule inet "${_NFT_TABLE}" "${_NFT_CHAIN}" udp dport "${p}" accept && \ + success " nftables: accepted ${p}/udp" || \ + error " nftables: failed ${p}/udp" + done + # Persist + if command -v nft &>/dev/null; then + if [[ -d /etc/nftables.d ]]; then + nft list ruleset > /etc/nftables.d/netbird-relay.nft && \ + success " nftables: saved to /etc/nftables.d/netbird-relay.nft" + elif [[ -f /etc/nftables.conf ]]; then + nft list ruleset > /etc/nftables.conf && \ + success " nftables: saved to /etc/nftables.conf" + else + warn " nftables: rules applied but not persisted โ€” save manually with:" + warn " nft list ruleset > /etc/nftables.conf" + fi + fi + ;; + + iptables) + for p in "${FW_TCP[@]}"; do + iptables -C INPUT -p tcp --dport "${p}" -j ACCEPT 2>/dev/null || { + iptables -A INPUT -p tcp --dport "${p}" -j ACCEPT && \ + success " iptables: opened ${p}/tcp" || \ + error " iptables: failed to open ${p}/tcp" + } + done + for p in "${FW_UDP[@]}"; do + iptables -C INPUT -p udp --dport "${p}" -j ACCEPT 2>/dev/null || { + iptables -A INPUT -p udp --dport "${p}" -j ACCEPT && \ + success " iptables: opened ${p}/udp" || \ + error " iptables: failed to open ${p}/udp" + } + done + # Persist + if command -v netfilter-persistent &>/dev/null; then + netfilter-persistent save && success " iptables: rules persisted via netfilter-persistent" + elif command -v iptables-save &>/dev/null; then + if [[ -f /etc/iptables/rules.v4 ]]; then + iptables-save > /etc/iptables/rules.v4 && \ + success " iptables: saved to /etc/iptables/rules.v4" + else + warn " iptables: rules applied but not persisted โ€” save manually with:" + warn " iptables-save > /etc/iptables/rules.v4" + fi + fi + ;; + esac +} + +if [[ "$EUID" -ne 0 ]]; then + warn "Not running as root โ€” firewall commands may fail." + warn "Re-run with sudo if needed." +fi + +apply_firewall_rules "$FW" +echo "" +success "Firewall rules applied. ๐ŸŽ‰" \ No newline at end of file