From 526f037bba9c450dfe3997a1d86013f9f5452f88 Mon Sep 17 00:00:00 2001 From: joe Date: Thu, 22 Jan 2026 11:51:01 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=B9=E3=82=A4=E3=83=83=E3=83=81BUG?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20=E4=BF=AE=E6=AD=A3=E5=BE=8C=E3=81=AE?= =?UTF-8?q?=E6=8C=99=E5=8B=95=20=20=20=20=20-t=20=E3=81=AE=E9=80=B2?= =?UTF-8?q?=E5=8C=96:=20=20=20=20=20=20=20=20=20=E3=83=AB=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=81=8C1=E3=81=A4=E3=81=AE=E5=A0=B4=E5=90=88:=20./ip?= =?UTF-8?q?fn=20-t=20=E3=81=A0=E3=81=91=E3=81=A7=E3=81=9D=E3=81=AE?= =?UTF-8?q?=E3=83=AB=E3=83=BC=E3=83=AB=E3=81=AE=E7=96=8E=E9=80=9A=E7=A2=BA?= =?UTF-8?q?=E8=AA=8D=E3=82=92=E3=81=97=E3=81=BE=E3=81=99=E3=80=82=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=E3=82=B9=E3=83=9A=E3=83=BC=E3=82=B9=E3=81=AA?= =?UTF-8?q?=E3=81=97:=20./ipfn=20-t17=20=E3=81=8C=E5=8B=95=E3=81=8D?= =?UTF-8?q?=E3=81=BE=E3=81=99=E3=80=82=20=20=20=20=20=E3=82=B9=E3=82=A4?= =?UTF-8?q?=E3=83=83=E3=83=81=E7=84=A1=E8=A6=96=E3=81=AE=E8=A7=A3=E6=B6=88?= =?UTF-8?q?:=20=20=20=20=20=20=20=20=20while=20=E3=83=AB=E3=83=BC=E3=83=97?= =?UTF-8?q?=E5=86=85=E3=81=AE=20shift=20=E5=87=A6=E7=90=86=E3=82=92?= =?UTF-8?q?=E8=A6=8B=E7=9B=B4=E3=81=97=E3=80=81-f=20=E3=82=92=E5=90=AB?= =?UTF-8?q?=E3=82=81=E3=81=9F=E3=82=AA=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E3=81=8C=E7=A2=BA=E5=AE=9F=E3=81=AB=E8=A9=95=E4=BE=A1=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=BE?= =?UTF-8?q?=E3=81=97=E3=81=9F=E3=80=82=20=20=20=20=20=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E6=99=82=E3=81=AE=20-f:=20=20=20=20=20=20=20=20=20./ipfn=2080:?= =?UTF-8?q?10.0.0.1:80=20-f=20=E3=81=A8=E3=81=99=E3=82=8B=E3=81=A8?= =?UTF-8?q?=E3=80=81=E7=96=8E=E9=80=9A=E7=A2=BA=E8=AA=8D=E3=82=92=E3=82=B9?= =?UTF-8?q?=E3=82=AD=E3=83=83=E3=83=97=E3=81=97=E3=81=A6=E5=8D=B3=E5=BA=A7?= =?UTF-8?q?=E3=81=AB=E7=B5=82=E4=BA=86=E3=81=97=E3=81=BE=E3=81=99=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ipfn1.0 | 146 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 67 deletions(-) diff --git a/ipfn1.0 b/ipfn1.0 index 4633835..b536d74 100755 --- a/ipfn1.0 +++ b/ipfn1.0 @@ -1,8 +1,7 @@ #!/bin/bash # Name: ipfn -# Version: 1.0.9 +# Version: 1.1.0 # Date: 2026-01-22 -# Description: Supports range deletion (e.g., -d 80-85) and complex handle lists. if [ "$(id -u)" -ne 0 ]; then exec sudo "$0" "$@" @@ -41,99 +40,112 @@ list_rules() { done } -perform_delete() { - local handle=$1 - local rule_info=$(nft -a list chain inet ${TABLE_NAME} prerouting | grep "handle $handle") - [[ -z "$rule_info" ]] && return # 存在しないハンドルは静かにスルー - local uuid=$(echo "$rule_info" | grep -o 'ipf-id:[a-z0-9-]*' | head -n 1) - for chain in prerouting output forward postrouting; do - nft -a list chain inet ${TABLE_NAME} "$chain" | grep "$uuid" | grep -o 'handle [0-9]*' | awk '{print $2}' | while read -r h; do - nft delete rule inet ${TABLE_NAME} "$chain" handle "$h" - done - done - echo "ipfn: Handle $handle deleted." -} - -# --- メインパース部分の強化 --- -parse_handles() { - local input=$1 - local -a result=() - # カンマで分割 - IFS=',' read -r -a parts <<< "$input" - for part in "${parts[@]}"; do - if [[ "$part" =~ ^([0-9]+)-([0-9]+)$ ]]; then - # 範囲指定 (start-end) の処理 - start=${BASH_REMATCH[1]} - end=${BASH_REMATCH[2]} - for ((i=start; i<=end; i++)); do result+=("$i"); done - else - # 単一指定 - result+=("$part") - fi - done - echo "${result[@]}" -} - -# (add_rule, test_rule_by_port は前バージョンと同じ) test_rule_by_port() { local lp=$1 echo -n "Testing connectivity to :$lp... " - if nc -z -v -w 2 127.0.0.1 "$lp" 2>&1 | grep -E "succeeded|connected|open" >/dev/null; then + if nc -z -v -w 2 127.0.0.1 "$lp" 2>&1 | grep -iqE "succeeded|connected|open"; then echo -e "\e[32mOK\e[0m" else echo -e "\e[31mFAILED\e[0m" fi } +get_port_by_handle() { + local h=$1 + nft -a list chain inet ${TABLE_NAME} prerouting | grep "handle $h" | grep -o 'dport [0-9]*' | awk '{print $2}' +} + +parse_handles() { + local input=$1 + local -a result=() + IFS=',' read -r -a parts <<< "$input" + for part in "${parts[@]}"; do + if [[ "$part" =~ ^([0-9]+)-([0-9]+)$ ]]; then + for ((i=${BASH_REMATCH[1]}; i<=${BASH_REMATCH[2]}; i++)); do result+=("$i"); done + else + result+=("$part") + fi + done + echo "${result[@]}" +} + add_rule() { init_nft - local port_ip_port=$1 - local lp=$(echo "$port_ip_port" | cut -d':' -f1) - local tip=$(echo "$port_ip_port" | cut -d':' -f2) - local tp=$(echo "$port_ip_port" | cut -d':' -f3) - [[ -n "$lp" ]] && nft list chain inet ${TABLE_NAME} prerouting | grep -q "dport $lp" && echo -e "\e[33mWarning: Port :$lp is already in use.\e[0m" + local lp=$(echo "$1" | cut -d':' -f1) + local tip=$(echo "$1" | cut -d':' -f2) + local tp=$(echo "$1" | cut -d':' -f3) + nft list chain inet ${TABLE_NAME} prerouting | grep -q "dport $lp" && echo -e "\e[33mWarning: Port :$lp is already in use.\e[0m" local raw_uuid=$(cat /proc/sys/kernel/random/uuid) local uuid="ipf-id:$raw_uuid" - local comment="comment \"$uuid\"" local family="ip"; [[ "$tip" =~ : ]] && family="ip6" - nft add rule inet ${TABLE_NAME} prerouting "$PROTO" dport "$lp" dnat $family to "$tip:$tp" "$comment" - nft add rule inet ${TABLE_NAME} output "$PROTO" dport "$lp" dnat $family to "$tip:$tp" "$comment" - nft add rule inet ${TABLE_NAME} forward iifname "lo" accept "$comment" - nft add rule inet ${TABLE_NAME} forward $family daddr "$tip" "$PROTO" dport "$tp" ct state new,established,related accept "$comment" - nft add rule inet ${TABLE_NAME} forward $family saddr "$tip" "$PROTO" sport "$tp" ct state established,related accept "$comment" - nft add rule inet ${TABLE_NAME} postrouting $family daddr "$tip" "$PROTO" dport "$tp" masquerade "$comment" - echo "ipfn: Rule added."; echo ""; list_rules "$raw_uuid" + nft add rule inet ${TABLE_NAME} prerouting "$PROTO" dport "$lp" dnat $family to "$tip:$tp" comment "\"$uuid\"" + nft add rule inet ${TABLE_NAME} output "$PROTO" dport "$lp" dnat $family to "$tip:$tp" comment "\"$uuid\"" + nft add rule inet ${TABLE_NAME} forward iifname "lo" accept comment "\"$uuid\"" + nft add rule inet ${TABLE_NAME} forward $family daddr "$tip" "$PROTO" dport "$tp" ct state new,established,related accept comment "\"$uuid\"" + nft add rule inet ${TABLE_NAME} forward $family saddr "$tip" "$PROTO" sport "$tp" ct state established,related accept comment "\"$uuid\"" + nft add rule inet ${TABLE_NAME} postrouting $family daddr "$tip" "$PROTO" dport "$tp" masquerade comment "\"$uuid\"" + list_rules "$raw_uuid" [[ "$SKIP_TEST" == false ]] && { echo ""; test_rule_by_port "$lp"; } } -for arg in "$@"; do [[ "$arg" == "-f" ]] && FORCE_FLAG=true && SKIP_TEST=true; done +# --- メインロジック --- if [[ $# -eq 0 ]]; then list_rules; exit 0; fi +# フラグ先読み +for arg in "$@"; do + [[ "$arg" == "-f" ]] && FORCE_FLAG=true && SKIP_TEST=true +done + while [[ $# -gt 0 ]]; do case "$1" in -L|-l) list_rules; exit 0 ;; -df*|-d*) [[ "$1" == -df* ]] && FORCE_FLAG=true - raw_h="${1#-df}"; raw_h="${raw_h#-d}" - [[ -z "$raw_h" ]] && { raw_h="$2"; shift; } - - # 範囲指定を含むハンドルリストを解析 - handles=($(parse_handles "$raw_h")) - + h_str="${1#-df}"; h_str="${h_str#-d}" + [[ -z "$h_str" ]] && { h_str="$2"; shift; } + handles=($(parse_handles "$h_str")) if [[ "$FORCE_FLAG" == false ]]; then echo "Review handles to delete:" - for h in "${handles[@]}"; do - rule=$(nft -a list chain inet ${TABLE_NAME} prerouting | grep "handle $h") - [[ -n "$rule" ]] && echo " $rule" - done - echo -n "Delete these rules? (y/N): " - read -r confirm - [[ ! "$confirm" =~ ^[yY]$ ]] && { echo "Aborted."; exit 0; } + for h in "${handles[@]}"; do nft -a list table inet ${TABLE_NAME} | grep "handle $h" | sed 's/^/ /'; done + read -p "Delete these rules? (y/N): " confirm + [[ ! "$confirm" =~ ^[yY]$ ]] && exit 0 fi - for h in "${handles[@]}"; do perform_delete "$h"; done + for h in "${handles[@]}"; do + rule_info=$(nft -a list chain inet ${TABLE_NAME} prerouting | grep "handle $h") + [[ -z "$rule_info" ]] && continue + uuid=$(echo "$rule_info" | grep -o 'ipf-id:[a-z0-9-]*' | head -n 1) + for c in prerouting output forward postrouting; do + nft -a list chain inet ${TABLE_NAME} "$c" | grep "$uuid" | grep -o 'handle [0-9]*' | awk '{print $2}' | while read -r rh; do + nft delete rule inet ${TABLE_NAME} "$c" handle "$rh" + done + done + echo "Handle $h deleted." + done echo ""; list_rules; exit 0 ;; - -f) [[ $# -eq 1 ]] && { sysctl -w net.ipv4.ip_forward=1 >/dev/null; sysctl -w net.ipv4.conf.all.route_localnet=1 >/dev/null; echo "Kernel parameters updated."; exit 0; } ;; - *) [[ "$1" =~ ^[0-9]+: ]] && { add_rule "$1"; exit 0; } ;; + -t*) + h_str="${1#-t}" + if [[ -z "$h_str" && ( "$2" =~ ^[0-9,-]+$ ) ]]; then h_str="$2"; shift; fi + + if [[ -z "$h_str" ]]; then + # ハンドル指定がない場合、ルールが1つならそれを採用 + count=$(nft list chain inet ${TABLE_NAME} prerouting | grep -c "dnat") + if [ "$count" -eq 1 ]; then + h_str=$(nft -a list chain inet ${TABLE_NAME} prerouting | grep "handle" | awk '{print $NF}') + else + echo "Error: Multiple rules exist. Specify a handle."; exit 1 + fi + fi + lp=$(get_port_by_handle "$h_str") + [[ -n "$lp" ]] && test_rule_by_port "$lp" || echo "Error: Handle $h_str not found." + exit 0 ;; + -f) + if [[ $# -eq 1 ]]; then + sysctl -w net.ipv4.ip_forward=1 >/dev/null + sysctl -w net.ipv4.conf.all.route_localnet=1 >/dev/null + echo "Kernel parameters updated."; exit 0 + fi ;; + *) + if [[ "$1" =~ ^[0-9]+: ]]; then add_rule "$1"; exit 0; fi ;; esac shift done