# 機能設計書 49-IPsec

## 概要

本ドキュメントは、FreeBSDのIPsec（IP Security）実装について記述する。IPsecはIPレベルでの暗号化・認証を提供し、VPN（Virtual Private Network）基盤として機能する。カーネル内のnetipsec実装とsetkeyユーザ空間ツールを含む。

### 本機能の処理概要

IPsecはネットワーク層（IP層）でパケットの暗号化（ESP: Encapsulating Security Payload）、認証（AH: Authentication Header）、圧縮（IPComp: IP Payload Compression）を提供するセキュリティプロトコル群である。

**業務上の目的・背景**：拠点間VPN接続、リモートアクセスVPN、ホスト間のセキュア通信において、IPレベルでの透過的な暗号化・認証が必要とされる。IPsecはRFCで標準化されたプロトコルであり、相互運用性が高い。

**機能の利用シーン**：site-to-site VPN接続の構築、リモートアクセスVPNの構成、ホスト間の機密通信の暗号化、ネットワークレベルの認証（パケット改ざん検知）、IKE（Internet Key Exchange）デーモンとの連携によるSA（Security Association）の自動管理に使用される。

**主要な処理内容**：
1. セキュリティポリシーデータベース（SPD）の管理
2. セキュリティアソシエーションデータベース（SAD）の管理
3. ESP暗号化・復号化処理（xform_esp.c）
4. AH認証ヘッダ処理（xform_ah.c）
5. IPComp圧縮処理（xform_ipcomp.c）
6. PF_KEY v2プロトコルによるSA管理インタフェース（key.c, keysock.c）
7. setkeyコマンドによるSPD/SAD手動管理
8. IPsecオフロード（ipsec_offload.c）
9. UDP encapsulation（udpencap.c）

**関連システム・外部連携**：opencryptoフレームワークとの暗号処理連携、PF_KEYソケットインタフェースによるIKEデーモン（racoon/strongSwan等）との連携、ネットワークインタフェース層（if_enc）、pfilフレームワーク。

**権限による制御**：IPsecポリシーの設定にはroot権限が必要。PF_KEYソケットのオープンにはroot権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （CLIベースのためGUI画面なし） | - | setkeyコマンド / PF_KEYソケットによる管理 |

## 機能種別

ネットワーク暗号化 / パケット認証 / VPN基盤 / SA管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| policy | string | Yes（SPD設定時） | IPsecポリシー（ipsec/discard/none） | 有効なポリシー文字列 |
| src/dst | IP address | Yes | 送信元/宛先IPアドレス | 有効なIPv4/IPv6アドレス |
| protocol | string | Yes（SA設定時） | プロトコル（esp/ah/ipcomp） | 有効なプロトコル名 |
| algorithm | string | Yes（SA設定時） | 暗号/認証アルゴリズム | サポートされたアルゴリズム |
| spi | uint32 | Yes（SA設定時） | Security Parameter Index | 0以外の32ビット値 |
| key | hex string | Yes（SA設定時） | 暗号/認証鍵 | アルゴリズムに適合する鍵長 |

### 入力データソース

- setkeyコマンド（手動SA/SPD管理）
- PF_KEY v2ソケット（IKEデーモン経由の自動SA管理）
- setkey.conf設定ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| encrypted_packet | IP packet | ESP暗号化パケット |
| authenticated_packet | IP packet | AH認証付きパケット |
| compressed_packet | IP packet | IPComp圧縮パケット |
| sa_dump | text | SAD/SPDの内容ダンプ |

### 出力先

- ネットワークインタフェース（暗号化/認証済みパケット）
- 標準出力（setkey -D/-DPによるSA/SPD表示）
- PF_KEYソケット（SA変更通知）

## 処理フロー

### 処理シーケンス

```
1. SA/SPD設定（setkey or IKEデーモン）
   └─ PF_KEY v2メッセージによるカーネルSAD/SPD更新
2. 送信パケット処理（ipsec_output.c）
   └─ SPDルックアップ → 一致するSA取得 → ESP/AH適用
3. ESP暗号化（xform_esp.c）
   └─ opencryptoフレームワーク経由で暗号化+認証
4. AH認証（xform_ah.c）
   └─ opencryptoフレームワーク経由で認証ヘッダ計算
5. 受信パケット処理（ipsec_input.c）
   └─ SPI検索 → SA取得 → ESP復号/AH検証
6. SPDチェック
   └─ 復号後パケットのSPDポリシー照合
```

### フローチャート

