From 344beb18e41442f7af86fa585e4fb970452dc632 Mon Sep 17 00:00:00 2001 From: Oyvind Albrigtsen Date: Fri, 10 Oct 2025 16:31:00 +0200 Subject: [PATCH] portblock: add Promoted monitor op, validate-all checks, and add "method" and "status_check" parameters - add Promoted monitor op - run validate-all to catch missing firewall binary and other issues for non-metadata/usage actions - add "method" parameter with reject alternative to be able to clear connections when blocking - add "status_check" parameter to allow user to specify rule or pseudo check --- heartbeat/portblock | 93 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 14 deletions(-) diff --git a/heartbeat/portblock b/heartbeat/portblock index ff162c955..4fc9c2bb8 100755 --- a/heartbeat/portblock +++ b/heartbeat/portblock @@ -29,6 +29,8 @@ OCF_RESKEY_protocol_default="" OCF_RESKEY_portno_default="" OCF_RESKEY_direction_default="in" OCF_RESKEY_action_default="" +OCF_RESKEY_method_default="drop" +OCF_RESKEY_status_check_default="rule" OCF_RESKEY_ip_default="0.0.0.0/0" OCF_RESKEY_reset_local_on_unblock_stop_default="false" OCF_RESKEY_tickle_dir_default="" @@ -39,6 +41,8 @@ OCF_RESKEY_sync_script_default="" : ${OCF_RESKEY_portno=${OCF_RESKEY_portno_default}} : ${OCF_RESKEY_direction=${OCF_RESKEY_direction_default}} : ${OCF_RESKEY_action=${OCF_RESKEY_action_default}} +: ${OCF_RESKEY_method=${OCF_RESKEY_method_default}} +: ${OCF_RESKEY_status_check=${OCF_RESKEY_status_check_default}} : ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}} : ${OCF_RESKEY_reset_local_on_unblock_stop=${OCF_RESKEY_reset_local_on_unblock_stop_default}} : ${OCF_RESKEY_tickle_dir=${OCF_RESKEY_tickle_dir_default}} @@ -195,6 +199,26 @@ actions. + + +Block method: +drop: Use DROP rule. +reject: Use REJECT rule w/conntrack to clear connections when blocking. + +Block method + + + + + +Status check: +rule: Check rule. +pseudo: Check pseudo status when rule is absent. + +Status check + + + If for some reason the long lived server side TCP sessions won't be cleaned up @@ -263,6 +287,7 @@ If "both" is used, both the incoming and outgoing ports are blocked. + @@ -301,9 +326,17 @@ active_grep_pat() if [ "$FIREWALL" = "nft" ]; then local ip [ "$4" = "s" ] && ip=$src || ip=$dst - echo "^\s\+ip $4addr ${ip} $1 $4port $2 ct state { established, related, new } drop$" + 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$" + 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$" + fi else - echo "^DROP${w}${prot}${w}--${w}${src}${w}${dst}${w}multiport${w}${4}ports${w}${2}$" + if [ "$method" = "DROP" ]; then + 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$" + fi fi } @@ -394,17 +427,17 @@ tickle_local() SayActive() { - ocf_log debug "$CMD DROP rule [$*] is running (OK)" + ocf_log debug "$CMD $method rule [$*] is running (OK)" } SayConsideredActive() { - ocf_log debug "$CMD DROP rule [$*] considered to be running (OK)" + ocf_log debug "$CMD $method rule [$*] considered to be running (OK)" } SayInactive() { - ocf_log debug "$CMD DROP rule [$*] is inactive" + ocf_log debug "$CMD $method rule [$*] is inactive" } #PortStatus {udp|tcp} portno,portno ip {in|out|both} {block|unblock} @@ -425,14 +458,18 @@ PortStatus() { case $5 in block) SayActive $* - rc=$OCF_SUCCESS + if [ "$__OCF_ACTION" = "monitor" ] && [ "$promotion_score" = "$SCORE_PROMOTED" ]; then + rc=$OCF_RUNNING_MASTER + else + rc=$OCF_SUCCESS + fi ;; *) SayInactive $* rc=$OCF_NOT_RUNNING ;; esac - elif ocf_is_ms; then + elif [ "$OCF_RESKEY_status_check" = "rule" ]; then case $5 in block) SayInactive $* @@ -440,7 +477,11 @@ PortStatus() { ;; *) SayActive $* - rc=$OCF_SUCCESS + if [ "$__OCF_ACTION" = "monitor" ] && [ "$promotion_score" = "$SCORE_PROMOTED" ]; then + rc=$OCF_RUNNING_MASTER + else + rc=$OCF_SUCCESS + fi ;; esac else @@ -499,13 +540,21 @@ DoPort() case $FIREWALL in nft) if [ "$op" = "insert" ]; then - $NFTABLES $op rule inet $TABLE $chain ip ${ds}addr $ip $proto ${ds}port $ports ct state { established, related, new } drop + if [ "$method" = "DROP" ]; then + $NFTABLES $op rule inet $TABLE $chain ip ${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 + fi elif [ "$op" = "delete" ]; then NftDelete "$chain" "$proto" "$ds" "$ip" "$ports" fi ;; iptables) - $IPTABLES $wait "$op" "$chain" -p "$proto" -${ds} "$ip" -m multiport --${ds}ports "$ports" -j DROP + if [ "$method" = "DROP" ]; then + $IPTABLES $wait "$op" "$chain" -p "$proto" -${ds} "$ip" -m multiport --${ds}ports "$ports" -j DROP + else + $IPTABLES $wait "$op" "$chain" -p "$proto" -${ds} "$ip" -m multiport --${ds}ports "$ports" -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j REJECT --reject-with tcp-reset + fi ;; esac fi @@ -534,7 +583,11 @@ PortBLOCK() $NFTABLES insert rule inet $TABLE OUTPUT ip saddr $3 $1 sport $2 ct state { established, related, new } reject with tcp reset tickle_local fi - $NFTABLES insert rule inet $TABLE INPUT ip daddr $3 $1 dport $2 ct state { established, related, new } drop + if [ "$method" = "DROP" ]; then + $NFTABLES insert rule inet $TABLE INPUT ip 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 + fi rc_in=$? if $try_reset ; then NftDelete "OUTPUT" "$1" "s" "$ports" @@ -544,7 +597,11 @@ PortBLOCK() $IPTABLES $wait -I OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset tickle_local fi - $IPTABLES $wait -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP + if [ "$method" = "DROP" ]; then + $IPTABLES $wait -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP + else + $IPTABLES $wait -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j REJECT --reject-with tcp-reset + fi rc_in=$? if $try_reset ; then $IPTABLES $wait -D OUTPUT -p "$1" -s "$3" -m multiport --sports "$2" -j REJECT --reject-with tcp-reset @@ -768,7 +825,7 @@ detect_firewall_tool() { ocf_log debug "Detected iptables" else ocf_exit_reason "No firewall tool available" - return $OCF_ERR_CONFIGURED + exit $OCF_ERR_CONFIGURED fi } @@ -812,6 +869,13 @@ action=$OCF_RESKEY_action ip=$OCF_RESKEY_ip reset_local_on_unblock_stop=$OCF_RESKEY_reset_local_on_unblock_stop nodename=$(ocf_local_nodename) +case "$OCF_RESKEY_method" in + drop) method="DROP" ;; + reject) method="REJECT" ;; + *) ocf_log err "method: $OCF_RESKEY_method not supported" + exit $OCF_ERR_CONFIGURED + ;; +esac # If "tickle" is enabled, we need to record the list of currently established @@ -863,6 +927,8 @@ if ocf_is_ms; then fi fi +PortValidateAll + case $__OCF_ACTION in start) PortStart "$protocol" "$portno" "$ip" "$direction" "$action" @@ -885,7 +951,6 @@ case $__OCF_ACTION in ;; validate-all) - PortValidateAll ;; *) usage