# 機能設計書 51-SSH

## 概要

本ドキュメントは、FreeBSDにおけるOpenSSH（Secure Shell）機能の設計を記述する。SSH機能はリモートホストへのセキュアな接続、ファイル転送、ポートフォワーディング等を提供するネットワークセキュリティ機能群である。

### 本機能の処理概要

SSH機能は、OpenSSHをベースとしたセキュアなリモートアクセスプロトコルの実装であり、暗号化された通信チャネルを介して、リモートログイン、コマンド実行、ファイル転送などを安全に行う。

**業務上の目的・背景**：ネットワーク経由でのリモート管理は、サーバ運用において不可欠である。従来のtelnetやrsh等のプロトコルは平文通信であり盗聴のリスクがあるため、SSHにより暗号化された安全な通信路を確立し、認証情報やデータの機密性・完全性を保証する必要がある。

**機能の利用シーン**：サーバへのリモートログイン、scpやsftpによるファイル転送、SSHトンネリングによるポートフォワーディング、鍵ベースの自動化スクリプト実行、Git等のバージョン管理システムでの認証など、多岐にわたる場面で利用される。

**主要な処理内容**：
1. SSHクライアント（ssh）による暗号化リモート接続の確立
2. SSHサーバ（sshd）による接続受付と認証処理
3. 公開鍵認証・パスワード認証・GSSAPI認証等の多段認証
4. SCP/SFTPによるセキュアファイル転送
5. SSH鍵の生成・管理（ssh-keygen）
6. SSHエージェント（ssh-agent）による鍵管理
7. ポートフォワーディング（ローカル/リモート/ダイナミック）
8. X11フォワーディング
9. 多重接続（ControlMaster/ControlPersist）

**関連システム・外部連携**：OpenSSLライブラリ（暗号化処理）、PAM（認証モジュール）、Kerberos/GSSAPI（SSO認証）、audit（セキュリティ監査ログ）との連携がある。

**権限による制御**：sshdはroot権限で起動しリスニングソケットを作成するが、認証後はユーザ権限に降格する。特権分離（privilege separation）機構により、認証前の処理は非特権プロセスで実行される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | サービス選択画面 | 補助機能 | sshdサービスの起動設定（デフォルトON） |

## 機能種別

ネットワークサービス / セキュア通信 / 認証処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| destination | string | Yes | 接続先ホスト名またはIPアドレス | 有効なホスト名/IP形式 |
| port | int | No | 接続先ポート番号（デフォルト22） | 1-65535の範囲 |
| identity_file | path | No | 秘密鍵ファイルパス | ファイルが存在すること |
| login_name | string | No | ログインユーザ名 | 有効なユーザ名形式 |
| cipher_spec | string | No | 暗号アルゴリズム指定 | サポートされるアルゴリズム名 |
| configfile | path | No | 設定ファイルパス | ファイルが存在すること |
| command | string | No | リモート実行コマンド | 任意の文字列 |

### 入力データソース

- コマンドライン引数
- 設定ファイル（~/.ssh/config, /etc/ssh/ssh_config, /etc/ssh/sshd_config）
- 鍵ファイル（~/.ssh/id_rsa, ~/.ssh/id_ed25519等）
- known_hostsファイル（~/.ssh/known_hosts）
- authorized_keysファイル（~/.ssh/authorized_keys）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 暗号化通信チャネル | stream | 暗号化されたデータストリーム |
| 認証結果 | boolean | 認証成功/失敗 |
| 終了ステータス | int | リモートコマンドの終了コード |
| ホスト鍵 | file | サーバのホスト鍵ファイル群 |
| ログ出力 | syslog | 認証ログ、接続ログ |

### 出力先

- 標準出力/標準エラー出力（クライアント側）
- syslog（サーバ側認証ログ）
- ファイル（鍵ファイル、known_hosts等）
- ネットワークソケット（暗号化データ転送）

## 処理フロー

### 処理シーケンス

```
1. SSH接続開始
   └─ クライアントがサーバのポート22（またはカスタムポート）に接続
2. プロトコルバージョン交換
   └─ SSH-2.0プロトコルバージョン文字列の交換
3. 鍵交換（Key Exchange）
   └─ Diffie-Hellman等のアルゴリズムで共有秘密を生成
4. ホスト認証
   └─ サーバのホスト鍵をknown_hostsと照合
5. ユーザ認証
   └─ 公開鍵認証 → パスワード認証 → keyboard-interactive等の順に試行
6. チャネル確立
   └─ セッションチャネル、転送チャネルの確立
7. セッション実行
   └─ シェル起動/コマンド実行/ファイル転送
8. セッション終了
   └─ チャネルクローズ、接続切断
```

### フローチャート

