TCP(Transmission Control Protocol)は、信頼性のある双方向通信を実現するために、厳密な状態管理機構を備えています。この状態機械(state machine)は、接続の確立・データ転送・切断までの全フェーズを制御し、シーケンス番号、アックノレッジメント番号、および制御フラグ(SYN, ACK, FINなど)を用いて整合性を保ちます。以下に、主な状態とその運用上の意味を再構成して解説します。
1. 接続ライフサイクルにおける代表的な状態
接続確立(3-way handshake)
-
LISTEN サーバ側が受信待ち状態。
bind()とlisten()の実行後、指定ポートでSYNパケットを待機中。例:Nginxがポート443でHTTPS接続を受け付ける準備完了時。 -
SYN-SENT クライアントがSYNパケットを送出済みで、相手からのSYN-ACK応答を待っている状態。ネットワーク遅延やファイアウォールブロックにより長期間滞留すると、タイムアウト後にエラーが返される。
-
SYN-RECEIVED サーバがSYNを受信し、SYN-ACKを返信した直後。クライアントからの最終ACKを待機中。不正な大量SYN受信(SYN Flood)に対する防御として、Linuxでは
tcp_syncookies=1が有効化可能。 -
ESTABLISHED 双方向のセッションが正常に開始された状態。アプリケーション層でのデータ交換(HTTPリクエスト/レスポンスなど)が可能。この状態で継続的にパケットが流れないと、中間機器(ロードバランサ、NATデバイス)がコネクションを切断するリスクがある。
接続終了(4-way teardown)
-
FIN-WAIT-1 主動クローズ側(通常クライアント)がFINを送出し、相手のACKまたはFIN+ACKを待つ状態。FIN送信後、アプリケーションはソケットを閉じたとみなされ、送信バッファ内の残りデータも含めて順次送信される。
-
CLOSE-WAIT 受動側(サーバ)が相手のFINを受信し、ACKを返信済みだが、まだ自らの送信を完了していない状態。これは「半閉じ(half-close)」の典型的な表現であり、コード内で
close()呼び出し漏れがあると、この状態が長期間維持され、ファイルディスクリプタ枯渇を招く。 -
FIN-WAIT-2 主動側がACKを受信後、相手のFINを待つ状態。相手がFINを送信しない場合、カーネルは
tcp_fin_timeout(デフォルト60秒)で強制終了を試行する。 -
LAST-ACK 受動側が自らFINを送出し、最終ACKを待っている一時的状態。ACKが届かないとFINが再送され、一定回数を超えると接続が破棄される。
-
TIME-WAIT 主動側が最終ACKを受信後、2×MSL(Maximum Segment Lifetime)時間(通常約60秒)待機する状態。これは、ネットワーク上に残留する重複パケットが新規コネクションに干渉するのを防ぐための安全機構。高頻度短命コネクション(例:HTTP/1.0)では、この状態が多数発生し、ポート枯渇を引き起こす可能性がある。
-
CLOSED すべてのリソース(ポート、メモリ、カーネル構造体)が解放された終了状態。ユーザー空間では明示的に
close()を呼ぶか、プロセス終了時にカーネルが自動解放する。
2. 状態遷移の簡易モデル(Mermaid記法)
graph LR A[LISTEN] -->|SYN| B[SYN-RECEIVED] C[SYN-SENT] -->|SYN+ACK| D[ESTABLISHED] B -->|ACK| D D -->|FIN| E[FIN-WAIT-1] E -->|ACK| F[FIN-WAIT-2] D -->|FIN| G[CLOSE-WAIT] G -->|FIN| H[LAST-ACK] F -->|FIN| H H -->|ACK| I[CLOSED] E -->|timeout| J[TIME-WAIT] J -->|2MSL| I
3. 運用上の課題と対応策
| 状態 | 課題の兆候 | 対応手法 |
|---|---|---|
SYN-RECEIVED 過多 |
パフォーマンス低下、拒否サービス攻撃の疑い | net.ipv4.tcp_syncookies = 1 を有効化、ファイアウォールによるSYNフィルタリング |
CLOSE-WAIT 持続 |
アプリケーションのリソースリーク | ソースコード内のclose()呼び出し確認、lsof -iで開かれたソケットをトレース |
TIME-WAIT 積滞 |
新規接続失敗、ポート不足 | net.ipv4.tcp_tw_reuse = 1(クライアント向け再利用)、net.ipv4.tcp_fin_timeout短縮(注意:RFC準拠性とのトレードオフ) |
ESTABLISHED なのに通信なし |
中間機器のタイムアウト、アプリケーションハング | tcpdump -i any port <PORT> でパケットフロー確認、ss -iでRTT・ウィンドウサイズを検証 |
4. 監視と診断に役立つコマンド
- 全TCPコネクションの一覧(最新の
ss推奨):
ss -tunap # -t:TCP, -u:UDP, -n:数値表示, -a:全状態, -p:プロセス情報
- 特定状態の集計(例:TIME-WAITの数):
ss -tan state time-wait | wc -l
- 各状態ごとのカウント:
ss -tan | awk '{print $1}' | sort | uniq -c | sort -nr
- 接続詳細(RTT、再送回数、ウィンドウサイズ含む):
ss -ti 'sport == :443' # HTTPSサーバの詳細情報