fail2ban対策
This commit is contained in:
parent
4109595fe3
commit
fef485c6d4
2 changed files with 194 additions and 66 deletions
127
README.md
127
README.md
|
|
@ -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にリファクタさせたら原型を留めないのが良いのか悪いのか謎。
|
|
||||||
133
ipf
133
ipf
|
|
@ -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
|
||||||
-h, --help この詳細ヘルプを表示
|
-R 設定リセット (テーブルを再作成)
|
||||||
|
-f, -y 確認なしで実行し、IP フォワーディングを強制有効化
|
||||||
|
-q クワイエットモード (メッセージ出力を抑制)
|
||||||
|
-F SNAT モード (fail2ban と整合): snat to type nat orig
|
||||||
|
例:ipf -F 8080:10.10.100.1:80
|
||||||
|
-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
|
||||||
-h, --help Show this help
|
-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
|
||||||
|
|
||||||
|
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,13 +393,13 @@ 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 ;;
|
||||||
*) err "$(printf "${MSGS[unknown_opt]}" "$1")"; exit 1 ;;
|
*) err "$(printf "${MSGS[unknown_opt]}" "$1")"; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
Loading…
Reference in a new issue