- portblock: add IPv6 support
- portblock: fix IPv6 rule detection in the iptables backend Resolves: RHEL-171167, RHEL-183131
This commit is contained in:
parent
7a5c9e0f3f
commit
be90666493
125
RHEL-171167-portblock-add-IPv6-support.patch
Normal file
125
RHEL-171167-portblock-add-IPv6-support.patch
Normal file
@ -0,0 +1,125 @@
|
||||
From 269264e5a9859f9d2d31207d5067fc7673025db0 Mon Sep 17 00:00:00 2001
|
||||
From: Yusuf Yildiz <yusuf@upforge.at>
|
||||
Date: Wed, 22 Apr 2026 16:09:23 +0200
|
||||
Subject: [PATCH] portblock: add IPv6 support to iptables and nft backends
|
||||
|
||||
Previously, portblock rejected IPv6 service IPs because:
|
||||
|
||||
- The iptables path fed the address to $IPTABLES (=iptables),
|
||||
which only accepts IPv4.
|
||||
- The nft path emitted `ip daddr`/`ip saddr`, which match IPv4
|
||||
only even inside an `inet` table; IPv6 requires
|
||||
`ip6 daddr`/`ip6 saddr`.
|
||||
|
||||
Detect the IP family from $OCF_RESKEY_ip once (a colon indicates
|
||||
IPv6) and route both backends through a single ${ip_family}
|
||||
variable:
|
||||
|
||||
- iptables path: IPTABLES=${ip_family}tables selects `iptables`
|
||||
or `ip6tables` as appropriate.
|
||||
- nft path: rule templates emit `${ip_family} daddr`/
|
||||
`${ip_family} saddr`; the same keyword is used in the
|
||||
active_grep_pat regex generator so monitor matches what write
|
||||
emits.
|
||||
- The `iptables -V` capability probe now uses $IPTABLES.
|
||||
|
||||
Verified on RHEL 9.7 across all four combinations of
|
||||
(firewall=iptables|nft) x (ip=IPv4|IPv6):
|
||||
|
||||
- iptables + IPv4: installs iptables DROP rule (regression ok).
|
||||
- nft + IPv4: emits `ip daddr ...` rule (regression ok).
|
||||
- iptables + IPv6: installs ip6tables DROP rule (new).
|
||||
- nft + IPv6: emits `ip6 daddr ...` rule (new).
|
||||
|
||||
stop cleans up fully in every case (no leftover rules in
|
||||
`nft list ruleset`, `iptables -S`, or `ip6tables -S` after the
|
||||
run).
|
||||
|
||||
tickle_tcp/tickle_local paths and documentation updates are not
|
||||
covered by this change; they can be handled in follow-up PRs.
|
||||
|
||||
Closes #2151
|
||||
|
||||
Signed-off-by: Yusuf Yildiz <yusuf@upforge.at>
|
||||
---
|
||||
heartbeat/portblock | 26 +++++++++++++++++---------
|
||||
1 file changed, 17 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index 803eea55f6..8fef3beec8 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -49,6 +49,14 @@ fi
|
||||
: ${OCF_RESKEY_method=${OCF_RESKEY_method_default}}
|
||||
: ${OCF_RESKEY_status_check=${OCF_RESKEY_status_check_default}}
|
||||
: ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}}
|
||||
+
|
||||
+# IPv6 support: detect family from service IP and parameterise both backends.
|
||||
+case "$OCF_RESKEY_ip" in
|
||||
+ *:*) ip_family=ip6 ;;
|
||||
+ *) ip_family=ip ;;
|
||||
+esac
|
||||
+IPTABLES=${ip_family}tables
|
||||
+
|
||||
: ${OCF_RESKEY_reset_local_on_unblock_stop=${OCF_RESKEY_reset_local_on_unblock_stop_default}}
|
||||
: ${OCF_RESKEY_tickle_dir=${OCF_RESKEY_tickle_dir_default}}
|
||||
: ${OCF_RESKEY_sync_script=${OCF_RESKEY_sync_script_default}}
|
||||
@@ -332,9 +340,9 @@ active_grep_pat()
|
||||
local ip
|
||||
[ "$4" = "s" ] && ip=$src || ip=$dst
|
||||
if [ "$method" = "DROP" ]; then
|
||||
- echo "^\s\+ip${w}$4addr${w}${ip}${w}$1${w}$4port${w}$2${w}ct${w}state${w}{${w}established,${w}related,${w}new${w}}${w}drop$"
|
||||
+ echo "^\s\+${ip_family}${w}$4addr${w}${ip}${w}$1${w}$4port${w}$2${w}ct${w}state${w}{${w}established,${w}related,${w}new${w}}${w}drop$"
|
||||
else
|
||||
- echo "^\s\+ip${w}$4addr${w}${ip}${w}$1${w}$4port${w}$2${w}ct${w}state${w}{${w}established,${w}related,${w}new${w}}${w}reject${w}with${w}tcp${w}reset$"
|
||||
+ echo "^\s\+${ip_family}${w}$4addr${w}${ip}${w}$1${w}$4port${w}$2${w}ct${w}state${w}{${w}established,${w}related,${w}new${w}}${w}reject${w}with${w}tcp${w}reset$"
|
||||
fi
|
||||
else
|
||||
if [ "$method" = "DROP" ]; then
|
||||
@@ -545,7 +553,7 @@ NftDelete()
|
||||
{
|
||||
local chain=$1 proto=$2 ds=$3 ip=$(echo "$4" | sed "s#/#\\\/#") ports=$5
|
||||
# Try both single port and multi-port patterns for handle search
|
||||
- local handles=$($NFTABLES -a list chain inet $TABLE $chain 2>/dev/null | awk "/\s+ip ${ds}addr $ip $proto ${ds}port $ports/"' {printf "%d ", $NF}')
|
||||
+ local handles=$($NFTABLES -a list chain inet $TABLE $chain 2>/dev/null | awk "/\s+${ip_family} ${ds}addr $ip $proto ${ds}port $ports/"' {printf "%d ", $NF}')
|
||||
for handle in $handles; do
|
||||
ocf_log debug "NftDelete: Deleting $chain rule with handle $handle"
|
||||
nft delete rule inet $TABLE $chain handle $handle || {
|
||||
@@ -570,9 +578,9 @@ DoPort()
|
||||
nft)
|
||||
if [ "$op" = "insert" ]; then
|
||||
if [ "$method" = "DROP" ]; then
|
||||
- $NFTABLES $op rule inet $TABLE $chain ip ${ds}addr $ip $proto ${ds}port $ports ct state { established, related, new } drop
|
||||
+ $NFTABLES $op rule inet $TABLE $chain ${ip_family} ${ds}addr $ip $proto ${ds}port $ports ct state { established, related, new } drop
|
||||
else
|
||||
- $NFTABLES $op rule inet $TABLE $chain ip ${ds}addr $ip $proto ${ds}port $ports ct state { established, related, new } reject with tcp reset
|
||||
+ $NFTABLES $op rule inet $TABLE $chain ${ip_family} ${ds}addr $ip $proto ${ds}port $ports ct state { established, related, new } reject with tcp reset
|
||||
fi
|
||||
elif [ "$op" = "delete" ]; then
|
||||
NftDelete "$chain" "$proto" "$ds" "$ip" "$ports"
|
||||
@@ -609,13 +617,13 @@ PortBLOCK()
|
||||
else
|
||||
if [ "$FIREWALL" = "nft" ]; then
|
||||
if $try_reset ; then
|
||||
- $NFTABLES insert rule inet $TABLE OUTPUT ip saddr $3 $1 sport $2 ct state { established, related, new } reject with tcp reset
|
||||
+ $NFTABLES insert rule inet $TABLE OUTPUT ${ip_family} saddr $3 $1 sport $2 ct state { established, related, new } reject with tcp reset
|
||||
tickle_local
|
||||
fi
|
||||
if [ "$method" = "DROP" ]; then
|
||||
- $NFTABLES insert rule inet $TABLE INPUT ip daddr $3 $1 dport $2 ct state { established, related, new } drop
|
||||
+ $NFTABLES insert rule inet $TABLE INPUT ${ip_family} daddr $3 $1 dport $2 ct state { established, related, new } drop
|
||||
else
|
||||
- $NFTABLES insert rule inet $TABLE INPUT ip daddr $3 $1 dport $2 ct state { established, related, new } reject with tcp reset
|
||||
+ $NFTABLES insert rule inet $TABLE INPUT ${ip_family} daddr $3 $1 dport $2 ct state { established, related, new } reject with tcp reset
|
||||
fi
|
||||
rc_in=$?
|
||||
if $try_reset ; then
|
||||
@@ -937,7 +945,7 @@ if [ "$FIREWALL" = "nft" ]; then
|
||||
echo "$portno" | grep -q "," && portno="{ $(echo $portno | sed 's/,/, /g') }"
|
||||
elif [ "$FIREWALL" = "iptables" ]; then
|
||||
# iptables v1.4.20+ is required to use -w (wait)
|
||||
- version=$(iptables -V | grep -oE '[0-9]+[\.0-9]+')
|
||||
+ version=$($IPTABLES -V | grep -oE '[0-9]+[\.0-9]+')
|
||||
ocf_version_cmp "$version" "1.4.19.1"
|
||||
if [ "$?" -eq "2" ]; then
|
||||
wait="-w"
|
||||
@ -0,0 +1,75 @@
|
||||
From 81386a499106053f658aad336865cc36f67ab168 Mon Sep 17 00:00:00 2001
|
||||
From: Yusuf Yildiz <yusuf@upforge.at>
|
||||
Date: Fri, 5 Jun 2026 12:42:42 +0200
|
||||
Subject: [PATCH] portblock: fix IPv6 rule detection in the iptables backend
|
||||
|
||||
active_grep_pat() hardcoded the IPv4 "anywhere" address 0.0.0.0/0 when
|
||||
building the regex used to detect existing DROP/REJECT rules from
|
||||
"iptables -L" output. ip6tables prints ::/0 in the source/destination
|
||||
"anywhere" column, so for an IPv6 service IP the grep never matched an
|
||||
existing rule and chain_isactive() always reported the rule as absent.
|
||||
|
||||
Because rule handling is gated on that detection, an IPv6 OCF_RESKEY_ip
|
||||
caused:
|
||||
|
||||
- "unblock start" to never remove the DROP rule (DoIptables() sees the
|
||||
rule as already absent and skips the -D), so the port stayed blocked
|
||||
after the protected service was up;
|
||||
- "block stop" to likewise leave the DROP rule behind;
|
||||
- monitor/status to always report inactive;
|
||||
- duplicate rules to potentially accumulate across restarts.
|
||||
|
||||
"block start" appeared to work only because IptablesBLOCK() inserts the
|
||||
rule when detection reports it absent, which masked the problem.
|
||||
|
||||
Select the "anywhere" literal with a case on $ip_family (::/0 for
|
||||
ip6tables, 0.0.0.0/0 otherwise), matching the family-aware handling the
|
||||
nft backend already had.
|
||||
|
||||
A second variant of the same detection failure remained: the "opt" column
|
||||
("--") is printed by legacy iptables but omitted by nft-backed ip6tables,
|
||||
so the mandatory "--" in the regex still failed to match on those builds
|
||||
and the DROP rule was again never removed on unblock. Make the opt column
|
||||
optional so the pattern matches both legacy iptables (prints "--") and
|
||||
nft-backed ip6tables (omits it); IPv4 with legacy "--" is unchanged.
|
||||
|
||||
Tested on a 3-node AlmaLinux 9.7 cluster (iptables/ip6tables v1.8.10,
|
||||
nf_tables) driving an IPv6 service IP end-to-end through LINSTOR Gateway
|
||||
kernel NFS (portblock action=block + action=unblock): the DROP rule is now
|
||||
inserted on block and removed on unblock with no leftover rule, monitor
|
||||
reports correctly, and the IPv4 path is unchanged.
|
||||
|
||||
Co-authored-by: Claude <noreply@anthropic.com>
|
||||
Signed-off-by: Yusuf Yildiz <yusuf@upforge.at>
|
||||
---
|
||||
heartbeat/portblock | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/heartbeat/portblock b/heartbeat/portblock
|
||||
index 8fef3beec8..f922ee0db6 100755
|
||||
--- a/heartbeat/portblock
|
||||
+++ b/heartbeat/portblock
|
||||
@@ -323,7 +323,10 @@ END
|
||||
active_grep_pat()
|
||||
{
|
||||
w="[ ][ ]*"
|
||||
- any="0\\.0\\.0\\.0/0"
|
||||
+ case $ip_family in
|
||||
+ ip6) any="::/0" ;;
|
||||
+ *) any="0\\.0\\.0\\.0/0" ;;
|
||||
+ esac
|
||||
src=$any dst=$3
|
||||
if [ "$4" = "s" ]; then
|
||||
local src=$3
|
||||
@@ -346,9 +349,9 @@ active_grep_pat()
|
||||
fi
|
||||
else
|
||||
if [ "$method" = "DROP" ]; then
|
||||
- echo "^DROP${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$"
|
||||
+ echo "^DROP${w}${prot}${w}\(--${w}\)\?${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$"
|
||||
else
|
||||
- echo "^REJECT${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}${w}ctstate${w}NEW,RELATED,ESTABLISHED${w}reject-with${w}tcp-reset$"
|
||||
+ echo "^REJECT${w}${prot}${w}\(--${w}\)\?${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}${w}ctstate${w}NEW,RELATED,ESTABLISHED${w}reject-with${w}tcp-reset$"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@ -45,7 +45,7 @@
|
||||
Name: resource-agents
|
||||
Summary: Open Source HA Reusable Cluster Resource Scripts
|
||||
Version: 4.16.0
|
||||
Release: 70%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}
|
||||
Release: 71%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-or-later
|
||||
URL: https://github.com/ClusterLabs/resource-agents
|
||||
Source0: %{upstream_prefix}-%{upstream_version}.tar.gz
|
||||
@ -141,6 +141,8 @@ Patch88: RHEL-180765-2-nfsserver-fixes-incorrect-indentation.patch
|
||||
Patch89: RHEL-156729-sybaseASE-fix-for-missing-sybaseASE-env-during-probe-action.patch
|
||||
Patch90: RHEL-180765-3-nfsserver-do-not-try-to-stop-fsidd-when-not-present.patch
|
||||
Patch91: RHEL-182592-nfsserver-monitor-nfsdcld-and-nfs-mountd-services-to-trigger-recovery-on-failure.patch
|
||||
Patch92: RHEL-171167-portblock-add-IPv6-support.patch
|
||||
Patch93: RHEL-183131-portblock-fix-IPv6-rule-detection-in-the-iptables-backend.patch
|
||||
|
||||
# bundled ha-cloud-support libs
|
||||
Patch500: ha-cloud-support-aliyun.patch
|
||||
@ -403,6 +405,8 @@ exit 1
|
||||
%patch -p1 -P 89
|
||||
%patch -p1 -P 90
|
||||
%patch -p1 -P 91
|
||||
%patch -p1 -P 92
|
||||
%patch -p1 -P 93
|
||||
|
||||
# bundled ha-cloud-support libs
|
||||
%patch -p1 -P 500
|
||||
@ -735,6 +739,12 @@ rm -rf %{buildroot}/usr/share/doc/resource-agents
|
||||
%{_usr}/lib/ocf/lib/heartbeat/OCF_*.pm
|
||||
|
||||
%changelog
|
||||
* Fri Jun 19 2026 Oyvind Albrigtsen <oalbrigt@redhat.com> - 4.16.0-71
|
||||
- portblock: add IPv6 support
|
||||
- portblock: fix IPv6 rule detection in the iptables backend
|
||||
|
||||
Resolves: RHEL-171167, RHEL-183131
|
||||
|
||||
* Thu Jun 11 2026 Arslan Ahmad <arahmad@redhat.com> - 4.16.0-70
|
||||
- nfsserver: monitor nfsdcld and nfs-mountd services to trigger
|
||||
recovery on failure
|
||||
|
||||
Loading…
Reference in New Issue
Block a user