fail2ban対策

This commit is contained in:
joe 2026-03-05 21:37:53 +09:00
parent 4109595fe3
commit fef485c6d4
2 changed files with 194 additions and 66 deletions

125
README.md
View file

@ -1,51 +1,108 @@
このプロジェクトは、nftablesのルールを編集するためのスクリプトです。以下が使用方法とライセンス情報です。 # ipf - nftables ベースのポートフォワーディング管理ツール
完全機能な IP フォワーダーで、マルチプロトコル検出SSH/HTTP/HTTPS など)、日本語・英語ローカリゼーションに対応。
--- ---
### 概要 ## 概要
このツールは、`nftables`のルールを編集する際のスクリプトです `nftables` のルールを編集するスクリプトです。IP フォワーディングを管理し、fail2ban などのセキュリティツールと整合した設定を実現
--- ---
### 使用方法 ## セキュリティポリシー: fail2ban 対策
**ルールの編集**
```bash
使用法:
ipf [オプション] [ルール]
ルール形式: ipf は転送先のセキュリティfail2ban など)との整合性を考慮した設計をしていませんが、以下のように実装可能です。
<ローカルポート>:<ターゲットIP>:<ターゲットポート>
例: ipf 8080:10.10.100.1:80 (外部アクセス8080を内部80へ)
<ローカルポート>:<ターゲットポート> ### 環境別挙動比較表
例: ipf 80:8080 (外部80をローカル8080へ)
<ポート番号> | 環境 | デフォルト動作 | SNAT モード (`-F` オプション) | fail2ban 推奨設定 |
例: ipf 22 (外部22をローカル22へ) |------|---------------|-------------------------------|------------------|
| **リアルマシン/VM** | MASQUERADEホスト IP で中継) | ✅ SNAT でクライアント IP 保持 | `-F` を使用 |
| **コンテナ環境** | MASQUERADEホスト IP で中継) | ⚠️ スタンダードな動作 | デフォルトで OK |
オプション: ### SNAT と MASQUERADE の違い
-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 この詳細ヘルプを表示
```
```bash
# MASQUERADE: ホスト IP に置換(シンプル)
nft insert rule inet ipf postrouting daddr "$tip" ... masquerade comment "simple"
# SNAT (orig): クライアント IP を保持fail2ban 対応)
nft insert rule inet ipf postrouting daddr "$tip" ... snat to type nat orig comment "client-ip"
```
#### 各手法のメリット・デメリット
| 手法 | メリット | デメリット |
|------|----------|-----------|
| **MASQUERADE**(デフォルト) | シンプル、パフォーマンス良好 | fail2ban でクライアント IP を正しく検出できない |
| **SNAT (orig)** (`-F` オプション) | fail2ban と整合し、クライアント IP が保持される | スケジューリング処理が発生し、少し遅い(現代の CPU では差は微々たるもの) |
--- ---
### ライセンス ## 使用方法
**基本コマンド:**
```bash
# ポート転送ルールを追加(例:外部 8080 を内部 80 へ)
ipf 8080:10.10.100.1:80
# 失敗のリスクを減らすため、デフォルトでは MASQUERADE を使用します
```
**ルール形式:**
- `<ローカルポート>:<ターゲット IP>:<ターゲットポート>`
例:`ipf 8080:10.10.100.1:80`(外部アクセス 8080 を内部 80 へ)
- `<ローカルポート>:<ターゲットポート>`
例:`ipf 80:8080`(外部 80 をローカル 8080 へ、ターゲットは 127.0.0.1
- `<ポート番号>`
例:`ipf 22`(外部 22 をローカル 22 へ、ターゲットは 127.0.0.1
---
## オプション
| オプション | 説明 | 例 |
|-----------|------|-----|
| `-l, -L` | 現在の転送ルールを一覧表示 | `ipf -l` |
| `-d <ID/PORT>` | 指定したハンドル ID または : ポートでルールを削除 | `ipf -d 12` / `ipf -d :80` |
| `-d all` | すべてのルールを削除してテーブルを初期化 | `ipf -d all` |
| `-t <IP:PORT>` | 指定したターゲットの接続性とプロトコルをテスト | `ipf -t 10.10.100.1:80` |
| `-t <HANDLE>` | 既存ルールのハンドル ID を指定して疎通テストを実行 | `ipf -t 12345678` |
| `-u` | UDP プロトコルを使用(デフォルトは TCP<br>ルール追加時:`ipf -u 5353:10.0.0.1:53`<br>テスト時:`ipf -u -t 10.0.0.1:53` | `ipf -u 5353:10.0.0.1:53` |
| `-R` | 設定リセット(テーブルを再作成) | `ipf -R` |
| `-f, -y` | 確認なしで実行し、IP フォワーディングを強制有効化 | `ipf -f` |
| `-q` | クワイエットモード(メッセージ出力を抑制) | `ipf -q` |
| `-h, --help` | この詳細ヘルプを表示 | `ipf -h` |
---
## セキュリティへの配慮
### fail2ban との整合性
転送先に fail2ban が稼働している場合、`masquerade` を使用するとクライアント IP がログされません。以下の方法で回避します:
1. **デフォルト設定MASQUERADE**: シンプルで無難
2. **`-F` オプション**: クライアント IP を保持し、fail2ban と整合させる
**失敗のリスク低減のため、デフォルトでは MASQUERADE を使用します。**
### 注意事項
- ipf は fail2ban のログを正しく生成することを前提としていません。
- SNAT モード(`-F` オプション)を使用する場合のみ、クライアント IP が保持されます。
- コンテナ環境では、MASQUERADE で動作することを確認してください。
---
## 補足
このスクリプトは `qwen3/gpt-oss/gemini-2.5-pro``krasherjoe` によって作成されました。
---
## ライセンス
MIT License に基づくライセンスです。 MIT License に基づくライセンスです。
**権利者**: krasherjoe **権利者**: krasherjoe
**日付**: 2026-01-22 **日付**: 2026-01-22
---
### 補足
このスクリプトは、`qwen3/gpt-oss/gemini-2.5-pro`と`krasherjoe`によって作成されました。
AIにリファクタさせたら原型を留めないのが良いのか悪いのか謎。

127
ipf
View file

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Name: ipf # Name: ipf
# Version: 1.6.9 # Version: 1.7.0
# Date: 2026-02-04 # Date: 2026-03-05
# Description: Fully featured port forwarder with rich help, multi-protocol # Description: Fully featured port forwarder with rich help, multi-protocol
# detection (SSH/HTTP/HTTPS/etc.), and JP/EN localization. # detection (SSH/HTTP/HTTPS/etc.), and JP/EN localization.
@ -14,18 +14,20 @@ declare -A MSGS
if [[ "$SYSTEM_LANG" == "ja" ]]; then if [[ "$SYSTEM_LANG" == "ja" ]]; then
MSGS=( MSGS=(
[system]="\e[34m[システム]\e[0m" [system]="\e[34m[システム]\e[0m"
[enabling_fwd]="IPフォワーディングを有効化しています..." [enabling_fwd]="IP フォワーディングを有効化しています..."
[err_fwd]="致命的: net.ipv4.ip_forward を有効にできませんでした。" [err_fwd]="致命的net.ipv4.ip_forward を有効にできませんでした。"
[rules_header]="転送ルール一覧 (テーブル: %s):" [rules_header]="転送ルール一覧 (テーブル%s):"
[overwrite]="\e[33mポート :%s (ハンドル %s) の既存ルールを上書きします...\e[0m" [overwrite]="\e[33mポート :%s (ハンドル %s) の既存ルールを上書きします...\e[0m"
[reset_warn]="\e[33m警告: テーブル '%s' 内の全ルールが削除されます。\e[0m" [reset_warn]="\e[33m警告テーブル '%s' 内の全ルールが削除されます。\e[0m"
[confirm]="削除を確認しますか? (y/N): " [confirm]="削除を確認しますか?(y/N): "
[reset_done]="テーブル '%s' をリセットしました。" [reset_done]="テーブル '%s' をリセットしました。"
[testing]="ハンドル %s をテスト中 (Local :%s -> Target %s:%s) [%s]... " [testing]="ハンドル %s をテスト中 (Local :%s -> Target %s:%s) [%s]... "
[passed]=" \e[32m成功 (パケット増分: +%s)\e[0m" [passed]=" \e[32m成功 (パケット増分 +%s)\e[0m"
[skipped]=" \e[33mスキップ (疎通なし、またはシャドウイングの可能性)\e[0m" [skipped]=" \e[33mスキップ (疎通なし、またはシャドウイングの可能性)\e[0m"
[err_not_found]="ハンドル %s が見つかりません。" [err_not_found]="ハンドル %s が見つかりません。"
[unknown_opt]="不明なオプション '%s' です。-h でヘルプを表示してください。" [unknown_opt]="不明なオプション '%s' です。-h でヘルプを表示してください。"
[nat_mode]="\e[32mSNAT モード (fail2ban 対応)\e[0m"
[masq_mode]="\e[33mMASQUERADE モード (シンプル)\e[0m"
) )
else else
MSGS=( MSGS=(
@ -42,6 +44,8 @@ else
[skipped]=" \e[33mSKIPPED (No traffic or shadowed)\e[0m" [skipped]=" \e[33mSKIPPED (No traffic or shadowed)\e[0m"
[err_not_found]="Handle %s not found." [err_not_found]="Handle %s not found."
[unknown_opt]="Unknown option '%s'. Use -h for help." [unknown_opt]="Unknown option '%s'. Use -h for help."
[nat_mode]="\e[32mSNAT mode (fail2ban compatible)\e[0m"
[masq_mode]="\e[33mMASQUERADE mode (simple)\e[0m"
) )
fi fi
@ -53,12 +57,13 @@ if [ "$(id -u)" -ne 0 ]; then
fi fi
TABLE_NAME="ipf" TABLE_NAME="ipf"
VERSION="1.6.9" VERSION="1.7.0"
PROTO="tcp" PROTO="tcp"
FORCE_FLAG=false FORCE_FLAG=false
SKIP_TEST=false SKIP_TEST=false
QUIET_MODE=false QUIET_MODE=false
RESET_MODE=false RESET_MODE=false
SNAT_FLAG=false
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# 3. Core Functions # 3. Core Functions
@ -84,7 +89,18 @@ init_nft() {
} }
test_connection() { test_connection() {
local host=$1; local port=$2; local info="" local host=$1; local port=$2; local proto=${3:-$PROTO}; local info=""
# UDP mode: use nc -zu for connectivity check
if [[ "$proto" == "udp" ]]; then
if nc -zu -w 1 "$host" "$port" >/dev/null 2>&1; then
echo -e "\e[32mUP\e[0m (UDP)"
return 0
else
echo -e "\e[31mDOWN\e[0m (UDP)"
return 1
fi
fi
# A. Protocol Banner Check (SSH, FTP, etc.) # A. Protocol Banner Check (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')
@ -109,7 +125,7 @@ test_connection() {
local url="${sch}://${host}:${port}" local url="${sch}://${host}:${port}"
local res=$(curl -sLk -m 3 -A "Mozilla/5.0 ipf-tester" "${url}/api/tags" 2>/dev/null) local res=$(curl -sLk -m 3 -A "Mozilla/5.0 ipf-tester" "${url}/api/tags" 2>/dev/null)
# Ollama API 判定 (JSONに "models" が含まれているか) # Ollama API 判定 (JSON に "models" が含まれているか)
if [[ "$res" == *"models"* ]]; then if [[ "$res" == *"models"* ]]; then
info=" (Ollama API)" info=" (Ollama API)"
echo -e "\e[32mUP\e[0m${info}" echo -e "\e[32mUP\e[0m${info}"
@ -125,7 +141,7 @@ test_connection() {
return 0 return 0
fi fi
# 通常のHTTP/HTTPSステータス判定 # 通常の HTTP/HTTPS ステータス判定
local code=$(curl -IsLk -m 2 -o /dev/null -w "%{http_code}" "${url}/" 2>/dev/null) local code=$(curl -IsLk -m 2 -o /dev/null -w "%{http_code}" "${url}/" 2>/dev/null)
[[ "$code" == "000" ]] && code=$(curl -sLk -m 2 -o /dev/null -w "%{http_code}" "${url}/" 2>/dev/null) [[ "$code" == "000" ]] && code=$(curl -sLk -m 2 -o /dev/null -w "%{http_code}" "${url}/" 2>/dev/null)
@ -146,32 +162,47 @@ test_connection() {
show_help() { show_help() {
if [[ "$SYSTEM_LANG" == "ja" ]]; then if [[ "$SYSTEM_LANG" == "ja" ]]; then
cat << EOF cat << EOF
ipf (IP Forwarder) - nftablesベースの簡易ポート転送管理ツール ipf (IP Forwarder) - nftables ベースのポート転送管理ツール
使用法: 使用法:
ipf [オプション] [ルール] ipf [オプション] [ルール]
ルール形式: ルール形式:
<ローカルポート>:<ターゲットIP>:<ターゲットポート> <ローカルポート>:<ターゲット IP>:<ターゲットポート>
: ipf 8080:10.10.100.1:80 (外部アクセス8080を内部80へ) ipf 8080:10.10.100.1:80 (外部アクセス 8080 を内部 80 へ)
<ローカルポート>:<ターゲットポート> <ローカルポート>:<ターゲットポート>
: ipf 80:8080 (外部80をローカル8080へ) ipf 80:8080 (外部 80 をローカル 8080 へ)
<ポート番号> <ポート番号>
: ipf 22 (外部22をローカル22へ) ipf 22 (外部 22 をローカル 22 へ)
オプション: オプション:
-l, -L 現在の転送ルールを一覧表示 (引数なしのデフォルト) -l, -L 現在の転送ルールを一覧表示 (引数なしのデフォルト)
-d <ID/PORT> 指定したハンドルIDまたは :ポート でルールを削除 -d <ID/PORT> 指定したハンドル ID または : ポート でルールを削除
: ipf -d 12 / ipf -d :80 ipf -d 12 / ipf -d :80
-d all すべてのルールを削除してテーブルを初期化 -d all すべてのルールを削除してテーブルを初期化
-t <IP:PORT> 指定したターゲットの接続性とプロトコルをテスト -t <IP:PORT> 指定したターゲットの接続性とプロトコルをテスト
-t <HANDLE> 既存ルールのハンドルIDを指定して疎通テストを実行 -t <HANDLE> 既存ルールのハンドル ID を指定して疎通テストを実行
-R 設定リセット(テーブルを再作成) -u UDP プロトコルを使用 (デフォルトは TCP)
-f, -y 確認なしで実行し、IPフォワーディングを強制有効化 ルール追加時ipf -u 5353:10.0.0.1:53
-q クワイエットモード(メッセージ出力を抑制) テスト時: ipf -u -t 10.0.0.1:53
-R 設定リセット (テーブルを再作成)
-f, -y 確認なしで実行し、IP フォワーディングを強制有効化
-q クワイエットモード (メッセージ出力を抑制)
-F SNAT モード (fail2ban と整合): snat to type nat orig
ipf -F 8080:10.10.100.1:80
-h, --help この詳細ヘルプを表示 -h, --help この詳細ヘルプを表示
セキュリティポリシー:
デフォルトは MASQUERADE モード (シンプル、無難) です。
fail2ban と整合させるには -F オプションを使用します。
SNAT モードの特徴:
- クライアント IP がログされる
- fail2ban が正しく動作する
- パフォーマンスは MASQUERADE よりわずかに低速
EOF EOF
else else
cat << EOF cat << EOF
@ -195,8 +226,25 @@ Options:
-d <ID/PORT> Delete rule by handle or :port -d <ID/PORT> Delete rule by handle or :port
-d all Flush all rules -d all Flush all rules
-t <IP:PORT> Test connectivity/protocol -t <IP:PORT> Test connectivity/protocol
-u Use UDP protocol (default: TCP)
Add rule: ipf -u 5353:10.0.0.1:53
Test: ipf -u -t 10.0.0.1:53
-R Reset table -R Reset table
-f, -y Force enable forwarding
-q Quiet mode (suppress output)
-F SNAT mode (fail2ban compatible): snat to type nat orig
Ex: ipf -F 8080:10.10.100.1:80
-h, --help Show this help -h, --help Show this help
Security Policy:
Default is MASQUERADE mode (simple, safe).
Use -F option for fail2ban compatibility.
SNAT Mode Features:
- Client IP is logged
- fail2ban works correctly
- Slightly slower than MASQUERADE
EOF EOF
fi fi
} }
@ -231,10 +279,14 @@ test_strict_handle() {
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)
# ルールからプロトコルを検出 (明示的に -u 指定がなければルール自体から判定)
local rule_proto=$PROTO
echo "$info" | grep -q "udp" && rule_proto="udp"
printf "${MSGS[testing]}" "$h" "$lp" "$tip" "$tp" "$short_id" printf "${MSGS[testing]}" "$h" "$lp" "$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=$(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 "$tip" "$tp" test_connection "$tip" "$tp" "$rule_proto"
nc -z -w 1 127.0.0.1 "$lp" >/dev/null 2>&1; sleep 0.1 local nc_opt="-z"; [[ "$rule_proto" == "udp" ]] && nc_opt="-zu"
nc $nc_opt -w 1 127.0.0.1 "$lp" >/dev/null 2>&1; sleep 0.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}') 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}')
if (( count_after > count_before )); then printf "${MSGS[passed]}\n" "$((count_after - count_before))" if (( count_after > count_before )); then printf "${MSGS[passed]}\n" "$((count_after - count_before))"
else printf "${MSGS[skipped]}\n"; fi else printf "${MSGS[skipped]}\n"; fi
@ -261,6 +313,7 @@ list_rules() {
add_rule() { add_rule() {
local raw=$1; init_nft local raw=$1; 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]}
elif [[ "$raw" =~ ^([0-9]+):([0-9]+)$ ]]; then elif [[ "$raw" =~ ^([0-9]+):([0-9]+)$ ]]; then
@ -268,15 +321,29 @@ add_rule() {
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 err "Invalid format: $raw"; return 1; fi else err "Invalid 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 msg "$(printf "${MSGS[overwrite]}" "$lp" "$ch")"; delete_by_handle "$ch"; done for ch in $conflicts; do msg "$(printf "${MSGS[overwrite]}" "$lp" "$ch")"; 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" 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\""
nft insert rule inet "${TABLE_NAME}" forward $fam saddr "$tip" "$PROTO" sport "$tp" ct state established,related accept comment "\"$u\"" nft insert rule inet "${TABLE_NAME}" forward $fam saddr "$tip" "$PROTO" sport "$tp" ct state established,related accept comment "\"$u\""
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\""
# ポストルートイングSNAT モードか MASQUERADE モードかで分岐
if [[ "$SNAT_FLAG" == true ]]; then
msg "$(printf "${MSGS[nat_mode]}")"
nft insert rule inet "${TABLE_NAME}" postrouting $fam daddr "$tip" "$PROTO" dport "$tp" \
counter snat to type nat orig comment "\"$u\""
else
msg "$(printf "${MSGS[masq_mode]}")"
nft insert rule inet "${TABLE_NAME}" postrouting $fam daddr "$tip" "$PROTO" dport "$tp" \
masquerade comment "\"$u\""
fi
list_rules "$u_raw" list_rules "$u_raw"
[[ "$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"; } [[ "$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"; }
} }
@ -288,6 +355,8 @@ 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 ;;
-f*|-y*) FORCE_FLAG=true; SKIP_TEST=true ;; -f*|-y*) FORCE_FLAG=true; SKIP_TEST=true ;;
-F*) SNAT_FLAG=true; SKIP_TEST=true ;;
-u) PROTO="udp" ;;
-R) RESET_MODE=true ;; -R) RESET_MODE=true ;;
esac esac
done done
@ -308,7 +377,9 @@ while [[ $# -gt 0 ]]; do
-h|--help) show_help; exit 0 ;; -h|--help) show_help; 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 ;;
-u) shift; [[ $# -eq 0 ]] && exit 0; continue ;;
-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 ;;
-F*) enable_forwarding; shift; [[ $# -eq 0 ]] && exit 0; continue ;;
-*[d]*) -*[d]*)
target="${1#-d}"; [[ -z "$target" ]] && { target="$2"; shift; } target="${1#-d}"; [[ -z "$target" ]] && { target="$2"; shift; }
[[ "$target" == "all" ]] && { nft delete table inet "${TABLE_NAME}" 2>/dev/null; init_nft; list_rules; exit 0; } [[ "$target" == "all" ]] && { nft delete table inet "${TABLE_NAME}" 2>/dev/null; init_nft; list_rules; exit 0; }
@ -322,9 +393,9 @@ while [[ $# -gt 0 ]]; do
-t*) -t*)
target="${1#-t}"; [[ -z "$target" ]] && { target="$2"; shift; } target="${1#-t}"; [[ -z "$target" ]] && { target="$2"; shift; }
if [[ "$target" =~ ^([0-9\.]+):([0-9]+)$ ]]; then if [[ "$target" =~ ^([0-9\.]+):([0-9]+)$ ]]; then
echo -n "Target $target... "; test_connection "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" echo -n "Target $target [$PROTO]... "; test_connection "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "$PROTO"
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 [$PROTO]... "; test_connection "127.0.0.1" "${BASH_REMATCH[1]}" "$PROTO"
else test_strict_handle "$target"; fi else test_strict_handle "$target"; fi
exit 0 ;; exit 0 ;;
[0-9]*) add_rule "$1"; exit 0 ;; [0-9]*) add_rule "$1"; exit 0 ;;