# バッチ設計書 55-900.tcpwrap

## 概要

本ドキュメントは、FreeBSD の periodic セキュリティスクリプト `900.tcpwrap` のバッチ設計書である。TCP Wrapper による接続拒否ログを確認し、セキュリティレポートとして管理者に通知する。

### 本バッチの処理概要

本バッチは、`/var/log/messages` およびそのローテーション済みファイルから前日分の TCP Wrapper 接続拒否メッセージを抽出し、セキュリティレポートとして管理者に通知する。TCP Wrapper（libwrap）によるアクセス制御で拒否された接続を監視する。

**業務上の目的・背景**：TCP Wrapper は、`/etc/hosts.allow` および `/etc/hosts.deny` に基づいてネットワークサービスへのアクセス制御を行う仕組みである。本バッチは、TCP Wrapper によって拒否された接続を日次で監視し、不正アクセスの試行や誤った設定による正当なアクセスの拒否を管理者に報告する。これにより、ネットワークセキュリティの状況把握と設定の適切性確認を支援する。

**バッチの実行タイミング**：daily（日次）のセキュリティチェック（450.status-security）から呼び出される。periodic(8) フレームワークにより、`security_status_tcpwrap_period` の設定に応じて daily/weekly/monthly のいずれかで実行される。デフォルトは daily。

**主要な処理内容**：
1. `security_status_logdir`（デフォルト `/var/log`）から `messages` およびローテーション済みファイル（`messages.*`）を収集
2. RFC 3164（従来形式）および RFC 5424（新形式）の syslog タイムスタンプに対応した前日の日付パターンを生成
3. `catmsgs` 関数で直近2日以内の messages ファイルを時系列順に結合
4. `egrep` で接続拒否メッセージ（`refused connect`）を含む前日分のメッセージを抽出
5. 該当メッセージを標準エラー出力に表示し、件数をカウント

**前後の処理との関連**：本バッチは `450.status-security` から呼び出される。ファイアウォール関連の監査スクリプト群（`500.ipfwdenied`, `510.ipfdenied`, `520.pfdenied` 等）と並行して、アプリケーションレベルのアクセス制御監視を担当する。

**影響範囲**：システムログファイルを読み取り専用で参照する。システムの設定変更は行わない。

## バッチ種別

レポート生成 / セキュリティ監査

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 日次（デフォルト） |
| 実行時刻 | periodic(8) の daily セキュリティチェック実行時 |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | cron 経由の periodic(8) フレームワーク |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| periodic.conf の読み込み | `/etc/defaults/periodic.conf` が読み取り可能であること |
| messages ログの存在 | `security_status_logdir` 配下に `messages` が存在すること |
| find/zcat コマンド | `find`, `zcat`, `egrep` コマンドが利用可能であること |

### 実行可否判定

`check_yesno_period security_status_tcpwrap_enable` で有効/無効を判定（デフォルト: YES）。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| security_status_tcpwrap_enable | 文字列 | No | YES | バッチの有効/無効 |
| security_status_tcpwrap_period | 文字列 | No | daily | 実行期間（daily/weekly/monthly） |
| security_status_logdir | 文字列 | No | /var/log | ログディレクトリ |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| `${LOG}/messages` | syslog テキスト | 現在のシステムメッセージログ |
| `${LOG}/messages.*` | syslog テキスト（圧縮含む） | ローテーション済みシステムメッセージログ |
| `/etc/defaults/periodic.conf` | シェル変数定義 | periodic フレームワークの設定ファイル |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力 | テキスト | "{host} refused connections:" ヘッダ |
| 標準エラー出力 | テキスト | 前日分の接続拒否メッセージ（tee /dev/stderr 経由） |
| 終了コード | 整数 | 0: 接続拒否なし、1: 接続拒否あり |

### 出力ファイル仕様

本バッチは永続的な出力ファイルを生成しない。結果は標準出力および標準エラー出力に出力される。

## 処理フロー

### 処理シーケンス

