# 機能設計書 43-IPFilter

## 概要

本ドキュメントは、FreeBSDにおけるIPFilter（IPF）パケットフィルタリング・NAT機能の設計について記述する。IPFilterはDarren Reed氏が開発したクロスプラットフォームのパケットフィルタであり、ステートフルインスペクション、NAT、プロキシサポートを提供する。

### 本機能の処理概要

IPFilterはカーネル内でパケットフィルタリングとNATを行う機構で、ipf/ipnat/ippool/ipmon等のユーザ空間ツール群で管理される。

**業務上の目的・背景**：IPFilterはBSD系・Solaris等で広く使われてきた歴史あるパケットフィルタであり、FreeBSDでは3番目のファイアウォールオプションとして提供されている。既存のIPFilter設定を持つシステムからの移行や、IPFilter固有の機能を活用したい場合に利用される。

**機能の利用シーン**：ステートフルパケットフィルタリングの設定、NAT（Network Address Translation）の構成、IPプールによるアドレスグループ管理、ipmonによるリアルタイムログ監視、ipfstatによる統計情報の確認に使用される。

**主要な処理内容**：
1. パケットフィルタルールの読み込みと適用（ipf -f /etc/ipf.rules）
2. NATルールの読み込みと適用（ipnat -f /etc/ipnat.rules）
3. IPプール（アドレスプール/ハッシュプール）の管理（ippool）
4. フィルタリング統計の表示（ipfstat）
5. 状態テーブルの管理（ipf -s / ipf -F）
6. リアルタイムログ監視（ipmon）
7. NATテーブルの表示・フラッシュ（ipnat -l / ipnat -F）
8. 状態同期（ipfsync）
9. テスト用パケット生成（ipftest/ipsend/ipresend）

**関連システム・外部連携**：pfilフレームワーク経由でカーネルネットワークスタックに接続。pfil_hookで入出力パケットをフィルタリングする。

**権限による制御**：ipf/ipnat等のコマンド実行にはroot権限が必要。/dev/ipfデバイスへのアクセス権限による制御。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （CLIベースのためGUI画面なし） | - | ipf/ipnat/ippool/ipmon/ipfstatコマンドによる操作 |

## 機能種別

パケットフィルタリング / NAT変換 / ルール管理（CRUD操作） / 状態追跡

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| rules_file | string | No | フィルタルールファイル（ipf.rules） | 読み取り可能なファイル |
| nat_file | string | No | NATルールファイル（ipnat.rules） | 読み取り可能なファイル |
| pool_file | string | No | IPプール定義ファイル | 読み取り可能なファイル |
| command | string | Yes | 操作コマンド（-f/-F/-s/-l等） | 有効なコマンドオプション |

### 入力データソース

- ipf.rulesフィルタルールファイル
- ipnat.rules NATルールファイル
- ippool.confプール定義ファイル
- コマンドライン引数
- /dev/ipf, /dev/ipnat, /dev/ipstate等のデバイスファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| filter_rules | text | フィルタルール一覧 |
| nat_rules | text | NATルール一覧 |
| statistics | text | パケットカウンタ・統計情報 |
| state_table | text | 接続状態テーブル |
| log_entries | text | リアルタイムフィルタログ |

### 出力先

- 標準出力（各コマンドの実行結果）
- カーネルルールテーブル
- /dev/ipl（ログデバイス）
- syslog（ipmon経由）

## 処理フロー

### 処理シーケンス

```
1. ルールファイル読み込み（ipf -f rules_file）
   └─ ルール構文のパース、バイナリ形式への変換
2. カーネルへのルール適用
   └─ ioctl経由でフィルタルールをカーネルに投入
3. NATルール適用（ipnat -f nat_file）
   └─ NATルール構文のパース、カーネルNATテーブルに投入
4. パケットフィルタリング（カーネル内）
   └─ pfilフック経由でパケットをルールチェーンと照合
5. 状態テーブル管理
   └─ keep state指定のルールで新規接続状態を作成
6. NAT処理
   └─ NATルールに基づくアドレス/ポート変換
```

### フローチャート