```mermaid
flowchart TD
    A[送信パケット] --> B{SPDルックアップ}
    B -->|IPsec適用| C[SA取得]
    B -->|非適用| D[通常送信]
    C --> E{プロトコル}
    E -->|ESP| F[暗号化+認証]
    E -->|AH| G[認証ヘッダ計算]
    E -->|IPComp| H[圧縮処理]
    F --> I[暗号化パケット送信]
    G --> I
    H --> I

    J[受信パケット] --> K{ESP/AH/IPComp?}
    K -->|ESP| L[復号化+認証検証]
    K -->|AH| M[認証検証]
    K -->|通常| N[通常処理]
    L --> O{SPDチェック}
    M --> O
    O -->|一致| P[パケット受け入れ]
    O -->|不一致| Q[パケット破棄]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-49-01 | SPD優先順位 | SPDエントリは最も具体的なマッチが優先される | ポリシー照合時 |
| BR-49-02 | SAライフタイム | SAにはソフト/ハードの有効期限（時間またはバイト数）がある | SA管理 |
| BR-49-03 | リプレイ防止 | ESPシーケンス番号によるリプレイ攻撃防止 | ESP受信時 |
| BR-49-04 | トランスポート/トンネルモード | トランスポートモードはホスト間、トンネルモードはゲートウェイ間の保護 | SA設定時 |

### 計算ロジック

- ESPパディング計算：暗号アルゴリズムのブロックサイズに合わせたパディング
- AH ICV計算：認証アルゴリズムによるパケット全体のICV（Integrity Check Value）計算
- リプレイウィンドウ：スライディングウィンドウによるシーケンス番号の重複検知

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

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

本機能はデータベースを使用しない。カーネル内のSAD（Security Association Database）とSPD（Security Policy Database）を操作する。

| 操作 | 対象データ構造 | 操作種別 | 概要 |
|-----|-------------|---------|------|
| setkey add | SAD | INSERT | SA追加 |
| setkey delete | SAD | DELETE | SA削除 |
| setkey spdadd | SPD | INSERT | ポリシー追加 |
| setkey spddump | SPD | SELECT | ポリシー一覧 |
| setkey -D | SAD | SELECT | SA一覧 |

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

#### secashead（SAデータベース）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| INSERT | spi, src, dst, proto, alg, key | setkeyまたはPF_KEY経由 | SPIで一意にインデックス |
| SELECT | src, dst, proto, spi | パケット処理時のSAルックアップ | ハッシュテーブル |
| DELETE | spi, src, dst, proto | SA期限切れまたは手動削除 | 参照カウント管理 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ENOENT | SA未発見 | パケットに一致するSAがない | SAを設定またはIKEでネゴシエーション |
| EINVAL | パラメータエラー | 不正なアルゴリズムまたは鍵長 | 正しいパラメータを指定 |
| EPERM | 権限不足 | 非rootでのSA/SPD変更 | root権限で実行 |
| EACCES | 認証失敗 | AH/ESP認証検証失敗 | SA鍵設定を確認 |

### リトライ仕様

SA未発見時にIKEデーモンへのSA取得要求（SADB_ACQUIRE）が自動的に発行される。IKEデーモンがSAネゴシエーションを完了するまでパケットはキューイングされる場合がある。

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

SA/SPDの追加・削除は個別の原子的操作。PF_KEYメッセージ単位で処理される。

## パフォーマンス要件

- ESP暗号化/復号化のスループットはopencryptoフレームワークの性能に依存
- AES-NIハードウェアアクセラレーションによる高速処理
- IPsecオフロード（ipsec_offload.c）によるNIC側での暗号処理
- SAD/SPDルックアップはハッシュテーブルによるO(1)

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

- 弱い暗号アルゴリズム（DES, MD5）の使用回避
- 鍵管理（手動鍵管理よりIKEによる自動鍵管理を推奨）
- リプレイ攻撃防止の有効化
- Perfect Forward Secrecy（PFS）の使用推奨
- SAライフタイムの適切な設定
- UDP encapsulationのNAT-Traversal設定

## 備考

- FreeBSDのIPsec実装はKAME由来であり、大幅に改修されている
- PF_KEY v2はRFC 2367で標準化されたSA管理プロトコル
- setkeyコマンドは手動SA管理用で、本番環境ではIKEデーモンの使用を推奨
- IPsecオフロードにより対応NICでの暗号処理のハードウェアアクセラレーションが可能

---

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

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

### 推奨読解順序

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

IPsecのSA/SPDデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ipsec.h | `sys/netipsec/ipsec.h` | secpolicy, secashead構造体の定義。IPsecポリシーとSAの基本構造 |
| 1-2 | keydb.h | `sys/netipsec/keydb.h` | SAデータベース構造体。secasvar構造体でSAの詳細を管理 |
| 1-3 | key.h | `sys/netipsec/key.h` | PF_KEY関連構造体の定義 |

**読解のコツ**: secpolicy（SPD）は送信元/宛先/プロトコルをキーとしたポリシーエントリ。secashead/secasvar（SAD）はSPI/プロトコル/アドレスをキーとしたSAエントリ。

#### Step 2: IPsec中核処理を理解する

パケット処理の入出力フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ipsec.c | `sys/netipsec/ipsec.c` | IPsecコントローラ部分。IPsecポリシーチェック、SA選択のメインロジック。KAME由来の実装（1行目$KAME$タグ、34-36行目のコメント） |

**主要処理フロー**:
1. **1行目**: KAME由来のバージョンタグ
2. **34-36行目**: "IPsec controller part."コメント
3. **38-57行目**: opt_inet.h, opt_inet6.h, opt_ipsec.hのインクルード

#### Step 3: ESP/AH/IPComp変換を理解する

各セキュリティプロトコルの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | xform_esp.c | `sys/netipsec/xform_esp.c` | ESP暗号化・復号化処理。opencryptoとの連携 |
| 3-2 | xform_ah.c | `sys/netipsec/xform_ah.c` | AH認証ヘッダの計算・検証 |
| 3-3 | xform_ipcomp.c | `sys/netipsec/xform_ipcomp.c` | IPComp圧縮処理 |

#### Step 4: 入出力処理を理解する

パケットの送受信時のIPsec処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ipsec_output.c | `sys/netipsec/ipsec_output.c` | 送信パケットのIPsec適用（SPDルックアップ→SA選択→暗号化/認証） |
| 4-2 | ipsec_input.c | `sys/netipsec/ipsec_input.c` | 受信パケットのIPsec処理（復号化/認証検証→SPDチェック） |
| 4-3 | ipsec_pcb.c | `sys/netipsec/ipsec_pcb.c` | ソケット単位のIPsecポリシー管理 |

#### Step 5: PF_KEYインタフェースを理解する

SA管理のユーザ空間インタフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | key.c | `sys/netipsec/key.c` | PF_KEY v2メッセージ処理。SADB_ADD/DELETE/GET等のハンドラ |
| 5-2 | keysock.c | `sys/netipsec/keysock.c` | PF_KEYソケットインタフェース |
| 5-3 | setkey.c | `sbin/setkey/setkey.c` | setkeyコマンドのmain処理 |

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

```
setkey / IKEデーモン（ユーザ空間）
    │
    ├─ PF_KEY v2 ソケット
    │      └─ keysock.c → key.c: SADB_*メッセージ処理
    │             ├─ SA追加/削除/更新
    │             └─ SPD追加/削除
    │
