Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The following are compatibility adapters, not PastureStack branding:

The default metadata endpoint is the brand-neutral link-local address `http://169.254.169.250/2015-12-19`; it does not depend on an internal DNS alias.

For Docker's native nftables bridge firewall, select `nftables` or let `auto` discover `ip docker-bridges`. The router does not write host firewall rules in this mode: the active network-plugin-manager must manage the overlay subnet's forwarding mark and exclude overlay destinations from its own egress masquerade. Docker must be configured to accept mark `0x1068/0x1068`. An xtables `ACCEPT` rule in a different nftables base chain is not a valid replacement for that NAT exclusion. The router does not alter Docker-owned chains, host FORWARD policy, or legacy kernel modules. If Docker's native table is absent, it chooses the live `iptables-nft` DOCKER NAT chain, or an already-loaded legacy DOCKER NAT chain for an old host; it fails closed if neither is identifiable. An explicit xtables selection is rejected while Docker's native table exists.
For Docker's native nftables bridge firewall, select `nftables` or let `auto` discover `ip docker-bridges`. The router does not write host firewall rules in this mode: the active network-plugin-manager must manage the overlay subnet's forwarding mark and exclude overlay destinations from its own egress masquerade. Docker must be configured to accept mark `0x1068/0x1068`. An xtables `ACCEPT` rule in a different nftables base chain is not a valid replacement for that NAT exclusion. The router does not alter Docker-owned chains, host FORWARD policy, or legacy kernel modules. If Docker's native table is absent, it chooses the live `iptables-nft` DOCKER NAT chain, or an already-loaded legacy DOCKER NAT chain for an old host; it fails closed if neither is identifiable. An explicit xtables selection is rejected while Docker's native table exists. Explicit `iptables-legacy` also refuses an active Docker `iptables-nft` chain or an unloaded legacy NAT table before invoking the legacy CLI, so a mistaken choice on Ubuntu 26.04 cannot load legacy modules merely by probing them.

The VXLAN router's historical POSTROUTING rule executes only inside its own container network namespace, not in the IPsec host-XFRM namespace. The IPsec firewall selection does not change that independent runtime path.

Expand Down
13 changes: 13 additions & 0 deletions package/firewall-backend.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ resolve_firewall_backend() {
echo "Docker uses native nftables; refusing an xtables overlay backend" >&2
return 1
fi
if [ "$requested" = iptables-legacy ]; then
# A legacy inspection on an nft-only host can itself load the
# forbidden legacy modules. Reject a live nft Docker chain
# and require an already-loaded legacy NAT table first.
if host_netns_cmd iptables-nft -t nat -S DOCKER >/dev/null 2>&1; then
echo "Docker uses iptables-nft; refusing an iptables-legacy overlay backend" >&2
return 1
fi
if ! host_netns_cmd grep -qx nat /proc/net/ip_tables_names; then
echo "No active legacy NAT table; refusing an iptables-legacy probe" >&2
return 1
fi
fi
host_netns_cmd "$requested" -t nat -S DOCKER >/dev/null || return 1
;;
esac
Expand Down
29 changes: 29 additions & 0 deletions scripts/test-firewall-backend
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ case " ${commands[*]} " in
*) echo "Expected active legacy Docker chain" >&2; exit 1 ;;
esac

commands=()
TEST_DOCKER_BACKEND=iptables-legacy
PASTURESTACK_FIREWALL_BACKEND=iptables-legacy
resolve_firewall_backend
[ "$PASTURESTACK_FIREWALL_BACKEND" = iptables-legacy ]
[[ " ${commands[*]} " == *"iptables-legacy -t nat -S DOCKER"* ]]

commands=()
TEST_DOCKER_BACKEND=nftables
PASTURESTACK_FIREWALL_BACKEND=iptables-legacy
Expand All @@ -63,6 +70,28 @@ if resolve_firewall_backend; then
exit 1
fi

commands=()
TEST_DOCKER_BACKEND=iptables-nft
PASTURESTACK_FIREWALL_BACKEND=iptables-legacy
if resolve_firewall_backend; then
echo "Explicit legacy must fail when Docker uses iptables-nft" >&2
exit 1
fi
case " ${commands[*]} " in
*iptables-legacy*) echo "Mismatch probed legacy despite active Docker nft frontend" >&2; exit 1 ;;
esac

commands=()
TEST_DOCKER_BACKEND=unknown
PASTURESTACK_FIREWALL_BACKEND=iptables-legacy
if resolve_firewall_backend; then
echo "Explicit legacy requires an already-loaded legacy NAT table" >&2
exit 1
fi
case " ${commands[*]} " in
*iptables-legacy*) echo "Absent legacy table must not trigger a module-loading probe" >&2; exit 1 ;;
esac

commands=()
TEST_DOCKER_BACKEND=unknown
PASTURESTACK_FIREWALL_BACKEND=auto
Expand Down
Loading