public inbox for development@lists.ipfire.org
 help / color / mirror / Atom feed
From: Michael Tremer <michael.tremer@ipfire.org>
To: "Peter Müller" <peter.mueller@ipfire.org>
Cc: "IPFire: Development" <development@lists.ipfire.org>
Subject: Re: [PATCH] initscripts: Always wait for xtables lock when running iptables commands
Date: Tue, 30 Sep 2025 09:55:27 +0100	[thread overview]
Message-ID: <CA31E795-D2AE-4D8F-B598-83E69BADAA78@ipfire.org> (raw)
In-Reply-To: <2dbd27d0-92f5-4611-b7c8-a98185601f0e@ipfire.org>

Hello Peter,

Nice to read you on this list again :)

I cannot say that I have ever noticed that we had any races here. I have merged the patch into next and it will be released with Core Update 199.

Best,
-Michael

> On 28 Sep 2025, at 20:51, Peter Müller <peter.mueller@ipfire.org> wrote:
> 
> If not explicitly instructed to do so, iptables by default aborts with
> an error message such as
> 
>> Can't lock /run/xtables.lock: Resource temporarily unavailable
>> Another app is currently holding the xtables lock. Perhaps you want to use the -w option?
> 
> if the Xtables lock is still set, i.e., another iptables operation is
> currently in progress. This causes iptables commands not to be executed
> at all if there are delays during the boot procedure, e.g. due to slow
> PPPoE dial-up procedure or similar.
> 
> To ensure deterministic behavior, this match modifies initscripts to
> always execute iptables to wait for the Xtables lock to be removed, to
> make sure iptables rules are installed properly (the "firewall"
> initscript is doing so already).
> 
> Fixes: #13896 - OpenVPN RW port not opened in firewall after reboot
> Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
> Tested-by: Peter Müller <peter.mueller@ipfire.org>
> ---
> src/initscripts/networking/red     |  4 ++--
> src/initscripts/packages/tor       | 10 +++++-----
> src/initscripts/system/dhcp        | 16 ++++++++--------
> src/initscripts/system/openvpn-n2n | 10 +++++-----
> src/initscripts/system/openvpn-rw  |  6 +++---
> src/initscripts/system/wireguard   | 20 ++++++++++----------
> 6 files changed, 33 insertions(+), 33 deletions(-)
> 
> diff --git a/src/initscripts/networking/red b/src/initscripts/networking/red
> index 6d779b365..536fc972c 100644
> --- a/src/initscripts/networking/red
> +++ b/src/initscripts/networking/red
> @@ -162,8 +162,8 @@ case "${1}" in
> 
> elif [ "${TYPE}" == "DHCP" ]; then
> # Add firewall rules to allow comunication with the dhcp server on red.
> - iptables -A REDINPUT -p tcp --source-port 67 --destination-port 68 -i ${DEVICE} -j ACCEPT
> - iptables -A REDINPUT -p udp --source-port 67 --destination-port 68 -i ${DEVICE} -j ACCEPT
> + iptables --wait -A REDINPUT -p tcp --source-port 67 --destination-port 68 -i ${DEVICE} -j ACCEPT
> + iptables --wait -A REDINPUT -p udp --source-port 67 --destination-port 68 -i ${DEVICE} -j ACCEPT
> 
> echo -n "${DEVICE}" > /var/ipfire/red/iface
> 
> diff --git a/src/initscripts/packages/tor b/src/initscripts/packages/tor
> index 47797265c..eef9682f3 100644
> --- a/src/initscripts/packages/tor
> +++ b/src/initscripts/packages/tor
> @@ -37,19 +37,19 @@ function setup_firewall() {
> # Allow incoming traffic to Tor relay (and directory) port and
> # all outgoing TCP connections from Tor user.
> if [ "${TOR_RELAY_ENABLED}" = "on" -a -n "${TOR_RELAY_PORT}" ]; then
> - iptables -A TOR_INPUT -p tcp --dport "${TOR_RELAY_PORT}" -j ACCEPT
> - iptables -A TOR_OUTPUT -p tcp -m owner --uid-owner tor -j ACCEPT
> + iptables --wait -A TOR_INPUT -p tcp --dport "${TOR_RELAY_PORT}" -j ACCEPT
> + iptables --wait -A TOR_OUTPUT -p tcp -m owner --uid-owner tor -j ACCEPT
> fi
> 
> if [ "${TOR_RELAY_ENABLED}" = "on" -a -n "${TOR_RELAY_DIRPORT}" ] && [ "${TOR_RELAY_DIRPORT}" -ne 0 ]; then
> - iptables -A TOR_INPUT -p tcp --dport "${TOR_RELAY_DIRPORT}" -j ACCEPT
> + iptables --wait -A TOR_INPUT -p tcp --dport "${TOR_RELAY_DIRPORT}" -j ACCEPT
> fi
> }
> 
> function flush_firewall() {
> # Flush all rules.
> - iptables -F TOR_INPUT
> - iptables -F TOR_OUTPUT
> + iptables --wait -F TOR_INPUT
> + iptables --wait -F TOR_OUTPUT
> }
> 
> case "${1}" in
> diff --git a/src/initscripts/system/dhcp b/src/initscripts/system/dhcp
> index 61b951658..826cd2dfe 100644
> --- a/src/initscripts/system/dhcp
> +++ b/src/initscripts/system/dhcp
> @@ -28,10 +28,10 @@ eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
> eval $(/usr/local/bin/readhash /var/ipfire/dhcp/settings)
> 
> function flush_chains() {
> - iptables -F DHCPGREENINPUT
> - iptables -F DHCPGREENOUTPUT
> - iptables -F DHCPBLUEINPUT
> - iptables -F DHCPBLUEOUTPUT
> + iptables --wait -F DHCPGREENINPUT
> + iptables --wait -F DHCPGREENOUTPUT
> + iptables --wait -F DHCPBLUEINPUT
> + iptables --wait -F DHCPBLUEOUTPUT
> }
> 
> case "$1" in
> @@ -41,14 +41,14 @@ case "$1" in
> if [ -n "${GREEN_DEV}" -a -e "/var/ipfire/dhcp/enable_green" ]; then
> LISTEN_INTERFACES+=" ${GREEN_DEV}"
> 
> - iptables -A DHCPGREENINPUT  -i "${GREEN_DEV}" -j DHCPINPUT
> - iptables -A DHCPGREENOUTPUT -o "${GREEN_DEV}" -j DHCPOUTPUT
> + iptables --wait -A DHCPGREENINPUT  -i "${GREEN_DEV}" -j DHCPINPUT
> + iptables --wait -A DHCPGREENOUTPUT -o "${GREEN_DEV}" -j DHCPOUTPUT
> fi
> if [ -n "${BLUE_DEV}" -a -e "/var/ipfire/dhcp/enable_blue" ]; then
> LISTEN_INTERFACES+=" ${BLUE_DEV}"
> 
> - iptables -A DHCPBLUEINPUT  -i "${BLUE_DEV}" -j DHCPINPUT
> - iptables -A DHCPBLUEOUTPUT -o "${BLUE_DEV}" -j DHCPOUTPUT
> + iptables --wait -A DHCPBLUEINPUT  -i "${BLUE_DEV}" -j DHCPINPUT
> + iptables --wait -A DHCPBLUEOUTPUT -o "${BLUE_DEV}" -j DHCPOUTPUT
> fi
> 
> boot_mesg "Starting DHCP Server..."
> diff --git a/src/initscripts/system/openvpn-n2n b/src/initscripts/system/openvpn-n2n
> index 985398379..f6d554eaf 100644
> --- a/src/initscripts/system/openvpn-n2n
> +++ b/src/initscripts/system/openvpn-n2n
> @@ -63,10 +63,10 @@ update_firewall_rules() {
> local local_address
> 
> # Flush the block chain
> - iptables -F OVPNBLOCK
> + iptables --wait -F OVPNBLOCK
> 
> # Flush the NAT chain
> - iptables -t nat -F OVPNNAT
> + iptables --wait -t nat -F OVPNNAT
> 
> local IFS=','
> 
> @@ -85,10 +85,10 @@ update_firewall_rules() {
> fi
> 
> # Open port
> - iptables -A OVPNINPUTN2N -p "${proto}" --dport "${port}" -j ACCEPT
> + iptables --wait -A OVPNINPUTN2N -p "${proto}" --dport "${port}" -j ACCEPT
> 
> # Block all communication from transfer networks
> - iptables -A OVPNBLOCK -s "${transfer_subnet}" -j DROP
> + iptables --wait -A OVPNBLOCK -s "${transfer_subnet}" -j DROP
> 
> # Calculate NAT addresses
> transfer_address="$(calculate_transfer_address "${transfer_subnet}" "${role}")"
> @@ -96,7 +96,7 @@ update_firewall_rules() {
> 
> # NAT all outgoing connections away from the transfer net
> if [ -n "${transfer_address}" -a -n "${local_address}" ]; then
> - iptables -t nat -A OVPNNAT -s "${transfer_address}" \
> + iptables --wait -t nat -A OVPNNAT -s "${transfer_address}" \
> -j SNAT --to-source "${local_address}"
> fi
> done < /var/ipfire/ovpn/ovpnconfig
> diff --git a/src/initscripts/system/openvpn-rw b/src/initscripts/system/openvpn-rw
> index 6359d0d08..d506c8ebd 100644
> --- a/src/initscripts/system/openvpn-rw
> +++ b/src/initscripts/system/openvpn-rw
> @@ -38,10 +38,10 @@ case "${1}" in
> modprobe tun &>/dev/null
> 
> # Flush all firewall rules
> - iptables -F OVPNINPUTRW
> + iptables --wait -F OVPNINPUTRW
> 
> # Open the port
> - iptables -A OVPNINPUTRW \
> + iptables --wait -A OVPNINPUTRW \
> -p "${DPROTOCOL}" --dport "${DDEST_PORT}" -j ACCEPT
> 
> boot_mesg "Starting OpenVPN Roadwarrior Server..."
> @@ -60,7 +60,7 @@ case "${1}" in
> killproc /usr/sbin/openvpn
> 
> # Flush all firewall rules
> - iptables -F OVPNINPUTRW
> + iptables --wait -F OVPNINPUTRW
> ;;
> 
> restart)
> diff --git a/src/initscripts/system/wireguard b/src/initscripts/system/wireguard
> index caaa69cb9..ead1cdce8 100644
> --- a/src/initscripts/system/wireguard
> +++ b/src/initscripts/system/wireguard
> @@ -216,7 +216,7 @@ generate_config() {
> ip addr add "${local_address}" dev "${intf}"
> 
> # Apply MASQUERADE
> - iptables -t nat -A WGNAT -o "${intf}" -j MASQUERADE
> + iptables --wait -t nat -A WGNAT -o "${intf}" -j MASQUERADE
> fi
> 
> echo "[Interface]"
> @@ -230,7 +230,7 @@ generate_config() {
> echo "ListenPort = ${port}"
> 
> # Open the port
> - iptables -A WGINPUT -p udp --dport "${port}" -j ACCEPT
> + iptables --wait -A WGINPUT -p udp --dport "${port}" -j ACCEPT
> fi
> 
> echo "[Peer]"
> @@ -285,7 +285,7 @@ generate_config() {
> # Set blocking rules
> for local_subnet in ${local_subnets//|/ }; do
> for remote_subnet in ${remote_subnets//|/ }; do
> - iptables -I WGBLOCK \
> + iptables --wait -I WGBLOCK \
> -s "${remote_subnet}" -d "${local_subnet}" -j RETURN
> done
> done
> @@ -297,23 +297,23 @@ generate_config() {
> 
> reload_firewall() {
> # Flush all previous rules
> - iptables -F WGINPUT
> - iptables -t nat -F WGNAT
> + iptables --wait -F WGINPUT
> + iptables --wait -t nat -F WGNAT
> 
> if [ "${ENABLED}" = "on" ]; then
> - iptables -A WGINPUT -p udp --dport "${PORT}" -j ACCEPT
> + iptables --wait -A WGINPUT -p udp --dport "${PORT}" -j ACCEPT
> fi
> 
> - iptables -F WGBLOCK
> + iptables --wait -F WGBLOCK
> 
> # Don't block any traffic from Roadwarrior peers
> if [ -n "${CLIENT_POOL}" ]; then
> - iptables -A WGBLOCK -s "${CLIENT_POOL}" -i wg0 -j RETURN
> - iptables -A WGBLOCK -d "${CLIENT_POOL}" -o wg0 -j RETURN
> + iptables --wait -A WGBLOCK -s "${CLIENT_POOL}" -i wg0 -j RETURN
> + iptables --wait -A WGBLOCK -d "${CLIENT_POOL}" -o wg0 -j RETURN
> fi
> 
> # Block all other traffic
> - iptables -A WGBLOCK -j REJECT --reject-with icmp-admin-prohibited
> + iptables --wait -A WGBLOCK -j REJECT --reject-with icmp-admin-prohibited
> 
> # Flush any custom routes
> ip route flush table wg 2>/dev/null
> -- 
> 2.51.0
> 



      reply	other threads:[~2025-09-30  8:55 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-28 19:51 Peter Müller
2025-09-30  8:55 ` Michael Tremer [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CA31E795-D2AE-4D8F-B598-83E69BADAA78@ipfire.org \
    --to=michael.tremer@ipfire.org \
    --cc=development@lists.ipfire.org \
    --cc=peter.mueller@ipfire.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox