Package: miniupnpd-nftables Version: 2.2.1-1 Severity: normal Tags: patch Dear Maintainer,
I have a manually-crafted set of firewall rules, currently using iptables-nft but still heavily based on classic iptables way of doing things. On update from Debian 10 to 11, miniupnpd transitioned to the use of miniupnpd-nftables, as expected. But I was surprised to find that after the transition, my existing NAT rules unrelated to miniupnpd had started vanishing every time I stopped the miniupnpd service. On examination of the nft_removeall.sh script, it turns out it runs "nft delete table nat", which removes any NAT rules created using iptables-nft's "iptables -t nat" command. As the comment at the beginning of the script says "Do not disturb other existing structures in nftables", this must not have been the intention. I also noticed that the stub chains generated by /etc/miniupnpd/nft_init.sh seem to be completely unused by the actual daemon, and the rules the daemon creates won't match the stub chains. In fact, it looks like the daemon might be able to work just fine without the nft_init script at all. On further investigation, I found that the daemon creates three Netfilter tables, all named "miniupnpd": * an ip6 table with two NAT chains * an ip (=IPv4-only) table with two NAT chains * an inet (=IPv4/v6) table with a single filter chain The default names for the tables and the chains did match neither what the scripts used, nor the commented-out values in the miniupnpd.conf file. The defaults can be found in the source code file miniupnpd-2.2.1/netfilter_nft/nftnlrdr_misc.c, lines 66-69. The name of the tables created by the daemon is clearly intended to be configurable in the source code, but the configuration file processing code does not yet define an option to change it away from default. I cleaned up the scripts to match the assumed intent and the actual behavior of miniupnpd-nftables, and now it seems to work fine: see patch below. I created variables at the beginning of each script to match the chain name configuration options in miniupnpd.conf. I also added a variable for the table name, in the assumption that the actual configuration option might eventually be added. I made the nft commands in the scripts explicitly specify the address family in each case, to make it more obvious what the scripts will do. Since existing documentation is rather sparse, this might be the next best thing. diff -rup miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_delete_chain.sh miniupnpd-2.2.1/netfilter_nft/scripts/nft_delete_chain.sh --- miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_delete_chain.sh 2019-06-26 00:30:54.000000000 +0300 +++ miniupnpd-2.2.1/netfilter_nft/scripts/nft_delete_chain.sh 2021-09-20 01:05:14.457155573 +0300 @@ -1,5 +1,14 @@ #!/bin/sh -nft delete chain nat MINIUPNPD -nft delete chain nat MINIUPNPD-POSTROUTING -nft delete chain filter MINIUPNPD +# If you modify the corresponding settings in miniupnpd.conf, +# change these variables in the scripts too. +upnp_table=miniupnpd +upnp_forward_chain=forward +upnp_nat_chain=prerouting +upnp_nat_postrouting_chain=postrouting + +nft delete chain ip ${upnp_table} ${upnp_nat_chain} +nft delete chain ip ${upnp_table} ${upnp_nat_postrouting_chain} +nft delete chain inet ${upnp_table} ${upnp_forward_chain} +nft delete chain ip6 ${upnp_table} ${upnp_nat_chain} +nft delete chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} diff -rup miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_display.sh miniupnpd-2.2.1/netfilter_nft/scripts/nft_display.sh --- miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_display.sh 2019-06-26 00:26:46.000000000 +0300 +++ miniupnpd-2.2.1/netfilter_nft/scripts/nft_display.sh 2021-09-20 01:05:24.707083374 +0300 @@ -1,8 +1,19 @@ #!/bin/sh -# Prerouting -nft list chain ip nat MINIUPNPD -# Postrouting -nft list chain ip nat MINIUPNPD-POSTROUTING -# Filter -nft list chain inet filter MINIUPNPD +# If you modify the corresponding settings in miniupnpd.conf, +# change these variables in the scripts too. +upnp_table=miniupnpd +upnp_forward_chain=forward +upnp_nat_chain=prerouting +upnp_nat_postrouting_chain=postrouting + +# IPv6 prerouting +nft list chain ip6 ${upnp_table} ${upnp_nat_chain} +# IPv6 postrouting +nft list chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} +# IPv4 prerouting +nft list chain ip ${upnp_table} ${upnp_nat_chain} +# IPv4 postrouting +nft list chain ip ${upnp_table} ${upnp_nat_postrouting_chain} +# IPv4/v6 filter +nft list chain inet ${upnp_table} ${upnp_forward_chain} diff -rup miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_flush.sh miniupnpd-2.2.1/netfilter_nft/scripts/nft_flush.sh --- miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_flush.sh 2019-06-26 00:30:54.000000000 +0300 +++ miniupnpd-2.2.1/netfilter_nft/scripts/nft_flush.sh 2021-09-20 01:05:35.473674198 +0300 @@ -1,5 +1,14 @@ #!/bin/sh -nft flush chain ip nat MINIUPNPD -nft flush chain ip nat MINIUPNPD-POSTROUTING -nft flush chain inet filter MINIUPNPD +# If you modify the corresponding settings in miniupnpd.conf, +# change these variables in the scripts too. +upnp_table=miniupnpd +upnp_forward_chain=forward +upnp_nat_chain=prerouting +upnp_nat_postrouting_chain=postrouting + +nft flush chain ip ${upnp_table} ${upnp_nat_chain} +nft flush chain ip ${upnp_table} ${upnp_nat_postrouting_chain} +nft flush chain inet ${upnp_table} ${upnp_forward_chain} +nft flush chain ip6 ${upnp_table} ${upnp_nat_chain} +nft flush chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} diff -rup miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_init.sh miniupnpd-2.2.1/netfilter_nft/scripts/nft_init.sh --- miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_init.sh 2019-09-02 02:02:26.000000000 +0300 +++ miniupnpd-2.2.1/netfilter_nft/scripts/nft_init.sh 2021-09-20 01:05:46.250264959 +0300 @@ -7,17 +7,38 @@ #opts="--echo" -echo "create nat table" -nft ${opts} add table nat - -echo "create chain in nat table" -nft ${opts} add chain nat MINIUPNPD - -echo "create pcp peer chain in nat table" -nft ${opts} add chain nat MINIUPNPD-POSTROUTING - -echo "create filter table" -nft ${opts} add table inet filter - -echo "create chain in filter table" -nft ${opts} add chain inet filter MINIUPNPD +# If you modify the corresponding settings in miniupnpd.conf, +# change these variables in the scripts too. +upnp_table=miniupnpd +upnp_forward_chain=forward +upnp_nat_chain=prerouting +upnp_nat_postrouting_chain=postrouting + +echo "create ipv4 table" +nft ${opts} add table ip ${upnp_table} + +echo "create nat chain in ipv4 table" +nft ${opts} add chain ip ${upnp_table} ${upnp_nat_chain} \ + "{ type nat hook prerouting priority dstnat; policy accept; }" + +echo "create pcp peer nat chain in ipv4 table" +nft ${opts} add chain ip ${upnp_table} ${upnp_nat_postrouting_chain} \ + "{ type nat hook postrouting priority srcnat; policy accept; }" + +echo "create ipv4/v6 table" +nft ${opts} add table inet ${upnp_table} + +echo "create forward filter chain in ipv4/v6 table" +nft ${opts} add chain inet ${upnp_table} ${upnp_forward_chain} \ + "{ type filter hook forward priority -25; policy accept; }" + +echo "create ipv6 table" +nft ${opts} add table ip6 ${upnp_table} + +echo "create nat chain in ipv6 table" +nft ${opts} add chain ip6 ${upnp_table} ${upnp_nat_chain} \ + "{ type nat hook prerouting priority dstnat; policy accept; }" + +echo "create ipv6 srcnat chain" +nft ${opts} add chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} \ + "{ type nat hook postrouting priority srcnat; policy accept; }" diff -rup miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_removeall.sh miniupnpd-2.2.1/netfilter_nft/scripts/nft_removeall.sh --- miniupnpd-2.2.1/netfilter_nft/scripts.orig/nft_removeall.sh 2019-09-02 02:02:26.000000000 +0300 +++ miniupnpd-2.2.1/netfilter_nft/scripts/nft_removeall.sh 2021-09-20 01:05:58.290180162 +0300 @@ -5,40 +5,69 @@ # Do not disturb other existing structures in nftables, e.g. those created by firewalld # -nft --check list table nat > /dev/null 2>&1 +# If you modify the corresponding settings in miniupnpd.conf, +# change these variables in the scripts too. +upnp_table=miniupnpd +upnp_forward_chain=forward +upnp_nat_chain=prerouting +upnp_nat_postrouting_chain=postrouting + +nft --check list table ip ${upnp_table} > /dev/null 2>&1 if [ $? -eq "0" ]; then { - # nat table exists, so first remove the chains we added - nft --check list chain nat MINIUPNPD > /dev/null 2>&1 + # ipv4 table exists, so first remove the nat chains we added + nft --check list chain ip ${upnp_table} ${upnp_nat_chain} > /dev/null 2>&1 if [ $? -eq "0" ]; then - echo "Remove chain from nat table" - nft delete chain nat MINIUPNPD + echo "Remove prerouting nat chain from ipv4 table" + nft delete chain ip ${upnp_table} ${upnp_nat_chain} fi - nft --check list chain nat MINIUPNPD-POSTROUTING > /dev/null 2>&1 + nft --check list chain ip ${upnp_table} ${upnp_nat_postrouting_chain} > /dev/null 2>&1 if [ $? -eq "0" ]; then - echo "Remove pcp peer chain from nat table" - nft delete chain nat MINIUPNPD-POSTROUTING + echo "Remove pcp peer nat chain from ipv4 table" + nft delete chain ip ${upnp_table} ${upnp_nat_postrouting_chain} fi # then remove the table itself - echo "Remove nat table" - nft delete table nat + echo "Remove ipv4 table" + nft delete table ip ${upnp_table} } fi -nft --check list table inet filter > /dev/null 2>&1 +nft --check list table inet ${upnp_table} > /dev/null 2>&1 if [ $? -eq "0" ]; then { - # filter table exists, so first remove the chain we added - nft --check list chain inet filter MINIUPNPD > /dev/null 2>&1 + # ipv4/v6 table exists, so first remove the filter chain we added + nft --check list chain inet ${upnp_table} ${upnp_forward_chain} > /dev/null 2>&1 if [ $? -eq "0" ]; then - echo "Remove chain from filter table" - nft delete chain inet filter MINIUPNPD + echo "Remove filter chain from ipv4/v6 table" + nft delete chain inet ${upnp_table} ${upnp_forward_chain} fi # then remove the table itself - echo "Remove filter table" - nft delete table inet filter + echo "Remove ipv4/v6 table" + nft delete table inet ${upnp_table} +} +fi + +nft --check list table ip6 ${upnp_table} > /dev/null 2>&1 +if [ $? -eq "0" ]; then +{ + # ipv6 table exists, so first remove the nat chains we added + nft --check list chain ip6 ${upnp_table} ${upnp_nat_chain} > /dev/null 2>&1 + if [ $? -eq "0" ]; then + echo "Remove prerouting nat chain from ipv6 table" + nft delete chain ip6 ${upnp_table} ${upnp_nat_chain} + fi + + nft --check list chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} > /dev/null 2>&1 + if [ $? -eq "0" ]; then + echo "Remove pcp peer nat chain from ipv6 table" + nft delete chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} + fi + + # then remove the table itself + echo "Remove ipv6 table" + nft delete table ip6 ${upnp_table} } fi *** Reporter, please consider answering these questions, where appropriate *** * What led up to the situation? * What exactly did you do (or not do) that was effective (or ineffective)? * What was the outcome of this action? * What outcome did you expect instead? *** End of the template - remove these template lines *** -- System Information: Debian Release: 11.0 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 5.10.63-i3 (SMP w/2 CPU threads) Kernel taint flags: TAINT_OOT_MODULE Locale: LANG=en_US.UTF-8, LC_CTYPE=fi_FI.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages miniupnpd-nftables depends on: ii libc6 2.31-13 ii libmnl0 1.0.4-3 ii libnftnl11 1.1.9-1 miniupnpd-nftables recommends no packages. miniupnpd-nftables suggests no packages. -- Configuration Files: /etc/miniupnpd/nft_delete_chain.sh changed: upnp_table=miniupnpd upnp_forward_chain=MINIUPNPD upnp_nat_chain=MINIUPNPD upnp_nat_postrouting_chain=MINIUPNPD-POSTROUTING nft delete chain ip ${upnp_table} ${upnp_nat_chain} nft delete chain ip ${upnp_table} ${upnp_nat_postrouting_chain} nft delete chain inet ${upnp_table} ${upnp_forward_chain} nft delete chain ip6 ${upnp_table} ${upnp_nat_chain} nft delete chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} /etc/miniupnpd/nft_flush.sh changed: upnp_table=miniupnpd upnp_forward_chain=MINIUPNPD upnp_nat_chain=MINIUPNPD upnp_nat_postrouting_chain=MINIUPNPD-POSTROUTING nft flush chain ip ${upnp_table} ${upnp_nat_chain} nft flush chain ip ${upnp_table} ${upnp_nat_postrouting_chain} nft flush chain inet ${upnp_table} ${upnp_forward_chain} nft flush chain ip6 ${upnp_table} ${upnp_nat_chain} nft flush chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} /etc/miniupnpd/nft_init.sh changed: upnp_table=miniupnpd upnp_forward_chain=MINIUPNPD upnp_nat_chain=MINIUPNPD upnp_nat_postrouting_chain=MINIUPNPD-POSTROUTING echo "create IPv4 nat table" nft ${opts} add table ip ${upnp_table} echo "create chain in nat table" nft ${opts} add chain ip ${upnp_table} ${upnp_nat_chain} \ "{ type nat hook prerouting priority dstnat; policy accept; }" echo "create pcp peer chain in nat table" nft ${opts} add chain ip ${upnp_table} ${upnp_nat_postrouting_chain} \ "{ type nat hook postrouting priority srcnat; policy accept; }" echo "create IPv4/IPv6 filter table" nft ${opts} add table inet ${upnp_table} echo "create chain in filter table" nft ${opts} add chain inet ${upnp_table} ${upnp_forward_chain} \ "{ type filter hook forward priority -25; policy accept; }" echo "create ip6 table" nft ${opts} add table ip6 ${upnp_table} echo "create IPv6 dstnat chain" nft ${opts} add chain ip6 ${upnp_table} ${upnp_nat_chain} \ "{ type nat hook prerouting priority dstnat; policy accept; }" echo "create IPv6 srcnat chain" nft ${opts} add chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} \ "{ type nat hook postrouting priority srcnat; policy accept; }" /etc/miniupnpd/nft_removeall.sh changed: upnp_table=miniupnpd upnp_forward_chain=MINIUPNPD upnp_nat_chain=MINIUPNPD upnp_nat_postrouting_chain=MINIUPNPD-POSTROUTING nft --check list table ip ${upnp_table} > /dev/null 2>&1 if [ $? -eq "0" ]; then { # nat table exists, so first remove the chains we added nft --check list chain ip ${upnp_table} ${upnp_nat_chain} > /dev/null 2>&1 if [ $? -eq "0" ]; then echo "Remove chain from nat table" nft delete chain ip ${upnp_table} ${upnp_nat_chain} fi nft --check list chain ip ${upnp_table} ${upnp_nat_postrouting_chain} > /dev/null 2>&1 if [ $? -eq "0" ]; then echo "Remove pcp peer chain from nat table" nft delete chain ip ${upnp_table} ${upnp_nat_postrouting_chain} fi # then remove the table itself echo "Remove nat table" nft delete table ip ${upnp_table} } fi nft --check list table inet ${upnp_table} > /dev/null 2>&1 if [ $? -eq "0" ]; then { # filter table exists, so first remove the chain we added nft --check list chain inet ${upnp_table} ${upnp_forward_chain} > /dev/null 2>&1 if [ $? -eq "0" ]; then echo "Remove chain from filter table" nft delete chain inet ${upnp_table} ${upnp_forward_chain} fi # then remove the table itself echo "Remove filter table" nft delete table inet ${upnp_table} } fi nft --check list table ip6 ${upnp_table} > /dev/null 2>&1 if [ $? -eq "0" ]; then { # IPv6 NAT table exists, so first remove the chains we added nft --check list chain ip6 ${upnp_table} ${upnp_nat_chain} > /dev/null 2>&1 if [ $? -eq "0" ]; then echo "Remove chain from IPv6 nat table" nft delete chain ip6 ${upnp_table} ${upnp_nat_chain} fi nft --check list chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} > /dev/null 2>&1 if [ $? -eq "0" ]; then echo "Remove IPv6 pcp peer chain from nat table" nft delete chain ip6 ${upnp_table} ${upnp_nat_postrouting_chain} fi # then remove the table itself echo "Remove IPv6 nat table" nft delete table ip6 ${upnp_table} } fi -- no debconf information