カーネル空間:
    │
    ├─ ipsec_output.c: 送信パケット処理
    │      ├─ SPDルックアップ
    │      ├─ SA選択
    │      └─ xform_esp.c / xform_ah.c: 暗号化/認証
    │             └─ opencrypto: crypto_dispatch()
    │
    ├─ ipsec_input.c: 受信パケット処理
    │      ├─ SPI検索 → SA取得
    │      ├─ xform_esp.c / xform_ah.c: 復号化/認証検証
    │      └─ SPDチェック
    │
    └─ ipsec_offload.c: NICオフロード
```

### データフロー図

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

setkey add SA ────▶ PF_KEY → key.c ──────▶ SAD更新
                    SADB_ADD

送信パケット ────▶ ipsec_output.c ─────────▶ ESP/AH暗号化パケット
                   SPDルックアップ → SA選択
                   xform_esp/ah → opencrypto

受信ESPパケット ─▶ ipsec_input.c ──────────▶ 復号化パケット
                   SA検索 → xform_esp/ah
                   opencrypto → SPDチェック
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ipsec.c | `sys/netipsec/ipsec.c` | ソース | IPsecコントローラ中核 |
| ipsec.h | `sys/netipsec/ipsec.h` | ヘッダ | IPsecポリシー/SA構造体定義 |
| ipsec_input.c | `sys/netipsec/ipsec_input.c` | ソース | 受信パケット処理 |
| ipsec_output.c | `sys/netipsec/ipsec_output.c` | ソース | 送信パケット処理 |
| ipsec_pcb.c | `sys/netipsec/ipsec_pcb.c` | ソース | ソケット単位ポリシー |
| ipsec_offload.c | `sys/netipsec/ipsec_offload.c` | ソース | NICオフロード |
| xform_esp.c | `sys/netipsec/xform_esp.c` | ソース | ESP処理 |
| xform_ah.c | `sys/netipsec/xform_ah.c` | ソース | AH処理 |
| xform_ipcomp.c | `sys/netipsec/xform_ipcomp.c` | ソース | IPComp処理 |
| key.c | `sys/netipsec/key.c` | ソース | PF_KEY SA管理 |
| keysock.c | `sys/netipsec/keysock.c` | ソース | PF_KEYソケット |
| keydb.h | `sys/netipsec/keydb.h` | ヘッダ | SAデータベース構造体 |
| key_debug.c | `sys/netipsec/key_debug.c` | ソース | デバッグ出力 |
| udpencap.c | `sys/netipsec/udpencap.c` | ソース | UDP encapsulation |
| subr_ipsec.c | `sys/netipsec/subr_ipsec.c` | ソース | IPsecサブルーチン |
| ipsec_mod.c | `sys/netipsec/ipsec_mod.c` | ソース | IPsecモジュール管理 |
| setkey.c | `sbin/setkey/setkey.c` | ソース | setkeyコマンド |
| parse.y | `sbin/setkey/parse.y` | ソース | setkeyパーサー |
| token.l | `sbin/setkey/token.l` | ソース | setkey字句解析 |
| setkey.8 | `sbin/setkey/setkey.8` | マニュアル | setkeyのmanページ |
