死んだコネクションを蘇らせるな:TCP Keepaliveの深淵と、その先にある「真の切断」戦略
ネットワークエンジニアとして現場を渡り歩いていると、必ずと言っていいほど直面するのが「ゾンビ化したコネクション」の処理だ。アプリケーション層では「接続されている」と信じ込んでいるのに、ルーターのNATタイムアウトやファイアウォールのステートフル・インスペクションによって、パケットが静かに破棄されているあの状況。
今日は、OSI参照モデルの第4層、TCPの「キープアライブ(Keepalive)」という、一見地味だが極めて重要なメカニズムに焦点を当て、その挙動と現場での「正しい」チューニングについて深掘りしていく。
1. なぜ「Keepalive」なのか:パケットの孤独を癒やすプローブの正体
TCPは信頼性を担保するプロトコルだが、その「信頼」はあくまで通信路が生きていることを前提としている。中継機器(L4/L7のファイアウォール等)が、一定時間トラフィックのないセッションを「アイドル」とみなしてエントリを削除すれば、TCPスタックは沈黙する。
ここで登場するのが TCP Keepalive だ。これは、OSのカーネルレベルで、データを含まない空のパケット(プローブ)を相手に投げつけ、ACKが返ってくるかを確認する仕組みである。
パケットレベルの解剖
Keepaliveパケットは、シーケンス番号が現在の接続状態に対して「1つ前のバイト」を指すように細工されている。受信側は「既知のデータに対するACK」と誤認し、正常なACKパケットを返す。このやり取りにより、経路上のファイアウォールは「この通信はまだ生きている」と判断し、エントリの寿命を延ばすわけだ。
2. Linuxカーネルにおけるチューニングの黄金律
LinuxにおいてKeepaliveを制御するパラメータは、主に /proc/sys/net/ipv4/ 配下に存在する。デフォルト値は多くの場合、現代のクラウドネイティブな環境には長すぎる(tcp_keepalive_time がデフォルトで7200秒=2時間という設定は、今の時代にはあまりに悠長だ)。
# 現在の設定値を確認する
sysctl net.ipv4.tcp_keepalive_time
sysctl net.ipv4.tcp_keepalive_intvl
sysctl net.ipv4.tcp_keepalive_probes
# ベストプラクティス:クラウド環境やLB配下での推奨設定
# 1. 60秒無通信が続いたらプローブを開始
sysctl -w net.ipv4.tcp_keepalive_time=60
# 2. 10秒間隔でプローブを送信
sysctl -w net.ipv4.tcp_keepalive_intvl=10
# 3. 3回失敗したら接続断とみなす
sysctl -w net.ipv4.tcp_keepalive_probes=3
この設定により、接続断をわずか90秒程度で検知できる。これは、ロードバランサーがバックエンドの不調を検知し、トラフィックを切り替えるまでのラグを極小化するために不可欠なチューニングだ。
3. アプリケーション層との「温度差」に注意せよ
ここで重要な知見を一つ。「TCP Keepaliveは、あくまでネットワークレベルの接続確認である」という点だ。
アプリケーション層では、HTTP Keep-Alive(Connection: keep-alive)という概念が存在するが、これはあくまで「HTTPのレスポンス後も同じTCPコネクションを再利用するか」を定義するものに過ぎない。
現場で陥るアンチパターン
多くの開発者が、アプリケーションのタイムアウト設定とTCPのKeepalive設定を混同する。TLSハンドシェイクのオーバーヘッドを避けるためにTCPコネクションを維持したい場合、以下のような設計が重要だ。
- RTT削減: TCP Fast Openを有効化し、ハンドシェイクのラウンドトリップを減らす。
- バッファチューニング:
tcp_rmem/tcp_wmemを適切に設定し、輻輳制御アルゴリズムをbbrに変更する(最近のカーネルならnet.ipv4.tcp_congestion_control=bbrは必須)。
4. セキュリティの視点:ゾンビセッションが招く脆弱性
Keepaliveの設定を怠り、タイムアウトが不適切だと何が起きるか。ファイアウォールのステートテーブルが溢れ、メモリ枯渇によるDoS状態に陥るリスクがある。あるいは、中途半端に残ったセッションを悪用したセッションハイジャックのリスクもゼロではない。
特に、TLSで暗号化された通信において、セッション再開(Session Resumption)を許可している場合、長期間放置されたTCPコネクションはセキュリティ上の脆弱な入り口になり得る。
結論:ネットワークを「飼い慣らす」ということ
Keepaliveは「単なる接続維持」のための機能ではない。ネットワークの荒野を駆け巡るパケットが、どこで、なぜ消えるのかを推測し、カーネルのパラメーターでそれを制御する。これは、インフラアーキテクトにとって「ネットワークの状態を可視化し、支配下に置く」という高度なマニピュレーション技術だ。
教科書的な設定に甘んじるな。自らのアプリケーションが通信する経路の特性(NATのタイムアウト時間、L7 LBのアイドルセッション保持設定)を計測し、それに最適化された値をカーネルに刻み込む。これこそが、ゼロトラスト時代のネットワークエンジニアが持つべき「現場の作法」である。
—
*追記:本稿の設定を商用環境に反映する際は、必ず本番環境と同等のトラフィック負荷を再現したステージング環境で検証してほしい。特に tcp_keepalive_probes の回数を減らしすぎると、一時的な瞬断による「偽の切断」を誤検知するリスクがある。トレードオフを理解した上でのチューニングこそが、プロの仕事だ。*
コメント