Skip to content

Conversation

@brauliobo
Copy link

Add connection tracking rules to preserve established/related connections when the PBR service restarts. This prevents existing SSH sessions from being broken when routing rules are flushed and recreated.

The fix adds rules at the top of prerouting and output chains that check for established/related connection state and return early, allowing those packets to continue using their existing routing table.

Add connection tracking rules to preserve established/related connections
that already have a routing mark when the PBR service restarts. This prevents
existing SSH sessions from being broken when routing rules are flushed and
recreated, while ensuring new connections are properly routed.

The fix adds rules that check for established/related connection state AND
an existing routing mark before returning early, allowing those packets to
continue using their existing routing table without interfering with new
traffic that needs to be processed.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR attempts to prevent established SSH sessions and other connections from being broken when the PBR (Policy-Based Routing) service restarts by adding connection tracking rules that preserve established/related connections.

Key Changes:

  • Adds two nftables rules at the beginning of the prerouting and output chains to check for established/related connection state and return early if a routing mark is present
  • These rules are inserted before the PBR guard rules that prevent re-marking of already marked packets

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +818 to +820
# Preserve established/related connections that already have a routing mark to prevent breaking existing sessions (e.g., SSH)
echo "add rule inet $nftTable ${nftPrefix}_prerouting ct state established,related meta mark & $fw_mask != 0 return" >> "$nftTempFile"
echo "add rule inet $nftTable ${nftPrefix}_output ct state established,related meta mark & $fw_mask != 0 return" >> "$nftTempFile"
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic of these rules may not work as intended. They check for meta mark & $fw_mask != 0, which verifies the packet mark, but packet marks are set by nftables rules on each packet and are not persistent across connections.

When the service restarts:

  1. Existing connections remain in conntrack with established/related state
  2. However, packet marks are not saved to conntrack (no ct mark set is used in this codebase)
  3. The first packet from an established connection after restart won't have a mark yet (it's set by subsequent rules in the chain)
  4. Therefore, these rules won't match and won't preserve the connection's routing

To fix this, consider one of these approaches:

  • Save marks to conntrack using ct mark set when initially marking packets, then check ct mark & $fw_mask != 0 here
  • Or simply check for ct state established,related without requiring a mark, allowing established connections to continue with their existing routing
  • Or use meta mark set ct mark to restore marks from conntrack at the start of processing
Suggested change
# Preserve established/related connections that already have a routing mark to prevent breaking existing sessions (e.g., SSH)
echo "add rule inet $nftTable ${nftPrefix}_prerouting ct state established,related meta mark & $fw_mask != 0 return" >> "$nftTempFile"
echo "add rule inet $nftTable ${nftPrefix}_output ct state established,related meta mark & $fw_mask != 0 return" >> "$nftTempFile"
# Preserve established/related connections to prevent breaking existing sessions (e.g., SSH)
echo "add rule inet $nftTable ${nftPrefix}_prerouting ct state established,related return" >> "$nftTempFile"
echo "add rule inet $nftTable ${nftPrefix}_output ct state established,related return" >> "$nftTempFile"

Copilot uses AI. Check for mistakes.
@stangri
Copy link
Owner

stangri commented Nov 21, 2025

Thanks for your contribution @brauliobo. As the pbr isn't the only package for OpenWrt marking packets, I wonder if this has been tested for potential unexpected behaviour from fw4 when SQM or other packet-marking packages are installed?

@egc112
Copy link
Collaborator

egc112 commented Nov 22, 2025

For my understanding is the problem you are encountering that existing SSH connections are broken and you have to login again after PBR (re)starts?

The main chains already have a rule on top preserving related and established traffic, adding such a rule to the prerouting chain might have unwanted side effects but I am not an expert on nftables as I grew up with iptables and not with nftables

@brauliobo
Copy link
Author

brauliobo commented Nov 23, 2025

Hi @stangri, yes I'm using SQM and nft sets with domain-based rules. I'm new to OpenWRT development and not able to test in detail. I have 3 WAN and 4 WG interfaces, so I'm testing rules to ping with each of them. I'm also using MWAN3, but I've set PBR a higher priority than it (lower uplink_ip_rules_priority number).

@egc112 The SSH drop of connections is reproducible on every click of "Save & Apply", which triggers a PBR restart. It also happens with other services like a PostgreSQL connection via psql command

@stangri
Copy link
Owner

stangri commented Nov 29, 2025

@egc112 I'd like to lean on your expertise here, I believe it's harmful to merge to dev branch and let people test it in the wild. What do you think?

@egc112
Copy link
Collaborator

egc112 commented Nov 30, 2025

@egc112 I'd like to lean on your expertise here, I believe it's harmful to merge to dev branch and let people test it in the wild. What do you think?

All the main chains (FORWARD, INPUT and OUTPUT) already have a rule on top which preserves RELATED and ESTABLISHED traffic.

The PREROUTING chain does not have that , in the prerouting chain you want to reroute traffic and I can imaging also already existing traffic so adding such a rule to preserve already established traffic might have unwanted side effects.

So I am hesitant to add it.

Note: the OP is using MWAN3 which is also doing PBR and those two package might well be interfering which each other.

@stangri
Copy link
Owner

stangri commented Dec 3, 2025

@egc112 Thanks for your input Erik.

@brauliobo I'm hesitant to add it to the package by default, but if it makes your life easier, I can move the nft-file header to a file on the OpenWrt filesystem instead of hard-coding it into the init script, so you could patch it yourself after install (rather than fixing the init script). Would that be useful for you, or do you have no problem patching the init-file?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants