packages/net/miniupnpd/files/miniupnpd.init
Jo-Philipp Wich f1c69d0e6c miniupnpd: rework firewall4 integration
- Bump to the latest Git version in order to increase the package version
   for simpler opkg upgrade of the broken version

 - (Re-)Introduce PKG_RELEASE into the package, omitting it may lead to
   opkg segmentation faults under certain circumstances

 - Utilize automatic include hooks to drop the isolated miniupnpd table
   in favor to chains within the main inet fw4 table, otherwise PCP is
   unreliable as the upnp table might accept traffic which is later
   rejected by fw4

 - Install a fw4 script hook to restart miniupnpd on fw4 restarts and
   reloads in order to repopulate the upnp chains with forward rules

 - Register the used miniupnpd configuration file and the firewall uci
   configuration as change sources, otherwise `/etc/init.d/miniupnpd reload`
   has no effect if the firewall or upnpd config was changed

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-06 20:28:11 +02:00

226 lines
6.6 KiB
Bash

#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2014 OpenWrt.org
START=94
STOP=15
USE_PROCD=1
PROG=/usr/sbin/miniupnpd
[ -x "$(command -v nft)" ] && FW="fw4" || FW="fw3"
upnpd_get_port_range() {
local var="$1"; shift
local val
config_get val "$@"
case "$val" in
[0-9]*[:-][0-9]*)
export -n -- "${var}_start=${val%%[:-]*}"
export -n -- "${var}_end=${val##*[:-]}"
;;
[0-9]*)
export -n -- "${var}_start=$val"
export -n -- "${var}_end="
;;
esac
}
conf_rule_add() {
local cfg="$1"
local action int_addr
local ext_start ext_end int_start int_end comment
config_get action "$cfg" action "deny" # allow or deny
upnpd_get_port_range "ext" "$cfg" ext_ports "0-65535" # external ports: x, x-y, x:y
config_get int_addr "$cfg" int_addr "0.0.0.0/0" # ip or network and subnet mask (internal)
upnpd_get_port_range "int" "$cfg" int_ports "0-65535" # internal ports: x, x-y, x:y or range
config_get comment "$cfg" comment "ACL" # comment
# Make a single IP IP/32 so that miniupnpd.conf can use it.
[ "${int_addr%/*}" = "$int_addr" ] && int_addr="$int_addr/32"
echo "$action $ext_start${ext_end:+-}$ext_end $int_addr $int_start${int_end:+-}$int_end #$comment"
}
upnpd_write_bool() {
local opt="$1"
local def="${2:-0}"
local alt="${3:-$opt}"
local val
config_get_bool val config "$opt" "$def"
if [ "$val" -eq 0 ]; then
echo "$alt=no"
else
echo "$alt=yes"
fi
}
upnpd() {
config_load "upnpd"
local external_iface external_iface6 external_zone external_ip internal_iface
local upload download log_output port config_file serial_number model_number
local use_stun stun_host stun_port uuid notify_interval presentation_url
local upnp_lease_file clean_ruleset_threshold clean_ruleset_interval
local ipv6_disable
local enabled
config_get_bool enabled config enabled 1
[ "$enabled" -eq 0 ] && return 1
config_get external_iface config external_iface
config_get external_iface6 config external_iface6
config_get external_zone config external_zone
config_get external_ip config external_ip
config_get internal_iface config internal_iface
config_get port config port 5000
config_get upload config upload
config_get download config download
config_get_bool log_output config log_output 0
config_get config_file config config_file
config_get serial_number config serial_number
config_get model_number config model_number
config_get uuid config uuid
config_get use_stun config use_stun 0
config_get stun_host config stun_host
config_get stun_port config stun_port
config_get notify_interval config notify_interval
config_get presentation_url config presentation_url
config_get upnp_lease_file config upnp_lease_file
config_get clean_ruleset_threshold config clean_ruleset_threshold
config_get clean_ruleset_interval config clean_ruleset_interval
config_get ipv6_disable config ipv6_disable 0
local conf ifname ifname6
. /lib/functions/network.sh
if [ -n "$external_iface" ] ; then
network_get_device ifname "$external_iface"
else
if [ -n "$external_zone" ] ; then
ifname=$($FW -q zone "$external_zone" 2>/dev/null | head -1)
else
network_find_wan external_iface && \
network_get_device ifname "$external_iface"
fi
fi
if [ -n "$external_iface6" ] ; then
network_get_device ifname6 "$external_iface6"
else
if [ -n "$external_zone" ] ; then
ifname6=$($FW -q zone "$external_zone" 2>/dev/null | head -1)
else
network_find_wan6 external_iface6 && \
network_get_device ifname6 "$external_iface6"
fi
fi
if [ -n "$config_file" ]; then
conf="$config_file"
else
local tmpconf="/var/etc/miniupnpd.conf"
conf="$tmpconf"
mkdir -p /var/etc
{
echo "ext_ifname=$ifname"
echo "ext_ifname6=$ifname6"
[ -n "$external_ip" ] && echo "ext_ip=$external_ip"
local iface
for iface in ${internal_iface:-lan}; do
local device
network_get_device device "$iface" && echo "listening_ip=$device"
done
config_load "upnpd"
upnpd_write_bool enable_natpmp 1
upnpd_write_bool enable_upnp 1
upnpd_write_bool secure_mode 1
upnpd_write_bool system_uptime 1
upnpd_write_bool igdv1 0 force_igd_desc_v1
upnpd_write_bool use_stun 0 ext_perform_stun
upnpd_write_bool ipv6_disable $ipv6_disable
[ "$use_stun" -eq 0 ] || {
[ -n "$stun_host" ] && echo "ext_stun_host=$stun_host"
[ -n "$stun_port" ] && echo "ext_stun_port=$stun_port"
}
[ -n "$upload" ] && [ -n "$download" ] && {
echo "bitrate_down=$((download * 1024 * 8))"
echo "bitrate_up=$((upload * 1024 * 8))"
}
[ -n "$upnp_lease_file" ] && touch "$upnp_lease_file" && echo "lease_file=$upnp_lease_file"
[ -n "$presentation_url" ] && echo "presentation_url=$presentation_url"
[ -n "$notify_interval" ] && echo "notify_interval=$notify_interval"
[ -n "$clean_ruleset_threshold" ] && echo "clean_ruleset_threshold=$clean_ruleset_threshold"
[ -n "$clean_ruleset_interval" ] && echo "clean_ruleset_interval=$clean_ruleset_interval"
[ -n "$serial_number" ] && echo "serial=$serial_number"
[ -n "$model_number" ] && echo "model_number=$model_number"
[ -n "$port" ] && echo "port=$port"
[ -z "$uuid" ] && {
uuid="$(cat /proc/sys/kernel/random/uuid)"
uci set upnpd.config.uuid="$uuid"
uci commit upnpd
}
[ "$uuid" = "nocli" ] || echo "uuid=$uuid"
config_foreach conf_rule_add perm_rule
if [ "$FW" = "fw4" ]; then
#When using nftables configure miniupnpd to use its own table and chains
echo "upnp_table_name=fw4"
echo "upnp_nat_table_name=fw4"
echo "upnp_forward_chain=upnp_forward"
echo "upnp_nat_chain=upnp_prerouting"
echo "upnp_nat_postrouting_chain=upnp_postrouting"
fi
} > "$tmpconf"
fi
if [ -n "$ifname" ]; then
# start firewall
if [ "$FW" = "fw4" ]; then
nft -s -t -n list chain inet fw4 upnp_forward >/dev/null 2>&1 || fw4 reload
else
iptables -L MINIUPNPD >/dev/null 2>&1 || fw3 reload
fi
else
logger -t "upnp daemon" "external interface not found, not starting"
fi
procd_open_instance
procd_set_param file "$conf" "/etc/config/firewall"
procd_set_param command "$PROG"
procd_append_param command -f "$conf"
[ "$log_output" = "1" ] && procd_append_param command -d
procd_close_instance
}
stop_service() {
if [ "$FW" = "fw3" ]; then
iptables -t nat -F MINIUPNPD 2>/dev/null
iptables -t nat -F MINIUPNPD-POSTROUTING 2>/dev/null
iptables -t filter -F MINIUPNPD 2>/dev/null
[ -x /usr/sbin/ip6tables ] && ip6tables -t filter -F MINIUPNPD 2>/dev/null
else
nft flush chain inet fw4 upnp_forward 2>/dev/null
nft flush chain inet fw4 upnp_prerouting 2>/dev/null
nft flush chain inet fw4 upnp_postrouting 2>/dev/null
fi
}
start_service() {
config_load "upnpd"
config_foreach upnpd "upnpd"
}
service_triggers() {
procd_add_reload_trigger "upnpd"
}