Fix FORWARD-drop reply handling

This commit is contained in:
2026-04-17 12:10:11 +08:00
parent 479c416b2f
commit 87ee5283c8
6 changed files with 61 additions and 46 deletions

View File

@@ -1,19 +1,15 @@
#!/usr/bin/env bash
if [[ -n ${IPF_IPTABLES_OPS_SH_LOADED:-} ]]; then
return 0
fi
IPF_IPTABLES_OPS_SH_LOADED=1
: "${IPTABLES_BIN:=iptables}"
: "${IP6TABLES_BIN:=ip6tables}"
: "${IPTABLES_SAVE_BIN:=iptables-save}"
: "${IP6TABLES_SAVE_BIN:=ip6tables-save}"
ipt_comment_tag() {
printf 'MGMT:%s\n' "$1"
}
ipt_protocols_for() {
case ${1-} in
tcp|udp) printf '%s\n' "$1" ;;
@@ -21,7 +17,6 @@ ipt_protocols_for() {
*) return 1 ;;
esac
}
ipt_families_for() {
case ${1-} in
4|6) printf '%s\n' "$1" ;;
@@ -29,7 +24,6 @@ ipt_families_for() {
*) return 1 ;;
esac
}
ipt_bin_for_family() {
case ${1-} in
4) printf '%s\n' "${IPTABLES_BIN}" ;;
@@ -37,7 +31,6 @@ ipt_bin_for_family() {
*) return 1 ;;
esac
}
ipt_save_bin_for_family() {
case ${1-} in
4) printf '%s\n' "${IPTABLES_SAVE_BIN}" ;;
@@ -45,7 +38,6 @@ ipt_save_bin_for_family() {
*) return 1 ;;
esac
}
ipt_target_for_family() {
local raw=${1-}
local family=${2-}
@@ -59,7 +51,6 @@ ipt_target_for_family() {
fi
printf '%s\n' "${raw}"
}
ipt_to_destination() {
local tip_raw=${1-}
local tport=${2-}
@@ -72,7 +63,6 @@ ipt_to_destination() {
printf '%s:%s\n' "${tip}" "${tport}"
fi
}
_ipt_exec_rule() {
local bin=$1
local table=$2
@@ -85,7 +75,6 @@ _ipt_exec_rule() {
"${bin}" "-${action}" "${chain}" "$@"
fi
}
_ipt_check_rule() {
local bin=$1
local table=$2
@@ -97,7 +86,6 @@ _ipt_check_rule() {
"${bin}" -C "${chain}" "$@" >/dev/null 2>&1
fi
}
_ipt_apply_expected_rules() {
local action=$1
local uuid=$2
@@ -108,13 +96,11 @@ _ipt_apply_expected_rules() {
local ipver=$7
local family protocol bin tip comment destination
comment=$(ipt_comment_tag "${uuid}")
while IFS= read -r family; do
[[ -n ${family} ]] || continue
bin=$(ipt_bin_for_family "${family}")
tip=$(ipt_target_for_family "${tip_raw}" "${family}")
destination=$(ipt_to_destination "${tip_raw}" "${tport}" "${family}")
while IFS= read -r protocol; do
[[ -n ${protocol} ]] || continue
if ! _ipt_exec_rule "${bin}" nat "${action}" PREROUTING \
@@ -123,14 +109,12 @@ _ipt_apply_expected_rules() {
-m comment --comment "${comment}"; then
return 1
fi
if ! _ipt_exec_rule "${bin}" nat "${action}" POSTROUTING \
-p "${protocol}" -d "${tip}" --dport "${tport}" \
-j MASQUERADE \
-m comment --comment "${comment}"; then
return 1
fi
if ! _ipt_exec_rule "${bin}" '' "${action}" FORWARD \
-p "${protocol}" -d "${tip}" --dport "${tport}" \
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
@@ -138,10 +122,16 @@ _ipt_apply_expected_rules() {
-m comment --comment "${comment}"; then
return 1
fi
if ! _ipt_exec_rule "${bin}" '' "${action}" FORWARD \
-p "${protocol}" -s "${tip}" --sport "${tport}" \
-m conntrack --ctstate ESTABLISHED,RELATED \
-j ACCEPT \
-m comment --comment "${comment}"; then
return 1
fi
done < <(ipt_protocols_for "${proto}")
done < <(ipt_families_for "${ipver}")
}
ipt_apply_rule() {
local uuid=$1 proto=$2 lport=$3 tip_raw=$4 tport=$5 ipver=$6
if ! _ipt_apply_expected_rules A "${uuid}" "${proto}" "${lport}" "${tip_raw}" "${tport}" "${ipver}"; then
@@ -149,18 +139,15 @@ ipt_apply_rule() {
return 1
fi
}
ipt_rule_healthy() {
local uuid=$1 proto=$2 lport=$3 tip_raw=$4 tport=$5 ipver=$6
local family protocol bin tip comment destination
comment=$(ipt_comment_tag "${uuid}")
while IFS= read -r family; do
[[ -n ${family} ]] || continue
bin=$(ipt_bin_for_family "${family}")
tip=$(ipt_target_for_family "${tip_raw}" "${family}")
destination=$(ipt_to_destination "${tip_raw}" "${tport}" "${family}")
while IFS= read -r protocol; do
[[ -n ${protocol} ]] || continue
_ipt_check_rule "${bin}" nat PREROUTING \
@@ -176,10 +163,14 @@ ipt_rule_healthy() {
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
-j ACCEPT \
-m comment --comment "${comment}" || return 1
_ipt_check_rule "${bin}" '' FORWARD \
-p "${protocol}" -s "${tip}" --sport "${tport}" \
-m conntrack --ctstate ESTABLISHED,RELATED \
-j ACCEPT \
-m comment --comment "${comment}" || return 1
done < <(ipt_protocols_for "${proto}")
done < <(ipt_families_for "${ipver}")
}
ipt_remove_rule() {
local uuid=$1 proto=$2 lport=$3 tip_raw=$4 tport=$5 ipver=$6
local -a families protocols
@@ -188,18 +179,28 @@ ipt_remove_rule() {
comment=$(ipt_comment_tag "${uuid}")
mapfile -t families < <(ipt_families_for "${ipver}")
mapfile -t protocols < <(ipt_protocols_for "${proto}")
for ((family_index=${#families[@]} - 1; family_index >= 0; family_index--)); do
family=${families[family_index]}
[[ -n ${family} ]] || continue
bin=$(ipt_bin_for_family "${family}")
tip=$(ipt_target_for_family "${tip_raw}" "${family}")
destination=$(ipt_to_destination "${tip_raw}" "${tport}" "${family}")
for ((proto_index=${#protocols[@]} - 1; proto_index >= 0; proto_index--)); do
protocol=${protocols[proto_index]}
[[ -n ${protocol} ]] || continue
if _ipt_check_rule "${bin}" '' FORWARD \
-p "${protocol}" -s "${tip}" --sport "${tport}" \
-m conntrack --ctstate ESTABLISHED,RELATED \
-j ACCEPT \
-m comment --comment "${comment}"; then
_ipt_exec_rule "${bin}" '' D FORWARD \
-p "${protocol}" -s "${tip}" --sport "${tport}" \
-m conntrack --ctstate ESTABLISHED,RELATED \
-j ACCEPT \
-m comment --comment "${comment}" || return 1
else
missing=1
fi
if _ipt_check_rule "${bin}" '' FORWARD \
-p "${protocol}" -d "${tip}" --dport "${tport}" \
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
@@ -213,7 +214,6 @@ ipt_remove_rule() {
else
missing=1
fi
if _ipt_check_rule "${bin}" nat POSTROUTING \
-p "${protocol}" -d "${tip}" --dport "${tport}" \
-j MASQUERADE \
@@ -225,7 +225,6 @@ ipt_remove_rule() {
else
missing=1
fi
if _ipt_check_rule "${bin}" nat PREROUTING \
-p "${protocol}" --dport "${lport}" \
-j DNAT --to-destination "${destination}" \
@@ -239,17 +238,14 @@ ipt_remove_rule() {
fi
done
done
if (( missing == 1 )); then
return 0
fi
}
ipt_find_by_uuid() {
local uuid=${1-}
local family save_bin found=1 line
[[ -n ${uuid} ]] || return 1
for family in 4 6; do
save_bin=$(ipt_save_bin_for_family "${family}")
if ! command_is_available "${save_bin}"; then
@@ -261,6 +257,5 @@ ipt_find_by_uuid() {
found=0
done < <("${save_bin}")
done
return "${found}"
}