Import miniupnpd from routing repo and bump to 20180422. Drop 102-ipv6-ext-port.patch as this looks upstreamed in the pinhole code to me. Consolidate all other patches & update with a view to sending upstream. Add support for runtime IGDv1 mode switch (default to IGDv2) (not extensively) Tested-on: ar71xx Archer C7 v2 in IGDv1 compatibility mode. A variety of devices/applications appear to be able to create mappings. Have an attempt at resolving https://github.com/openwrt-routing/packages/issues/286 TL;DR miniupnpd rules get processed before fw3 rules and thus can override existing/intended redirects. Ideally the miniupnpd rules would be last in the relevant chains, unfortunately fw3 can sometimes use the last rule as a REJECT. Put miniupnpd rules as penultimate. Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>lilik-openwrt-22.03
@ -0,0 +1,66 @@ | |||
# | |||
# Copyright (C) 2006-2014 OpenWrt.org | |||
# | |||
# This is free software, licensed under the GNU General Public License v2. | |||
# See /LICENSE for more information. | |||
# | |||
include $(TOPDIR)/rules.mk | |||
PKG_NAME:=miniupnpd | |||
PKG_VERSION:=2.0.20180422 | |||
PKG_RELEASE:=1 | |||
PKG_SOURCE_URL:=http://miniupnp.free.fr/files | |||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz | |||
PKG_HASH:=fe73dd48cbd2eeb30b1ae4f2b6ff46922f214019a50b9a8dd447849b42c9e90d | |||
PKG_MAINTAINER:=Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk> | |||
PKG_LICENSE:=BSD-3-Clause | |||
include $(INCLUDE_DIR)/package.mk | |||
include $(INCLUDE_DIR)/version.mk | |||
define Package/miniupnpd | |||
SECTION:=net | |||
CATEGORY:=Network | |||
DEPENDS:=+iptables +libip4tc +IPV6:libip6tc +IPV6:ip6tables +libuuid | |||
TITLE:=Lightweight UPnP IGD, NAT-PMP & PCP daemon | |||
SUBMENU:=Firewall | |||
URL:=http://miniupnp.free.fr/ | |||
endef | |||
define Package/miniupnpd/conffiles | |||
/etc/config/upnpd | |||
endef | |||
define Build/Prepare | |||
$(call Build/Prepare/Default) | |||
echo "$(VERSION_NUMBER)" | tr '() ' '_' >$(PKG_BUILD_DIR)/os.openwrt | |||
endef | |||
MAKE_FLAGS += \ | |||
TARGET_OPENWRT=1 TEST=0 LIBS="" \ | |||
CC="$(TARGET_CC) -DIPTABLES_143 -lip4tc -luuid \ | |||
$(if $(CONFIG_IPV6),-lip6tc)" \ | |||
CONFIG_OPTIONS="--portinuse --leasefile --igd2 \ | |||
$(if $(CONFIG_IPV6),--ipv6)" \ | |||
-f Makefile.linux miniupnpd | |||
define Package/miniupnpd/install | |||
$(INSTALL_DIR) $(1)/usr/sbin | |||
$(INSTALL_DIR) $(1)/etc/init.d | |||
$(INSTALL_DIR) $(1)/etc/config | |||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface | |||
$(INSTALL_DIR) $(1)/etc/uci-defaults | |||
$(INSTALL_DIR) $(1)/usr/share/miniupnpd | |||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/miniupnpd $(1)/usr/sbin/miniupnpd | |||
$(INSTALL_BIN) ./files/miniupnpd.init $(1)/etc/init.d/miniupnpd | |||
$(INSTALL_CONF) ./files/upnpd.config $(1)/etc/config/upnpd | |||
$(INSTALL_DATA) ./files/miniupnpd.hotplug $(1)/etc/hotplug.d/iface/50-miniupnpd | |||
$(INSTALL_BIN) ./files/miniupnpd.defaults $(1)/etc/uci-defaults/99-miniupnpd | |||
$(INSTALL_DATA) ./files/firewall.include $(1)/usr/share/miniupnpd/firewall.include | |||
endef | |||
$(eval $(call BuildPackage,miniupnpd)) |
@ -0,0 +1,69 @@ | |||
#!/bin/sh | |||
# miniupnpd integration for firewall3 | |||
IPTABLES=/usr/sbin/iptables | |||
IP6TABLES=/usr/sbin/ip6tables | |||
$IPTABLES -t filter -N MINIUPNPD 2>/dev/null | |||
$IPTABLES -t nat -N MINIUPNPD 2>/dev/null | |||
$IPTABLES -t nat -N MINIUPNPD-POSTROUTING 2>/dev/null | |||
[ -x $IP6TABLES ] && $IP6TABLES -t filter -N MINIUPNPD 2>/dev/null | |||
. /lib/functions/network.sh | |||
# helper to insert in chain as penultimate | |||
iptables_prepend_rule() { | |||
local iptables="$1" | |||
local table="$2" | |||
local chain="$3" | |||
local target="$4" | |||
$iptables -t "$table" -I "$chain" $($iptables -t "$table" --line-numbers -nL "$chain" | \ | |||
sed -ne '$s/[^0-9].*//p') -j "$target" | |||
} | |||
ADDED=0 | |||
add_extzone_rules() { | |||
local ext_zone="$1" | |||
[ -z "$ext_zone" ] && return | |||
# IPv4 - due to NAT, need to add both to nat and filter table | |||
# need to insert as penultimate rule for forward & postrouting since final rule might be a fw3 REJECT | |||
iptables_prepend_rule "$IPTABLES" filter "zone_${ext_zone}_forward" MINIUPNPD | |||
$IPTABLES -t nat -A "zone_${ext_zone}_prerouting" -j MINIUPNPD | |||
iptables_prepend_rule "$IPTABLES" nat "zone_${ext_zone}_postrouting" MINIUPNPD-POSTROUTING | |||
# IPv6 if available - filter only | |||
[ -x $IP6TABLES ] && { | |||
iptables_prepend_rule "$IP6TABLES" filter "zone_${ext_zone}_forward" MINIUPNPD | |||
} | |||
ADDED=$(($ADDED + 1)) | |||
} | |||
# By default, user configuration is king. | |||
for ext_iface in $(uci -q get upnpd.config.external_iface); do | |||
add_extzone_rules $(fw3 -q network "$ext_iface") | |||
done | |||
add_extzone_rules $(uci -q get upnpd.config.external_zone) | |||
[ "$ADDED" -ne 0 ] && exit 0 | |||
# If really nothing is available, resort to network_find_wan{,6} and | |||
# assume external interfaces all have same firewall zone. | |||
# (This heuristic may fail horribly, in case of e.g. multihoming, so | |||
# please set external_zone in that case!) | |||
network_find_wan wan_iface | |||
network_find_wan6 wan6_iface | |||
for ext_iface in $wan_iface $wan6_iface; do | |||
# fw3 -q network fails on sub-interfaces => map to device first | |||
network_get_device ext_device $ext_iface | |||
add_extzone_rules $(fw3 -q device "$ext_device") | |||
done |
@ -0,0 +1,13 @@ | |||
#!/bin/sh | |||
uci -q batch <<-EOT | |||
delete firewall.miniupnpd | |||
set firewall.miniupnpd=include | |||
set firewall.miniupnpd.type=script | |||
set firewall.miniupnpd.path=/usr/share/miniupnpd/firewall.include | |||
set firewall.miniupnpd.family=any | |||
set firewall.miniupnpd.reload=1 | |||
commit firewall | |||
EOT | |||
exit 0 |
@ -0,0 +1,33 @@ | |||
#!/bin/sh | |||
/etc/init.d/miniupnpd enabled || exit 0 | |||
. /lib/functions/service.sh | |||
# If miniupnpd is not running: | |||
# - check on _any_ event (even updates may contribute to network_find_wan*) | |||
# If miniupnpd _is_ running: | |||
# - check only on ifup (otherwise lease updates etc would cause | |||
# miniupnpd state loss) | |||
[ "$ACTION" != "ifup" ] && service_check /usr/sbin/miniupnpd && exit 0 | |||
tmpconf="/var/etc/miniupnpd.conf" | |||
extiface=$(uci get upnpd.config.external_iface) | |||
extzone=$(uci get upnpd.config.external_zone) | |||
. /lib/functions/network.sh | |||
if [ -z "$extiface" ] ; then | |||
# manual external zone (if dynamically find interfaces | |||
# belonging to it) overrides network_find_wan* | |||
if [ -n "$extzone" ] ; then | |||
ifname=$(fw3 -q zone $extzone | head -1) | |||
fi | |||
[ -n "$extiface" ] || network_find_wan extiface | |||
[ -n "$extiface" ] || network_find_wan6 extiface | |||
fi | |||
[ -n "$ifname" ] || network_get_device ifname "$extiface" | |||
grep -q "ext_ifname=$ifname" "$tmpconf" || /etc/init.d/miniupnpd restart |
@ -0,0 +1,210 @@ | |||
#!/bin/sh /etc/rc.common | |||
# Copyright (C) 2006-2014 OpenWrt.org | |||
START=94 | |||
STOP=15 | |||
SERVICE_USE_PID=1 | |||
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 tmpconf="$2" | |||
local action external_port_start external_port_end int_addr | |||
local internal_port_start internal_port_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" >>$tmpconf | |||
} | |||
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" >> $tmpconf | |||
else | |||
echo "$alt=yes" >> $tmpconf | |||
fi | |||
} | |||
boot() { | |||
return | |||
} | |||
start() { | |||
config_load "upnpd" | |||
local extiface intiface upload download logging secure enabled natpmp | |||
local extip port usesysuptime conffile serial_number model_number | |||
local uuid notify_interval presentation_url enable_upnp | |||
local upnp_lease_file clean_ruleset_threshold clean_ruleset_interval | |||
local ipv6_listening_ip enabled | |||
config_get_bool enabled config enabled 1 | |||
[ "$enabled" -eq 0 ] && return 1 | |||
config_get extiface config external_iface | |||
config_get extzone config external_zone | |||
config_get intiface config internal_iface | |||
config_get extip config external_ip | |||
config_get port config port 5000 | |||
config_get upload config upload | |||
config_get download config download | |||
config_get_bool logging config log_output 0 | |||
config_get conffile config config_file | |||
config_get serial_number config serial_number | |||
config_get model_number config model_number | |||
config_get uuid config uuid | |||
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_listening_ip config ipv6_listening_ip | |||
local args ifname | |||
. /lib/functions/network.sh | |||
# manual external interface overrides everything | |||
if [ -z "$extiface" ] ; then | |||
# manual external zone (if dynamically find interfaces | |||
# belonging to it) overrides network_find_wan* | |||
if [ -n "$extzone" ] ; then | |||
ifname=$(fw3 -q zone $extzone | head -1) | |||
fi | |||
[ -n "$extiface" ] || network_find_wan extiface | |||
[ -n "$extiface" ] || network_find_wan6 extiface | |||
fi | |||
[ -n "$ifname" ] || network_get_device ifname $extiface | |||
if [ -n "$conffile" ]; then | |||
args="-f $conffile" | |||
else | |||
local tmpconf="/var/etc/miniupnpd.conf" | |||
args="-f $tmpconf" | |||
mkdir -p /var/etc | |||
echo "ext_ifname=$ifname" >$tmpconf | |||
[ -n "$extip" ] && \ | |||
echo "ext_ip=$extip" >>$tmpconf | |||
local iface | |||
for iface in ${intiface:-lan}; do | |||
local device | |||
network_get_device device "$iface" && { | |||
echo "listening_ip=$device" >>$tmpconf | |||
} | |||
done | |||
[ "$port" != "auto" ] && \ | |||
echo "port=$port" >>$tmpconf | |||
config_load "upnpd" | |||
upnpd_write_bool enable_natpmp 1 | |||
upnpd_write_bool enable_upnp 1 | |||
upnpd_write_bool secure_mode 1 | |||
upnpd_write_bool pcp_allow_thirdparty 0 | |||
upnpd_write_bool system_uptime 1 | |||
upnpd_write_bool igdv1 0 force_igd_desc_v1 | |||
[ -n "$upnp_lease_file" ] && \ | |||
echo "lease_file=$upnp_lease_file" >>$tmpconf | |||
[ -n "$upload" -a -n "$download" ] && { | |||
echo "bitrate_down=$(($download * 1024 * 8))" >>$tmpconf | |||
echo "bitrate_up=$(($upload * 1024 * 8))" >>$tmpconf | |||
} | |||
[ -n "${presentation_url}" ] && \ | |||
echo "presentation_url=${presentation_url}" >>$tmpconf | |||
[ -n "${notify_interval}" ] && \ | |||
echo "notify_interval=${notify_interval}" >>$tmpconf | |||
[ -n "${clean_ruleset_threshold}" ] && \ | |||
echo "clean_ruleset_threshold=${clean_ruleset_threshold}" >>$tmpconf | |||
[ -n "${clean_ruleset_interval}" ] && \ | |||
echo "clean_ruleset_interval=${clean_ruleset_interval}" >>$tmpconf | |||
[ -n "${ipv6_listening_ip}" ] && \ | |||
echo "ipv6_listening_ip=${ipv6_listening_ip}" >>$tmpconf | |||
[ -z "$uuid" ] && { | |||
uuid="$(cat /proc/sys/kernel/random/uuid)" | |||
uci set upnpd.config.uuid=$uuid | |||
uci commit upnpd | |||
} | |||
[ "$uuid" = "nocli" ] || \ | |||
echo "uuid=$uuid" >>$tmpconf | |||
[ -n "${serial_number}" ] && \ | |||
echo "serial=${serial_number}" >>$tmpconf | |||
[ -n "${model_number}" ] && \ | |||
echo "model_number=${model_number}" >>$tmpconf | |||
config_foreach conf_rule_add perm_rule "$tmpconf" | |||
fi | |||
if [ -n "$ifname" ]; then | |||
# start firewall | |||
iptables -L MINIUPNPD >/dev/null 2>&1 || fw3 reload | |||
if [ "$logging" = "1" ]; then | |||
SERVICE_DAEMONIZE=1 \ | |||
service_start /usr/sbin/miniupnpd $args -d | |||
else | |||
SERVICE_DAEMONIZE= \ | |||
service_start /usr/sbin/miniupnpd $args | |||
fi | |||
else | |||
logger -t "upnp daemon" "external interface not found, not starting" | |||
fi | |||
} | |||
stop() { | |||
service_stop /usr/sbin/miniupnpd | |||
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 | |||
} | |||
} |
@ -0,0 +1,28 @@ | |||
config upnpd config | |||
option enabled 0 | |||
option enable_natpmp 1 | |||
option enable_upnp 1 | |||
option secure_mode 1 | |||
option log_output 0 | |||
option download 1024 | |||
option upload 512 | |||
#by default, looked up dynamically from ubus | |||
# option external_iface wan | |||
option internal_iface lan | |||
option port 5000 | |||
option upnp_lease_file /var/upnp.leases | |||
option igdv1 0 | |||
config perm_rule | |||
option action allow | |||
option ext_ports 1024-65535 | |||
option int_addr 0.0.0.0/0 # Does not override secure_mode | |||
option int_ports 1024-65535 | |||
option comment "Allow high ports" | |||
config perm_rule | |||
option action deny | |||
option ext_ports 0-65535 | |||
option int_addr 0.0.0.0/0 | |||
option int_ports 0-65535 | |||
option comment "Default deny" |
@ -0,0 +1,58 @@ | |||
--- a/genconfig.sh | |||
+++ b/genconfig.sh | |||
@@ -379,12 +379,19 @@ case $FW in | |||
esac | |||
# UUID API | |||
-if grep uuid_create /usr/include/uuid.h > /dev/null 2>&1 ; then | |||
- echo "#define BSD_UUID" >> ${CONFIGFILE} | |||
-fi | |||
-if grep uuid_generate /usr/include/uuid/uuid.h > /dev/null 2>&1 ; then | |||
- echo "#define LIB_UUID" >> ${CONFIGFILE} | |||
-fi | |||
+case $OS_NAME in | |||
+ OpenWRT) | |||
+ echo "#define LIB_UUID" >> ${CONFIGFILE} | |||
+ ;; | |||
+ *) | |||
+ if grep uuid_create /usr/include/uuid.h > /dev/null 2>&1 ; then | |||
+ echo "#define BSD_UUID" >> ${CONFIGFILE} | |||
+ fi | |||
+ if grep uuid_generate /usr/include/uuid/uuid.h > /dev/null 2>&1 ; then | |||
+ echo "#define LIB_UUID" >> ${CONFIGFILE} | |||
+ fi | |||
+ ;; | |||
+esac | |||
# set V6SOCKETS_ARE_V6ONLY to 0 if it was not set above | |||
if [ -z "$V6SOCKETS_ARE_V6ONLY" ] ; then | |||
--- a/Makefile.linux | |||
+++ b/Makefile.linux | |||
@@ -73,7 +73,10 @@ CPPFLAGS += -DIPTABLES_143 | |||
endif | |||
CFLAGS += $(shell $(PKG_CONFIG) --cflags libiptc) | |||
+#OpenWrt packager passes correct libraries | |||
+ifeq ($(TARGET_OPENWRT),) | |||
LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libiptc) | |||
+endif | |||
LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L libiptc) | |||
LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-other libiptc) | |||
else | |||
@@ -153,6 +156,8 @@ LDLIBS += $(shell $(PKG_CONFIG) --static | |||
LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libnetfilter_conntrack) | |||
endif # ($(TEST),1) | |||
+# OpenWrt packager disables https server for IGD v2 and hardcodes libuuid support | |||
+ifeq ($(TARGET_OPENWRT),) | |||
LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libssl) | |||
TEST := $(shell $(PKG_CONFIG) --exists uuid && echo 1) | |||
@@ -161,6 +166,7 @@ LDLIBS += $(shell $(PKG_CONFIG) --static | |||
else | |||
$(info please install uuid-dev package / libuuid) | |||
endif # ($(TEST),1) | |||
+endif # ($(TARGET_OPENWRT,) | |||
TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o | |||