```mermaid
flowchart TD
    A[接続開始] --> B[プロトコルバージョン交換]
    B --> C[鍵交換 Key Exchange]
    C --> D{ホスト鍵検証}
    D -->|既知| E[ユーザ認証]
    D -->|未知| F{ユーザ承認?}
    F -->|Yes| G[known_hostsに追加]
    F -->|No| H[接続拒否]
    G --> E
    E --> I{認証方式}
    I -->|公開鍵| J[公開鍵認証]
    I -->|パスワード| K[パスワード認証]
    I -->|GSSAPI| L[GSSAPI認証]
    J --> M{認証成功?}
    K --> M
    L --> M
    M -->|Yes| N[チャネル確立]
    M -->|No| O[認証失敗]
    N --> P[セッション実行]
    P --> Q[セッション終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-51-01 | MaxStartups制限 | 同時未認証接続数の制限（デフォルト10:30:100） | sshdへの接続受付時 |
| BR-51-02 | LoginGraceTime | 認証完了までの猶時間（デフォルト120秒） | 接続受付後、認証完了前 |
| BR-51-03 | MaxAuthTries | 認証試行回数の制限（デフォルト6回） | ユーザ認証処理中 |
| BR-51-04 | PermitRootLogin | rootログインの許可/拒否制御 | root認証時 |
| BR-51-05 | 特権分離 | 認証前処理は非特権プロセスで実行 | sshd接続処理全般 |

### 計算ロジック

特になし（暗号化アルゴリズムの詳細はOpenSSLライブラリに委譲）。

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

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

本機能はデータベースを使用しない。ファイルベースでの状態管理を行う。

| 操作 | 対象ファイル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ホスト鍵検証 | ~/.ssh/known_hosts | READ/WRITE | ホスト鍵の照合・追加 |
| 鍵認証 | ~/.ssh/authorized_keys | READ | 公開鍵の照合 |
| 設定読み込み | /etc/ssh/sshd_config | READ | サーバ設定の読み込み |

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

該当なし（ファイルベース）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 255 | 接続エラー | ホストに到達できない場合 | ホスト名・ポート番号を確認 |
| - | 認証失敗 | 全ての認証方式が失敗 | 鍵・パスワードを確認 |
| - | ホスト鍵変更 | サーバのホスト鍵がknown_hostsと不一致 | known_hostsを更新、またはMITM攻撃を疑う |
| - | 権限エラー | 鍵ファイルのパーミッションが不適切 | chmod 600で適切な権限に設定 |

### リトライ仕様

ConnectionAttempts設定（デフォルト1）により再接続試行回数を制御。ServerAliveIntervalにより接続維持のキープアライブを送信。

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

該当なし。SSHプロトコルは独自のシーケンス番号管理とMAC（メッセージ認証コード）により、パケットの整合性を保証する。

## パフォーマンス要件

- 接続確立時間：鍵交換・認証を含め通常1-3秒以内
- データ転送：暗号化オーバーヘッドはネットワーク帯域の5-10%程度
- ControlMasterによる多重接続で再接続のオーバーヘッドを削減可能

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

- 特権分離（Privilege Separation）により認証前処理のセキュリティリスクを低減
- ChRoot環境によるSFTPのアクセス制限
- AllowUsers/DenyUsers/AllowGroups/DenyGroupsによるアクセス制御
- HostbasedAuthentication、PubkeyAuthentication等の認証方式の選択的有効化
- StrictHostKeyCheckingによるMITM攻撃防止
- 暗号アルゴリズムの選択（Ciphers、MACs、KexAlgorithms設定）

## 備考

- FreeBSDではOpenSSHがベースシステムに統合されており、crypto/openssh/以下にソースがある
- ビルドはsecure/usr.bin/およびsecure/usr.sbin/のMakefileを通じて行われる
- FreeBSD固有のパッチ（GSSAPI対応、blocklist連携等）が適用されている

---

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

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

### 推奨読解順序

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

SSH通信で使用される主要なデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ssh.h | `crypto/openssh/ssh.h` | SSHプロトコル定数、構造体定義 |
| 1-2 | sshkey.h | `crypto/openssh/sshkey.h` | 鍵オブジェクトの構造定義 |
| 1-3 | packet.h | `crypto/openssh/packet.h` | パケット送受信構造の定義 |
| 1-4 | channels.h | `crypto/openssh/channels.h` | チャネル管理構造の定義 |

**読解のコツ**: OpenSSHのコードはOpenBSD由来であり、FreeBSD固有の変更は`#ifdef __FreeBSD__`で囲まれている。`sshd.c`の75-82行目にFreeBSD固有のインクルードがある。

#### Step 2: エントリーポイントを理解する（クライアント側）

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ssh.c | `crypto/openssh/ssh.c` | SSHクライアントのmain()関数 |