```
1. 設定ファイルの読み込み
   └─ /etc/defaults/periodic.conf を読み込み、source_periodic_confs で追加設定を適用
2. ログディレクトリの設定
   └─ LOG 変数に security_status_logdir の値を設定
3. 日付パターンの生成
   └─ RFC 3164 形式: "^Mon DD " （例: "^Jan 31 "）
   └─ RFC 5424 形式: "^<PRI>1 YYYY-MM-DDT" （例: "^<[0-9]{1,3}>1 2026-01-31T"）
   └─ 両形式を OR 結合: "(RFC3164|RFC5424)"
4. 有効/無効判定
   └─ check_yesno_period security_status_tcpwrap_enable で実行可否を判定
5. ヘッダ出力
   └─ "{host} refused connections:" を表示
6. ログファイル収集・検索
   └─ catmsgs 関数で messages.* を mtime -2 で検索
   └─ sort -t. -r -n -k 2,2 で番号降順にソート
   └─ 各ファイルを zcat -f で展開
   └─ 最後に messages を cat で出力
7. パターンマッチング
   └─ egrep -ia で前日の日付パターンと "refused connect" を含む行を抽出
   └─ tee /dev/stderr で結果を表示しつつ wc -l でカウント
8. 結果判定
   └─ 件数 > 0 の場合 rc=1、それ以外は rc=0
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[設定ファイル読み込み]
    B --> C[日付パターン生成<br>RFC 3164 + RFC 5424]
    C --> D{security_status_tcpwrap_enable?}
    D -->|NO| Z["exit 0"]
    D -->|YES| E["'{host} refused connections:' 表示"]
    E --> F["catmsgs: messages.* を収集・結合"]
    F --> G["egrep で前日分の 'refused connect' を抽出"]
    G --> H["tee /dev/stderr で表示 + wc -l でカウント"]
    H --> I{件数 > 0?}
    I -->|YES| J["rc=1"]
    I -->|NO| K["rc=0"]
    J --> L["exit $rc"]
    K --> L
```

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

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

本バッチではデータベース操作は行わない。ログファイルの読み取り専用アクセスのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 0 | 正常終了 | 接続拒否なし、または無効設定 | 対処不要 |
| 1 | 警告 | 接続拒否が検出された | 管理者が拒否内容を確認し、設定の妥当性を検証 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（リトライ機構なし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

messages ファイルが存在しない場合、catmsgs 関数は find の結果が空となり、最後の `[ -f ${LOG}/messages ] && cat` も実行されないため、egrep への入力は空となる。この場合、件数は 0 となり正常終了する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（データベース操作なし） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | messages のサイズに依存（通常数千〜数万行/日） |
| 目標処理時間 | 数秒〜数十秒（ログサイズに依存） |
| メモリ使用量上限 | 最小（パイプライン処理） |

## 排他制御

排他制御は実装されていない。ログファイルへの読み取り専用アクセスのため、ログローテーションとの競合に注意が必要だが、`-mtime -2` による直近2日分のファイル参照で対処している。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| ヘッダ | バッチ開始時 | "{host} refused connections:" |
| 拒否ログ | 接続拒否検出時 | 前日分の接続拒否メッセージ（stderr 経由） |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 終了コード | 1（接続拒否検出） | periodic(8) のメール通知先（daily セキュリティレポート） |

## 備考

- 本バッチは `800.loginfail` と非常に類似した構造を持ち、検索対象のログファイル（messages vs auth.log）と検索パターン（"refused connect" vs ログイン失敗キーワード）が異なる
- TCP Wrapper（libwrap）は `hosts.allow` / `hosts.deny` に基づくアクセス制御であり、inetd 経由のサービスや libwrap 対応サービスで使用される
- RFC 3164 タイムスタンプ形式: `Jan 31 ` のような従来の syslog 形式
- RFC 5424 タイムスタンプ形式: `<PRI>1 2026-01-31T` のような構造化 syslog 形式
- `date -v-1d` は FreeBSD の date コマンド固有の相対日付指定で、前日の日付を生成する
- `tee /dev/stderr` は出力を表示しつつ、パイプラインの次段（wc -l）にも渡すためのテクニック
- `sort -t. -r -n -k 2,2` でログファイルを番号の降順（古い順）にソートし、時系列で結合する
