#!/usr/bin/env bash # Open Sunshine's ports on whatever firewall is active. # Sunshine ports: # TCP: 47984, 47989, 47990, 48010 # UDP: 47998, 47999, 48000, 48010 SUNSHINE_TCP_PORTS=(47984 47989 47990 48010) SUNSHINE_UDP_PORTS=(47998 47999 48000 48010) _firewalld_active() { systemctl is-active --quiet firewalld 2>/dev/null; } # ufw is a Type=oneshot unit with RemainAfterExit=true. Its `ufw status` # command requires root to read /etc/ufw state, so an unprivileged check # returns nothing and silently misses an active firewall. Use systemd's # unit state instead — it works without sudo. _ufw_active() { command -v ufw >/dev/null 2>&1 || return 1 systemctl is-active ufw.service >/dev/null 2>&1 } _iptables_has_rules() { command -v iptables >/dev/null 2>&1 || return 1 # Heuristic: more than the default 3 chains-with-no-rules output lines means rules exist. [[ "$(as_root iptables -S 2>/dev/null | wc -l)" -gt 3 ]] } open_sunshine_ports() { if _firewalld_active; then info "firewalld is active — opening ports" local p for p in "${SUNSHINE_TCP_PORTS[@]}"; do as_root firewall-cmd --permanent --add-port="${p}/tcp" >/dev/null done for p in "${SUNSHINE_UDP_PORTS[@]}"; do as_root firewall-cmd --permanent --add-port="${p}/udp" >/dev/null done as_root firewall-cmd --reload >/dev/null ok "Opened Sunshine ports in firewalld" return 0 fi if _ufw_active; then info "ufw is active — opening ports" local p for p in "${SUNSHINE_TCP_PORTS[@]}"; do as_root ufw allow "${p}/tcp" >/dev/null done for p in "${SUNSHINE_UDP_PORTS[@]}"; do as_root ufw allow "${p}/udp" >/dev/null done ok "Opened Sunshine ports in ufw" return 0 fi if _iptables_has_rules; then warn "iptables rules detected but no managed firewall (ufw/firewalld). Open these ports manually:" warn " TCP: ${SUNSHINE_TCP_PORTS[*]}" warn " UDP: ${SUNSHINE_UDP_PORTS[*]}" return 0 fi info "No active firewall detected — nothing to configure." }