```mermaid
flowchart TD
    A[パケット受信] --> B[pfil フック]
    B --> C{状態テーブル照合}
    C -->|既存接続| D[状態に基づく処理]
    C -->|新規| E[フィルタルール評価]
    E --> F{マッチ?}
    F -->|pass| G[パケット通過]
    F -->|block| H[パケット破棄]
    G --> I{NAT必要?}
    I -->|Yes| J[NAT変換]
    I -->|No| K[パケット転送]
    J --> K
    D --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-43-01 | first-match評価 | IPFilterはデフォルトでfirst-match（最初にマッチしたルールが適用）だが、quickキーワードなしの場合はlast-match | ルール評価時 |
| BR-43-02 | グループ機能 | ルールをグループ化して効率的な評価を行える | group/head指定時 |
| BR-43-03 | ルール方向指定 | in/outの方向指定が必須 | ルール定義時 |

### 計算ロジック

- NATアドレスプール：ラウンドロビンまたはソースハッシュによるNATアドレス選択
- IPプールのルックアップ：ハッシュテーブルまたは基数木による効率的検索

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを使用しない。カーネル内のフィルタルールチェーン・NATテーブル・状態テーブルを操作する。

| 操作 | 対象データ構造 | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ipf -f | filter rules | INSERT | フィルタルール追加 |
| ipnat -f | NAT rules | INSERT | NATルール追加 |
| ipf -F | filter rules/states | DELETE | ルール・状態フラッシュ |
| ipfstat | statistics | SELECT | 統計情報取得 |

### テーブル別操作詳細

#### frentry（フィルタルール）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| INSERT | fr_flags, fr_proto, fr_src, fr_dst | ルールファイルのパース結果 | in/outチェーンに個別挿入 |
| DELETE | 全エントリ | フラッシュ操作時 | ルール番号指定削除も可 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EACCES | 権限エラー | root以外での操作 | root権限で実行 |
| ENOENT | デバイス未検出 | IPFilterモジュール未ロード | kldload ipl |
| EINVAL | 構文エラー | ルールファイルの構文不正 | 構文を修正 |
| EEXIST | 重複エラー | 同一ルールの重複登録 | 既存ルールを確認 |

### リトライ仕様

ルール適用はioctl単位で行われ、個別のルール登録失敗時はエラーメッセージを出力して次のルールの処理を続行する。

## トランザクション仕様

IPFilterのルール更新は個別のioctl操作で行われる。ルールファイルの一括適用時も1ルールずつ投入されるため、途中失敗時は部分的な適用状態となる可能性がある。flushしてから適用することで一貫性を確保する運用が一般的。

## パフォーマンス要件

- 状態テーブルルックアップはハッシュテーブルによるO(1)
- ルール評価はグループ機能により効率化可能
- IPプールのルックアップはハッシュまたは基数木

## セキュリティ考慮事項

- /dev/ipf等のデバイスファイルのパーミッション管理
- ルールファイルの適切なパーミッション設定
- ipmonのログ出力先のセキュリティ確保
- NAT設定の不備による内部ネットワーク露出リスク

## 備考

- IPFilterはDarren Reed氏が開発し、複数のOS（FreeBSD, NetBSD, Solaris等）で利用可能
- FreeBSDではIPFW, PFと並ぶ3番目のファイアウォールオプション
- ライブラリ形式（libipf）でIPFilter機能を他のプログラムから利用可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

IPFilterのルール構造体とNAT構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ip_fil.h | `sys/netpfil/ipfilter/netinet/ip_fil.h` | frentry構造体（フィルタルール）、fr_info構造体（パケット情報）の定義を把握する |
| 1-2 | ip_nat.h | `sys/netpfil/ipfilter/netinet/ip_nat.h` | NAT関連構造体の定義を理解する |

**読解のコツ**: IPFilterのソースはsys/netpfil/ipfilter/netinet/配下に集約されている。構造体名はfr_（フィルタルール）、nat_（NAT）、ips_（状態）のプレフィックスで分類される。

#### Step 2: ユーザ空間コマンドを理解する

主要なコマンドのエントリーポイントを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ipf.c | `sbin/ipf/ipf/ipf.c` | ipfコマンドのmain()関数。ルールファイル読み込み、フラッシュ、状態管理の分岐を理解する |
| 2-2 | ipnat.c | `sbin/ipf/ipnat/ipnat.c` | ipnatコマンドのmain()関数。NATルール管理の流れを理解する |
| 2-3 | ipfstat.c | `sbin/ipf/ipfstat/ipfstat.c` | ipfstatコマンド。統計情報取得の処理を理解する |
| 2-4 | ipmon.c | `sbin/ipf/ipmon/ipmon.c` | ipmonデーモン。リアルタイムログ監視の処理を理解する |

#### Step 3: ライブラリ層を理解する

共通ライブラリ関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | libipf/ | `sbin/ipf/libipf/` | ルールパーサー、出力フォーマッタ等の共通関数群 |

#### Step 4: カーネル処理を理解する

カーネル内のパケットフィルタリング処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ip_fil_freebsd.c | `sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c` | FreeBSD固有のカーネル統合部分。pfilフック登録処理 |
| 4-2 | fil.c | `sys/netpfil/ipfilter/netinet/fil.c` | フィルタリングエンジンの中核。ルール評価のメインループ |
| 4-3 | ip_nat.c | `sys/netpfil/ipfilter/netinet/ip_nat.c` | NATエンジン。アドレス変換処理 |
| 4-4 | ip_state.c | `sys/netpfil/ipfilter/netinet/ip_state.c` | 状態追跡エンジン。接続状態管理 |

### プログラム呼び出し階層図

```
ipf / ipnat / ipfstat / ipmon（ユーザ空間コマンド）
    │
    ├─ ipf main() → ioctl(/dev/ipf)
    │      ├─ ルール読み込み・パース（libipf）
    │      └─ SIOCADAFR/SIOCRMAFR → カーネルルール追加/削除
    │
    ├─ ipnat main() → ioctl(/dev/ipnat)
    │      └─ SIOCADNAT/SIOCRMNAT → NATルール追加/削除
    │
