feat(haproxy,service-registry): Auto-open firewall when publishing

Automatically creates firewall rules for HAProxy when:
- Requesting a certificate (haproxyctl cert add)
- Publishing a service with a domain (service-registry)

Added firewall rules:
- HAProxy-HTTP: Allow port 80 from WAN (ACME challenges)
- HAProxy-HTTPS: Allow port 443 from WAN (HTTPS traffic)

Rules are only created if they don't exist, preventing duplicates.
Firewall reloads automatically after rule creation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-01-28 06:53:27 +01:00
parent a96899c520
commit b762bffa44
2 changed files with 141 additions and 0 deletions

View File

@ -41,6 +41,59 @@ get_process_for_port() {
netstat -tlnp 2>/dev/null | grep ":${port} " | awk '{print $7}' | cut -d'/' -f2 | head -1
}
# Helper: Ensure firewall rules for HAProxy (HTTP/HTTPS from WAN)
ensure_haproxy_firewall_rules() {
local http_port="${1:-80}"
local https_port="${2:-443}"
local changed=0
# Check and create HTTP rule
local http_exists=0
local i=0
while uci -q get firewall.@rule[$i] >/dev/null 2>&1; do
local name=$(uci -q get firewall.@rule[$i].name)
[ "$name" = "HAProxy-HTTP" ] && http_exists=1 && break
i=$((i + 1))
done
if [ "$http_exists" = "0" ]; then
uci add firewall rule >/dev/null
uci set firewall.@rule[-1].name='HAProxy-HTTP'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].dest_port="$http_port"
uci set firewall.@rule[-1].proto='tcp'
uci set firewall.@rule[-1].target='ACCEPT'
uci set firewall.@rule[-1].enabled='1'
changed=1
fi
# Check and create HTTPS rule
local https_exists=0
i=0
while uci -q get firewall.@rule[$i] >/dev/null 2>&1; do
local name=$(uci -q get firewall.@rule[$i].name)
[ "$name" = "HAProxy-HTTPS" ] && https_exists=1 && break
i=$((i + 1))
done
if [ "$https_exists" = "0" ]; then
uci add firewall rule >/dev/null
uci set firewall.@rule[-1].name='HAProxy-HTTPS'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].dest_port="$https_port"
uci set firewall.@rule[-1].proto='tcp'
uci set firewall.@rule[-1].target='ACCEPT'
uci set firewall.@rule[-1].enabled='1'
changed=1
fi
# Apply firewall changes
if [ "$changed" = "1" ]; then
uci commit firewall
/etc/init.d/firewall reload >/dev/null 2>&1 &
fi
}
# List all services aggregated from providers
method_list_services() {
local lan_ip
@ -542,6 +595,9 @@ method_publish_service() {
# Create HAProxy vhost if domain specified
if [ -n "$domain" ]; then
# Ensure firewall allows HTTP/HTTPS from WAN (for public access + ACME)
ensure_haproxy_firewall_rules
# Create backend
ubus call luci.haproxy create_backend "{\"name\":\"$section_id\",\"mode\":\"http\"}" 2>/dev/null
@ -551,6 +607,10 @@ method_publish_service() {
# Create vhost with SSL
ubus call luci.haproxy create_vhost "{\"domain\":\"$domain\",\"backend\":\"$section_id\",\"ssl\":1,\"ssl_redirect\":1,\"acme\":1,\"enabled\":1}" 2>/dev/null
# Regenerate HAProxy config to include the new vhost
ubus call luci.haproxy generate 2>/dev/null
ubus call luci.haproxy reload 2>/dev/null
uci set "$UCI_CONFIG.$section_id.haproxy_enabled=1"
uci set "$UCI_CONFIG.$section_id.haproxy_domain=$domain"
uci set "$UCI_CONFIG.$section_id.haproxy_ssl=1"

View File

@ -33,6 +33,83 @@ ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; }
uci_get() { uci -q get ${CONFIG}.$1; }
uci_set() { uci set ${CONFIG}.$1="$2" && uci commit ${CONFIG}; }
# Firewall management - auto-open ports when publishing
firewall_ensure_haproxy_rules() {
local http_port="${1:-80}"
local https_port="${2:-443}"
local changed=0
# Check if HTTP rule exists
local http_rule_exists=0
local i=0
while uci -q get firewall.@rule[$i] >/dev/null 2>&1; do
local name=$(uci -q get firewall.@rule[$i].name)
if [ "$name" = "HAProxy-HTTP" ]; then
http_rule_exists=1
break
fi
i=$((i + 1))
done
# Create HTTP rule if missing
if [ "$http_rule_exists" = "0" ]; then
log_info "Creating firewall rule for HTTP (port $http_port)..."
uci add firewall rule
uci set firewall.@rule[-1].name='HAProxy-HTTP'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].dest_port="$http_port"
uci set firewall.@rule[-1].proto='tcp'
uci set firewall.@rule[-1].target='ACCEPT'
uci set firewall.@rule[-1].enabled='1'
changed=1
fi
# Check if HTTPS rule exists
local https_rule_exists=0
i=0
while uci -q get firewall.@rule[$i] >/dev/null 2>&1; do
local name=$(uci -q get firewall.@rule[$i].name)
if [ "$name" = "HAProxy-HTTPS" ]; then
https_rule_exists=1
break
fi
i=$((i + 1))
done
# Create HTTPS rule if missing
if [ "$https_rule_exists" = "0" ]; then
log_info "Creating firewall rule for HTTPS (port $https_port)..."
uci add firewall rule
uci set firewall.@rule[-1].name='HAProxy-HTTPS'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].dest_port="$https_port"
uci set firewall.@rule[-1].proto='tcp'
uci set firewall.@rule[-1].target='ACCEPT'
uci set firewall.@rule[-1].enabled='1'
changed=1
fi
# Apply changes
if [ "$changed" = "1" ]; then
uci commit firewall
/etc/init.d/firewall reload 2>/dev/null || true
log_info "Firewall rules updated - ports $http_port and $https_port open on WAN"
fi
}
firewall_check_haproxy_rules() {
local http_ok=0 https_ok=0
local i=0
while uci -q get firewall.@rule[$i] >/dev/null 2>&1; do
local name=$(uci -q get firewall.@rule[$i].name)
local enabled=$(uci -q get firewall.@rule[$i].enabled)
[ "$name" = "HAProxy-HTTP" ] && [ "$enabled" != "0" ] && http_ok=1
[ "$name" = "HAProxy-HTTPS" ] && [ "$enabled" != "0" ] && https_ok=1
i=$((i + 1))
done
[ "$http_ok" = "1" ] && [ "$https_ok" = "1" ]
}
# Load configuration
load_config() {
http_port="$(uci_get main.http_port)" || http_port="80"
@ -789,6 +866,10 @@ cmd_cert_add() {
log_info "Ensuring HAProxy config is up to date..."
generate_config
# Ensure firewall allows HTTP/HTTPS from WAN (required for ACME)
log_info "Checking firewall rules..."
firewall_ensure_haproxy_rules "$http_port" "$https_port"
local email=$(uci_get acme.email)
local staging=$(uci_get acme.staging)
local key_type_raw=$(uci_get acme.key_type) || key_type_raw="ec-256"