日本語に対応しました

This commit is contained in:
joe 2026-02-04 10:24:13 +09:00
parent 6dd9812ec9
commit d11c152767

266
ipf
View file

@ -1,20 +1,59 @@
#!/bin/bash #!/bin/bash
# Name: ipf # Name: ipf
# Version: 1.6.7 # Version: 1.6.9
# Date: 2026-02-04 # Date: 2026-02-04
# Description: Finalized multi-protocol detection. # Description: Fully featured port forwarder with rich help, multi-protocol
# Handles OpenResty/Nginx "Plain HTTP to HTTPS" (400) cases intelligently. # detection (SSH/HTTP/HTTPS/etc.), and JP/EN localization.
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# 1. Root & Environment Check # 1. Locale & Messaging Setup
# -----------------------------------------------------------------------------
SYSTEM_LANG=$([[ "$LANG" =~ ^ja ]] && echo "ja" || echo "en")
declare -A MSGS
if [[ "$SYSTEM_LANG" == "ja" ]]; then
MSGS=(
[system]="\e[34m[システム]\e[0m"
[enabling_fwd]="IPフォワーディングを有効化しています..."
[err_fwd]="致命的: net.ipv4.ip_forward を有効にできませんでした。"
[rules_header]="転送ルール一覧 (テーブル: %s):"
[overwrite]="\e[33mポート :%s (ハンドル %s) の既存ルールを上書きします...\e[0m"
[reset_warn]="\e[33m警告: テーブル '%s' 内の全ルールが削除されます。\e[0m"
[confirm]="削除を確認しますか? (y/N): "
[reset_done]="テーブル '%s' をリセットしました。"
[testing]="ハンドル %s をテスト中 (Local :%s -> Target %s:%s) [%s]... "
[passed]=" \e[32m成功 (パケット増分: +%s)\e[0m"
[skipped]=" \e[33mスキップ (疎通なし、またはシャドウイングの可能性)\e[0m"
[err_not_found]="ハンドル %s が見つかりません。"
[unknown_opt]="不明なオプション '%s' です。-h でヘルプを表示してください。"
)
else
MSGS=(
[system]="\e[34m[System]\e[0m"
[enabling_fwd]="Enabling IP forwarding..."
[err_fwd]="Critical: Could not enable net.ipv4.ip_forward."
[rules_header]="Forwarding Rules (Table: %s):"
[overwrite]="\e[33mOverwriting existing rule on port :%s (Handle %s)...\e[0m"
[reset_warn]="\e[33mWarning: This will delete ALL rules in table '%s'.\e[0m"
[confirm]="Confirm removal? (y/N): "
[reset_done]="Table '%s' has been reset."
[testing]="Testing handle %s (Local :%s -> Target %s:%s) [%s]... "
[passed]=" \e[32mPASSED (Counter: +%s)\e[0m"
[skipped]=" \e[33mSKIPPED (No traffic or shadowed)\e[0m"
[err_not_found]="Handle %s not found."
[unknown_opt]="Unknown option '%s'. Use -h for help."
)
fi
# -----------------------------------------------------------------------------
# 2. Root Check & Init
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
if [ "$(id -u)" -ne 0 ]; then if [ "$(id -u)" -ne 0 ]; then
exec sudo "$0" "$@" exec sudo "$0" "$@"
fi fi
# Global Configurations
TABLE_NAME="ipf" TABLE_NAME="ipf"
VERSION="1.6.7" VERSION="1.6.9"
PROTO="tcp" PROTO="tcp"
FORCE_FLAG=false FORCE_FLAG=false
SKIP_TEST=false SKIP_TEST=false
@ -22,23 +61,14 @@ QUIET_MODE=false
RESET_MODE=false RESET_MODE=false
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# 2. Messaging & System Functions # 3. Core Functions
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
msg() { msg() { [[ "$QUIET_MODE" == false ]] && echo -e "$@"; }
[[ "$QUIET_MODE" == false ]] && echo -e "$@" err() { [[ "$QUIET_MODE" == false ]] && echo -e "\e[31m$@\e[0m" >&2 || echo "$@" >&2; }
}
err() {
if [[ "$QUIET_MODE" == false ]]; then
echo -e "\e[31m$@\e[0m" >&2
else
echo "$@" >&2
fi
}
enable_forwarding() { enable_forwarding() {
msg "\e[34m[System]\e[0m Enabling IP forwarding..." msg "${MSGS[system]} ${MSGS[enabling_fwd]}"
sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1
for dev in /proc/sys/net/ipv4/conf/*/route_localnet; do for dev in /proc/sys/net/ipv4/conf/*/route_localnet; do
[[ -f "$dev" ]] && echo 1 > "$dev" 2>/dev/null [[ -f "$dev" ]] && echo 1 > "$dev" 2>/dev/null
@ -53,21 +83,9 @@ init_nft() {
nft add chain inet "${TABLE_NAME}" forward "{ type filter hook forward priority 0 ; policy accept ; }" 2>/dev/null nft add chain inet "${TABLE_NAME}" forward "{ type filter hook forward priority 0 ; policy accept ; }" 2>/dev/null
} }
# -----------------------------------------------------------------------------
# 3. Connectivity & Counter Functions
# -----------------------------------------------------------------------------
get_total_packets() {
local uuid=$1
nft list table inet "${TABLE_NAME}" 2>/dev/null | grep "$uuid" | grep -o 'packets [0-9]*' | awk '{sum+=$2} END {print sum+0}'
}
test_connection() { test_connection() {
local host=$1 local host=$1; local port=$2; local info=""
local port=$2 # Protocol Banner Check
local info=""
# A. Check for Protocol Banners (SSH, FTP, etc.)
local banner=$(timeout 0.5s nc -w 1 "$host" "$port" 2>/dev/null | head -n 1 | tr -d '\000-\031') local banner=$(timeout 0.5s nc -w 1 "$host" "$port" 2>/dev/null | head -n 1 | tr -d '\000-\031')
if [[ -n "$banner" ]]; then if [[ -n "$banner" ]]; then
case "$banner" in case "$banner" in
@ -77,55 +95,94 @@ test_connection() {
"mysql"*) info=" (MySQL)" ;; "mysql"*) info=" (MySQL)" ;;
*) info=" (Banner: ${banner:0:15})" ;; *) info=" (Banner: ${banner:0:15})" ;;
esac esac
echo -e "\e[32mUP\e[0m${info}" echo -e "\e[32mUP\e[0m${info}"; return 0
return 0
fi fi
# HTTP/HTTPS Check
# B. Check for HTTP/HTTPS
if nc -z -w 1 "$host" "$port" >/dev/null 2>&1; then if nc -z -w 1 "$host" "$port" >/dev/null 2>&1; then
local schemas=("http" "https") local schemas=("http" "https"); [[ "$port" == "443" ]] && schemas=("https" "http")
[[ "$port" == "443" ]] && schemas=("https" "http")
for sch in "${schemas[@]}"; do for sch in "${schemas[@]}"; do
# Try HEAD first
local res=$(curl -IsLk -m 2 -A "Mozilla/5.0 ipf-tester" -o /dev/null -w "%{http_code}" "${sch}://${host}:${port}/" 2>/dev/null) local res=$(curl -IsLk -m 2 -A "Mozilla/5.0 ipf-tester" -o /dev/null -w "%{http_code}" "${sch}://${host}:${port}/" 2>/dev/null)
[[ "$res" == "000" ]] && res=$(curl -sLk -m 2 -A "Mozilla/5.0 ipf-tester" -o /dev/null -w "%{http_code}" "${sch}://${host}:${port}/" 2>/dev/null)
# Try GET if HEAD fails (timeout or 000) if [[ "$res" == "400" ]]; then info=" (HTTPS? 400 Bad Request)"; break
if [[ "$res" == "000" ]]; then elif [[ "$res" =~ ^[0-9]+$ && "$res" -ne 000 ]]; then info=" (${sch^^} $res)"; break; fi
res=$(curl -sLk -m 2 -A "Mozilla/5.0 ipf-tester" -o /dev/null -w "%{http_code}" "${sch}://${host}:${port}/" 2>/dev/null)
fi
if [[ "$res" == "400" ]]; then
# Special Case: Nginx/OpenResty plain HTTP to HTTPS port
info=" (HTTPS? 400 Bad Request)"
break
elif [[ "$res" =~ ^[0-9]+$ && "$res" -ne 000 ]]; then
info=" (${sch^^} $res)"
break
fi
done done
echo -e "\e[32mUP\e[0m${info}" echo -e "\e[32mUP\e[0m${info}"; return 0
return 0
else else
echo -e "\e[31mDOWN\e[0m" echo -e "\e[31mDOWN\e[0m"; return 1
return 1 fi
}
show_help() {
if [[ "$SYSTEM_LANG" == "ja" ]]; then
cat << EOF
ipf (IP Forwarder) - nftablesベースの簡易ポート転送管理ツール
使用法:
ipf [オプション] [ルール]
ルール形式:
<ローカルポート>:<ターゲットIP>:<ターゲットポート>
例: ipf 8080:10.10.100.1:80 (外部アクセス8080を内部80へ)
<ローカルポート>:<ターゲットポート>
例: ipf 80:8080 (外部80をローカル8080へ)
<ポート番号>
例: ipf 22 (外部22をローカル22へ)
オプション:
-l, -L 現在の転送ルールを一覧表示 (引数なしのデフォルト)
-d <ID/PORT> 指定したハンドルIDまたは :ポート でルールを削除
例: ipf -d 12 / ipf -d :80
-d all すべてのルールを削除してテーブルを初期化
-t <IP:PORT> 指定したターゲットの接続性とプロトコルをテスト
-t <HANDLE> 既存ルールのハンドルIDを指定して疎通テストを実行
-R 設定リセット(テーブルを再作成)
-f, -y 確認なしで実行し、IPフォワーディングを強制有効化
-q クワイエットモード(メッセージ出力を抑制)
-h, --help この詳細ヘルプを表示
EOF
else
cat << EOF
ipf (IP Forwarder) - Simple nftables-based port forwarding manager
Usage:
ipf [OPTIONS] [RULE]
Rule Formats:
<LPORT>:<TIP>:<TPORT>
Ex: ipf 8080:10.10.100.1:80
<LPORT>:<TPORT>
Ex: ipf 80:8080
<PORT>
Ex: ipf 22
Options:
-l, -L List current rules
-d <ID/PORT> Delete rule by handle or :port
-d all Flush all rules
-t <IP:PORT> Test connectivity/protocol
-R Reset table
-h, --help Show this help
EOF
fi fi
} }
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# 4. Rule Management Functions # 4. Implementation Logic (List, Add, Delete)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
delete_by_handle() { delete_by_handle() {
local h=$1 local h=$1; local uuid=""
local uuid="" local chains=("prerouting" "output" "forward" "postrouting")
local search_chains=("prerouting" "output" "forward" "postrouting") for c in "${chains[@]}"; do
for sc in "${search_chains[@]}"; do uuid=$(nft -a list chain inet "${TABLE_NAME}" "$c" 2>/dev/null | grep "handle $h" | grep -o 'ipf-id:[a-z0-9-]*' | head -n 1)
uuid=$(nft -a list chain inet "${TABLE_NAME}" "$sc" 2>/dev/null | grep "handle $h" | grep -o 'ipf-id:[a-z0-9-]*' | head -n 1)
[[ -n "$uuid" ]] && break [[ -n "$uuid" ]] && break
done done
[[ -z "$uuid" ]] && return 1 [[ -z "$uuid" ]] && return 1
for c in "${search_chains[@]}"; do for c in "${chains[@]}"; do
nft -a list chain inet "${TABLE_NAME}" "$c" 2>/dev/null | grep "$uuid" | grep -o 'handle [0-9]*' | awk '{print $2}' | while read -r rh; do nft -a list chain inet "${TABLE_NAME}" "$c" 2>/dev/null | grep "$uuid" | grep -o 'handle [0-9]*' | awk '{print $2}' | while read -r rh; do
nft delete rule inet "${TABLE_NAME}" "$c" handle "$rh" nft delete rule inet "${TABLE_NAME}" "$c" handle "$rh"
done done
@ -136,32 +193,26 @@ delete_by_handle() {
test_strict_handle() { test_strict_handle() {
local h=$1 local h=$1
local info=$(nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "handle $h") local info=$(nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "handle $h")
[[ -z "$info" ]] && { err "Handle $h not found"; return; } [[ -z "$info" ]] && { err "$(printf "${MSGS[err_not_found]}" "$h")"; return; }
local lp=$(echo "$info" | grep -o 'dport [0-9]*' | awk '{print $2}') local lp=$(echo "$info" | grep -o 'dport [0-9]*' | awk '{print $2}')
local target=$(echo "$info" | grep -oE 'to ([0-9.]+|\[[0-9a-fA-F:]+\]):[0-9]+' | awk '{print $2}') local target=$(echo "$info" | grep -oE 'to ([0-9.]+|\[[0-9a-fA-F:]+\]):[0-9]+' | awk '{print $2}')
local tip=$(echo "$target" | cut -d':' -f1 | tr -d '[]') local tip=$(echo "$target" | cut -d':' -f1 | tr -d '[]')
local tp=$(echo "$target" | cut -d':' -f2) local tp=$(echo "$target" | cut -d':' -f2)
local uuid=$(echo "$info" | grep -o 'ipf-id:[a-z0-9-]*') local uuid=$(echo "$info" | grep -o 'ipf-id:[a-z0-9-]*')
local short_id=$(echo "$uuid" | cut -d':' -f2 | cut -c1-8) local short_id=$(echo "$uuid" | cut -d':' -f2 | cut -c1-8)
printf "${MSGS[testing]}" "$h" "$lp" "$tip" "$tp" "$short_id"
echo -n "Testing handle $h (Local :$lp -> Target $tip:$tp) [${short_id}]... " local count_before=$(nft list table inet "${TABLE_NAME}" 2>/dev/null | grep "$uuid" | grep -o 'packets [0-9]*' | awk '{sum+=$2} END {print sum+0}')
local count_before=$(get_total_packets "$uuid")
test_connection "$tip" "$tp" test_connection "$tip" "$tp"
nc -z -w 1 127.0.0.1 "$lp" >/dev/null 2>&1; sleep 0.1
nc -z -w 1 127.0.0.1 "$lp" >/dev/null 2>&1 local count_after=$(nft list table inet "${TABLE_NAME}" 2>/dev/null | grep "$uuid" | grep -o 'packets [0-9]*' | awk '{sum+=$2} END {print sum+0}')
sleep 0.1 if (( count_after > count_before )); then printf "${MSGS[passed]}\n" "$((count_after - count_before))"
local count_after=$(get_total_packets "$uuid") else printf "${MSGS[skipped]}\n"; fi
if (( count_after > count_before )); then
echo -e " \e[32mPASSED (Counter: +$((count_after - count_before)))\e[0m"
fi
} }
list_rules() { list_rules() {
[[ "$QUIET_MODE" == true ]] && return [[ "$QUIET_MODE" == true ]] && return
local highlight_uuid=$1 local highlight_uuid=$1; init_nft
init_nft msg "$(printf "${MSGS[rules_header]}" "${TABLE_NAME}")"
msg "Forwarding Rules (Table: ${TABLE_NAME}):"
printf "%-10s %-6s %-20s %-20s %-10s\n" "HANDLE" "PROTO" "LOCAL" "TARGET" "UUID" printf "%-10s %-6s %-20s %-20s %-10s\n" "HANDLE" "PROTO" "LOCAL" "TARGET" "UUID"
echo "-----------------------------------------------------------------------------------" echo "-----------------------------------------------------------------------------------"
nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "dnat" | while read -r line; do nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "dnat" | while read -r line; do
@ -172,15 +223,12 @@ list_rules() {
local full_uuid=$(echo "$line" | grep -o 'ipf-id:[a-z0-9-]*' | cut -d':' -f2) local full_uuid=$(echo "$line" | grep -o 'ipf-id:[a-z0-9-]*' | cut -d':' -f2)
if [[ -n "$highlight_uuid" && "$full_uuid" == "$highlight_uuid" ]]; then if [[ -n "$highlight_uuid" && "$full_uuid" == "$highlight_uuid" ]]; then
printf "\e[1;36m*%-9s %-6s %-20s %-20s %-10s\e[0m\n" "$handle" "$proto" ":$lport" "$target" "${full_uuid:0:8}" printf "\e[1;36m*%-9s %-6s %-20s %-20s %-10s\e[0m\n" "$handle" "$proto" ":$lport" "$target" "${full_uuid:0:8}"
else else printf " %-9s %-6s %-20s %-20s %-10s\n" "$handle" "$proto" ":$lport" "$target" "${full_uuid:0:8}"; fi
printf " %-9s %-6s %-20s %-20s %-10s\n" "$handle" "$proto" ":$lport" "$target" "${full_uuid:0:8}"
fi
done done
} }
add_rule() { add_rule() {
local raw=$1 local raw=$1; init_nft
init_nft
[[ "$FORCE_FLAG" == true ]] && enable_forwarding [[ "$FORCE_FLAG" == true ]] && enable_forwarding
if [[ "$raw" =~ ^([0-9]+):([0-9\.]+):([0-9]+)$ ]]; then if [[ "$raw" =~ ^([0-9]+):([0-9\.]+):([0-9]+)$ ]]; then
lp=${BASH_REMATCH[1]}; tip=${BASH_REMATCH[2]}; tp=${BASH_REMATCH[3]} lp=${BASH_REMATCH[1]}; tip=${BASH_REMATCH[2]}; tp=${BASH_REMATCH[3]}
@ -188,17 +236,10 @@ add_rule() {
lp=${BASH_REMATCH[1]}; tip="127.0.0.1"; tp=${BASH_REMATCH[2]} lp=${BASH_REMATCH[1]}; tip="127.0.0.1"; tp=${BASH_REMATCH[2]}
elif [[ "$raw" =~ ^([0-9]+)$ ]]; then elif [[ "$raw" =~ ^([0-9]+)$ ]]; then
lp=${BASH_REMATCH[1]}; tip="127.0.0.1"; tp=${BASH_REMATCH[1]} lp=${BASH_REMATCH[1]}; tip="127.0.0.1"; tp=${BASH_REMATCH[1]}
else else err "Invalid format: $raw"; return 1; fi
err "Error: Invalid rule format '$raw'"; return 1
fi
local conflicts=$(nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "dport $lp" | grep -o 'handle [0-9]*' | awk '{print $2}') local conflicts=$(nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "dport $lp" | grep -o 'handle [0-9]*' | awk '{print $2}')
for ch in $conflicts; do for ch in $conflicts; do msg "$(printf "${MSGS[overwrite]}" "$lp" "$ch")"; delete_by_handle "$ch"; done
msg "\e[33mOverwriting existing rule on port :$lp (Handle $ch)...\e[0m" local u_raw=$(cat /proc/sys/kernel/random/uuid); local u="ipf-id:$u_raw"; local fam="ip"; [[ "$tip" =~ : ]] && fam="ip6"
delete_by_handle "$ch"
done
local u_raw=$(cat /proc/sys/kernel/random/uuid)
local u="ipf-id:$u_raw"
local fam="ip"; [[ "$tip" =~ : ]] && fam="ip6"
nft insert rule inet "${TABLE_NAME}" prerouting "$PROTO" dport "$lp" counter dnat $fam to "$tip:$tp" comment "\"$u\"" nft insert rule inet "${TABLE_NAME}" prerouting "$PROTO" dport "$lp" counter dnat $fam to "$tip:$tp" comment "\"$u\""
nft insert rule inet "${TABLE_NAME}" output "$PROTO" dport "$lp" counter dnat $fam to "$tip:$tp" comment "\"$u\"" nft insert rule inet "${TABLE_NAME}" output "$PROTO" dport "$lp" counter dnat $fam to "$tip:$tp" comment "\"$u\""
nft insert rule inet "${TABLE_NAME}" forward $fam daddr "$tip" "$PROTO" dport "$tp" ct state new,established,related accept comment "\"$u\"" nft insert rule inet "${TABLE_NAME}" forward $fam daddr "$tip" "$PROTO" dport "$tp" ct state new,established,related accept comment "\"$u\""
@ -206,16 +247,12 @@ add_rule() {
nft insert rule inet "${TABLE_NAME}" forward iifname "lo" accept comment "\"$u\"" nft insert rule inet "${TABLE_NAME}" forward iifname "lo" accept comment "\"$u\""
nft insert rule inet "${TABLE_NAME}" postrouting $fam daddr "$tip" "$PROTO" dport "$tp" masquerade comment "\"$u\"" nft insert rule inet "${TABLE_NAME}" postrouting $fam daddr "$tip" "$PROTO" dport "$tp" masquerade comment "\"$u\""
list_rules "$u_raw" list_rules "$u_raw"
if [[ "$SKIP_TEST" == false && "$FORCE_FLAG" == false ]]; then [[ "$SKIP_TEST" == false ]] && { local nh=$(nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "$u_raw" | grep -o 'handle [0-9]*' | awk '{print $2}'); echo ""; test_strict_handle "$nh"; }
local nh=$(nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "$u_raw" | grep -o 'handle [0-9]*' | awk '{print $2}')
echo ""; test_strict_handle "$nh"
fi
} }
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# 5. Main Parsing Loop # 5. Main Loop
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
for arg in "$@"; do for arg in "$@"; do
case "$arg" in case "$arg" in
-q*) QUIET_MODE=true; FORCE_FLAG=true; SKIP_TEST=true ;; -q*) QUIET_MODE=true; FORCE_FLAG=true; SKIP_TEST=true ;;
@ -224,16 +261,20 @@ for arg in "$@"; do
esac esac
done done
[[ "$RESET_MODE" == true ]] && { nft delete table inet "${TABLE_NAME}" 2>/dev/null; init_nft; msg "Reset done."; list_rules; exit 0; } if [[ "$RESET_MODE" == true ]]; then
if [[ "$FORCE_FLAG" == false ]]; then
msg "$(printf "${MSGS[reset_warn]}" "${TABLE_NAME}")"
read -p "${MSGS[confirm]}" confirm
[[ ! "$confirm" =~ ^[yY]$ ]] && exit 0
fi
nft delete table inet "${TABLE_NAME}" 2>/dev/null; init_nft; msg "$(printf "${MSGS[reset_done]}" "${TABLE_NAME}")"; list_rules; exit 0
fi
[[ $# -eq 0 ]] && { list_rules; exit 0; } [[ $# -eq 0 ]] && { list_rules; exit 0; }
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
-h|--help) -h|--help) show_help; exit 0 ;;
echo "ipf version ${VERSION}"
echo "Usage: ipf [OPTIONS] [RULE]"
echo "Example: ipf 80:10.10.100.1:80"
exit 0 ;;
-v|--version) echo "ipf version ${VERSION}"; exit 0 ;; -v|--version) echo "ipf version ${VERSION}"; exit 0 ;;
-l|-L) list_rules; exit 0 ;; -l|-L) list_rules; exit 0 ;;
-f|-y|-q) [[ "$1" == "-f" ]] && enable_forwarding; shift; [[ $# -eq 0 ]] && exit 0; continue ;; -f|-y|-q) [[ "$1" == "-f" ]] && enable_forwarding; shift; [[ $# -eq 0 ]] && exit 0; continue ;;
@ -243,8 +284,7 @@ while [[ $# -gt 0 ]]; do
IFS=',' read -r -a parts <<< "$target" IFS=',' read -r -a parts <<< "$target"
for p in "${parts[@]}"; do for p in "${parts[@]}"; do
if [[ "$p" =~ ^:([0-9]+)$ ]]; then if [[ "$p" =~ ^:([0-9]+)$ ]]; then
ports=$(nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "dport ${BASH_REMATCH[1]}" | grep -o 'handle [0-9]*' | awk '{print $2}') for h in $(nft -a list chain inet "${TABLE_NAME}" prerouting 2>/dev/null | grep "dport ${BASH_REMATCH[1]}" | grep -o 'handle [0-9]*' | awk '{print $2}'); do delete_by_handle "$h"; done
for h in $ports; do delete_by_handle "$h"; done
else delete_by_handle "$p"; fi else delete_by_handle "$p"; fi
done done
list_rules; exit 0 ;; list_rules; exit 0 ;;
@ -254,12 +294,10 @@ while [[ $# -gt 0 ]]; do
echo -n "Target $target... "; test_connection "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" echo -n "Target $target... "; test_connection "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
elif [[ "$target" =~ ^:([0-9]+)$ ]]; then elif [[ "$target" =~ ^:([0-9]+)$ ]]; then
echo -n "Local $target... "; test_connection "127.0.0.1" "${BASH_REMATCH[1]}" echo -n "Local $target... "; test_connection "127.0.0.1" "${BASH_REMATCH[1]}"
else else test_strict_handle "$target"; fi
test_strict_handle "$target"
fi
exit 0 ;; exit 0 ;;
[0-9]*) add_rule "$1"; exit 0 ;; [0-9]*) add_rule "$1"; exit 0 ;;
*) err "Unknown option '$1'."; exit 1 ;; *) err "$(printf "${MSGS[unknown_opt]}" "$1")"; exit 1 ;;
esac esac
shift shift
done done