カーネル空間:
    │
    ├─ ip_fil_freebsd.c: pfil フック登録
    │
    ├─ fil.c: fr_check()  ← pfil フック経由
    │      ├─ ルール評価ループ
    │      ├─ ip_state.c: fr_stlookup() → 状態テーブル照合
    │      └─ ip_nat.c: nat_check() → NAT処理
    │
    └─ ip_log.c: ログ出力 → /dev/ipl
```

### データフロー図

```
[入力]                    [処理]                         [出力]

ipf.rules ───────▶ ipf コマンド ──────────▶ カーネルフィルタルール
                    libipf パーサー           (ioctl SIOCADAFR)

ipnat.rules ─────▶ ipnat コマンド ────────▶ カーネルNATテーブル
                    libipf パーサー           (ioctl SIOCADNAT)

ネットワークパケット ─▶ pfil フック ──────────▶ パケット通過/破棄/
                      fil.c: fr_check()        NAT変換/ログ出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ipf.c | `sbin/ipf/ipf/ipf.c` | ソース | ipfコマンドメイン処理 |
| ipnat.c | `sbin/ipf/ipnat/ipnat.c` | ソース | ipnatコマンドメイン処理 |
| ipfstat.c | `sbin/ipf/ipfstat/ipfstat.c` | ソース | 統計表示コマンド |
| ipmon.c | `sbin/ipf/ipmon/ipmon.c` | ソース | ログ監視デーモン |
| ippool.c | `sbin/ipf/ippool/ippool.c` | ソース | IPプール管理コマンド |
| ipfsync.c | `sbin/ipf/ipfsync/ipfsync.c` | ソース | 状態同期コマンド |
| libipf/ | `sbin/ipf/libipf/` | ソース | 共通ライブラリ |
| netinet/ | `sys/netpfil/ipfilter/netinet/` | ソース | カーネルIPFilter実装 |
| fil.c | `sys/netpfil/ipfilter/netinet/fil.c` | ソース | フィルタリングエンジン中核 |
| ip_nat.c | `sys/netpfil/ipfilter/netinet/ip_nat.c` | ソース | NATエンジン |
| ip_state.c | `sys/netpfil/ipfilter/netinet/ip_state.c` | ソース | 状態追跡エンジン |
| ip_fil_freebsd.c | `sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c` | ソース | FreeBSD統合層 |
| ip_pool.c | `sys/netpfil/ipfilter/netinet/ip_pool.c` | ソース | IPプールカーネル実装 |