**主要処理フロー**:
1. **124-172行目**: グローバル変数定義（debug_flag、tty_flag、Options構造体等）
2. **180-194行目**: usage()関数 - コマンドラインオプションの定義
3. main()関数: コマンドライン解析 → 設定ファイル読み込み → 接続 → セッション実行

#### Step 3: エントリーポイントを理解する（サーバ側）

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sshd.c | `crypto/openssh/sshd.c` | SSHサーバのmain()関数 |

**主要処理フロー**:
- **120-156行目**: サーバオプション構造体、sensitive_data（ホスト鍵保持構造体）
- **139-141行目**: MAX_LISTEN_SOCKS定義とリスニングソケット配列
- **167-199行目**: early_child構造体 - MaxStartups制限、LoginGraceTime管理用の子プロセス追跡

#### Step 4: 認証処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | auth2.c | `crypto/openssh/auth2.c` | SSH2認証ディスパッチャ |
| 4-2 | auth2-pubkey.c | `crypto/openssh/auth2-pubkey.c` | 公開鍵認証処理 |
| 4-3 | auth2-passwd.c | `crypto/openssh/auth2-passwd.c` | パスワード認証処理 |
| 4-4 | auth-pam.c | `crypto/openssh/auth-pam.c` | PAM連携認証 |

#### Step 5: 接続処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sshconnect2.c | `crypto/openssh/sshconnect2.c` | SSH2接続確立処理（約2365行） |
| 5-2 | kex.c | `crypto/openssh/kex.c` | 鍵交換プロトコル |
| 5-3 | cipher.c | `crypto/openssh/cipher.c` | 暗号化処理 |

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

```
ssh (クライアント)                    sshd (サーバ)
    |                                     |
    +-- main() [ssh.c]                    +-- main() [sshd.c]
    |   |                                 |   |
    |   +-- readconf() [readconf.c]       |   +-- servconf() [servconf.c]
    |   +-- ssh_connect() [sshconnect.c]  |   +-- listen/accept
    |   +-- ssh_login() [sshconnect2.c]   |   +-- fork() -> 子プロセス
    |       |                             |       |
    |       +-- kex [kex.c]               |       +-- 特権分離 privsep
    |       +-- userauth [auth2.c]        |       +-- do_authentication2()
    |                                     |           |
    +-- ssh_session2() [ssh.c]            |           +-- auth2-pubkey.c
        |                                 |           +-- auth2-passwd.c
        +-- client_loop() [clientloop.c]  |           +-- auth-pam.c
        +-- channel [channels.c]          |
                                          +-- do_child() [session.c]
```

### データフロー図

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

コマンドライン引数 ───▶ ssh クライアント ─────────────▶ 暗号化パケット
~/.ssh/config     ───▶ (ssh.c)                          |
~/.ssh/id_ed25519 ───▶                                   |
                                                         ▼
                        sshd サーバ ◀──────────────── ネットワーク
/etc/ssh/sshd_config ▶ (sshd.c)
~/.ssh/authorized_keys ▶   |
                           ├─▶ syslog (認証ログ)
                           ├─▶ utmp/wtmp (ログイン記録)
                           └─▶ シェル/コマンド実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ssh.c | `crypto/openssh/ssh.c` | ソース | SSHクライアントメインプログラム |
| sshd.c | `crypto/openssh/sshd.c` | ソース | SSHサーバメインプログラム |
| sshconnect2.c | `crypto/openssh/sshconnect2.c` | ソース | SSH2接続確立処理 |
| auth2.c | `crypto/openssh/auth2.c` | ソース | SSH2認証ディスパッチャ |
| auth2-pubkey.c | `crypto/openssh/auth2-pubkey.c` | ソース | 公開鍵認証 |
| auth-pam.c | `crypto/openssh/auth-pam.c` | ソース | PAM認証連携 |
| kex.c | `crypto/openssh/kex.c` | ソース | 鍵交換処理 |
| cipher.c | `crypto/openssh/cipher.c` | ソース | 暗号化処理 |
| channels.c | `crypto/openssh/channels.c` | ソース | チャネル管理 |
| readconf.c | `crypto/openssh/readconf.c` | ソース | クライアント設定読み込み |
| servconf.c | `crypto/openssh/servconf.c` | ソース | サーバ設定読み込み |
| sshd_config | `/etc/ssh/sshd_config` | 設定 | SSHサーバ設定 |
| ssh_config | `/etc/ssh/ssh_config` | 設定 | SSHクライアント設定 |
| Makefile | `secure/usr.bin/ssh/Makefile` | ビルド | クライアントビルド定義 |
| Makefile | `secure/usr.sbin/sshd/Makefile` | ビルド | サーバビルド定義 |
