conntrackコマンドでLinuxのNAT接続追跡を診断する方法|nf_conntrack_maxが上限に達した時の調査と恒久対処

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxトラブルシューティング > conntrackコマンドでLinuxのNAT接続追跡を診断する方法|nf_conntrack_maxが上限に達した時の調査と恒久対処
「外部への接続が突然つながらなくなった。でもネットワーク自体は死んでいないし、ポートも開いている。いったい何が起きているのか」
「サーバーの高負荷時や大量アクセス時だけ間欠的に通信が失敗する。原因の手がかりすらつかめない」

こういったトラブルの原因として見落とされがちなのが、Linuxカーネルの接続追跡テーブル(conntrackテーブル)の枯渇です。NATを使う環境では、カーネルがすべての通信セッションを内部テーブルに記録しています。このテーブルが上限に達すると、新しい接続が静かにドロップされ、アプリケーション側にはタイムアウトとして現れます。

この記事では、conntrackコマンドを使ってLinuxのNAT接続追跡テーブルを調べる方法を解説します。インストールから基本操作、nf_conntrack_maxが上限に達した際の症状確認、dmesgでのドロップ検知、sysctl永続化、タイムアウト調整まで、RHEL 9.4 / Ubuntu 24.04 LTSで動作確認した実践手順をお伝えします。

この記事のポイント

・nf_conntrack_max枯渇は "table full, dropping packet" というdmesgログで検知できる
・現在の使用数は /proc/sys/net/netfilter/nf_conntrack_count で確認できる
・nf_conntrack_maxはRAM(GB)×65536を目安にsysctlで増やして永続化する
・TCP ESTABLISHED のタイムアウトを短縮するとエントリを大幅に削減できる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

conntrackとNetfilterの接続追跡の仕組み

LinuxカーネルのNetfilterサブシステムは、iptables・nftables・NAT(IPマスカレード)を処理するフレームワークです。NAT環境では、送信元IPアドレスを変換した通信の戻りパケットを正しく元のホストへ返すために、すべての通信セッションを「接続追跡テーブル」(conntrackテーブル)に記録しています。

各エントリには以下の情報が格納されています。

・プロトコル(TCP/UDP/ICMP)
・送信元IP・ポートと宛先IP・ポート(オリジナル方向と返信方向の2タプル)
・接続状態(NEW/ESTABLISHED/RELATED/INVALID)
・エントリの残存タイムアウト(秒)

テーブルの最大エントリ数は nf_conntrack_max で制限されており、この上限に達すると新しい接続のパケットがドロップされます。NATを使うファイアウォール・ロードバランサ・VPNゲートウェイなど、多くのセッションを同時に扱うサーバーでは特に注意が必要です。

conntrackコマンドのインストールと基本操作

1. インストール方法

conntrack コマンドは conntrack-tools パッケージに含まれています。RHEL系とDebian系でインストール方法が異なります。

# RHEL 9 / AlmaLinux 9 / Rocky Linux 9 sudo dnf install conntrack-tools -y # Ubuntu 24.04 / Debian 12 sudo apt install conntrack -y # インストール確認 conntrack --version # conntrack v1.4.8 (conntrack-tools)

2. 接続追跡テーブルを一覧表示する(conntrack -L)

カーネルが現在追跡しているセッションを一覧表示するには conntrack -L を使います。root権限またはsudoが必要です。

sudo conntrack -L # tcp 6 431994 ESTABLISHED src=192.168.1.100 dst=10.0.0.1 sport=51234 dport=443 \ # src=10.0.0.1 dst=203.0.113.10 sport=443 dport=51234 [ASSURED] mark=0 use=1 # tcp 6 55 TIME_WAIT src=192.168.1.200 dst=8.8.8.8 sport=47231 dport=53 \ # src=8.8.8.8 dst=203.0.113.10 sport=53 dport=47231 [ASSURED] mark=0 use=1 # udp 17 28 src=192.168.1.100 dst=8.8.4.4 sport=34567 dport=53 \ # src=8.8.4.4 dst=203.0.113.10 sport=53 dport=34567 [ASSURED] mark=0 use=1 # conntrack v1.4.8 (conntrack-tools): 8412 flow entries have been shown.

出力の読み方を説明します。

・先頭の tcp はプロトコル名、次の 6 はIPプロトコル番号
431994 はこのエントリが消えるまでの残り秒数(タイムアウト)
ESTABLISHED はTCP接続状態
src=... dst=... が2セット並ぶのはオリジナル方向と返信方向の両タプル
[ASSURED] は双方向パケットが確認済みであることを示す

3. プロトコルやIPでフィルタリングする

大量のエントリがある場合、絞り込み検索が有効です。よく使うフィルタオプションを紹介します。

# TCPのみ表示 sudo conntrack -L -p tcp # 特定の宛先ポートのエントリを表示(例: HTTPS=443) sudo conntrack -L -p tcp --dport 443 # 特定の送信元IPからのエントリを表示 sudo conntrack -L --src 192.168.1.100 # ESTABLISHED 状態のTCPのみ sudo conntrack -L -p tcp --state ESTABLISHED # 現在のエントリ総数だけを表示 sudo conntrack -C # 8412

4. リアルタイムでイベントを監視する(conntrack -E)

接続の新規追加・破棄をリアルタイムで監視するには -E(event)オプションを使います。接続が頻繁にドロップされているかを確認するときに有効です。

# 新規接続の追加イベントを監視(Ctrl+Cで停止) sudo conntrack -E --event-mask NEW # エントリ破棄イベントを監視 sudo conntrack -E --event-mask DESTROY

nf_conntrack_maxが上限に達した時のエラーと確認手順

1. 典型的な症状

conntrackテーブルが満杯になると、以下のような症状が現れます。

・新規TCP接続のSYNパケットがドロップされ、クライアント側でConnection timed outになる
・UDPのDNS問い合わせがタイムアウトし、名前解決の失敗が散発する
・既存のESTABLISHED接続は継続するが、新しい接続だけが失敗する
・高トラフィック時や夜間バッチ実行中に間欠的に発生し、再現が難しい

2. dmesgでドロップログを確認する

カーネルはconntrackテーブルが満杯になった際に、dmesgに記録を残します。まずここを確認するのが最初のステップです。

# nf_conntrack関連のカーネルログを確認 sudo dmesg | grep nf_conntrack # [1234567.891234] nf_conntrack: nf_conntrack: table full, dropping packet # [1234568.012345] nf_conntrack: nf_conntrack: table full, dropping packet # journalctlでも確認できる sudo journalctl -k | grep nf_conntrack | tail -20

"table full, dropping packet" というメッセージが出ていれば、conntrackテーブルの枯渇が確定です。

3. 現在の使用数と上限値を確認する

現在のエントリ数と最大値を並べて確認することで、どの程度テーブルが埋まっているかがわかります。

# 現在の追跡エントリ数 cat /proc/sys/net/netfilter/nf_conntrack_count # 130891 # 設定されている最大値 cat /proc/sys/net/netfilter/nf_conntrack_max # 131072 # 使用率の確認(bashで計算) COUNT=$(cat /proc/sys/net/netfilter/nf_conntrack_count) MAX=$(cat /proc/sys/net/netfilter/nf_conntrack_max) echo "使用率: $((COUNT * 100 / MAX))% ($COUNT / $MAX)" # 使用率: 99% (130891 / 131072)

使用率が80%を超えていたら、本番トラフィックのピーク時に枯渇するリスクが高いと判断してください。

nf_conntrack_maxを増やして恒久化する方法

1. 適切な上限値の目安

Linuxカーネルのドキュメントでは、nf_conntrack_maxの適切な値として「実装メモリ量(MB)/ 128 * 8」が参考値とされています。現場での経験からは、搭載メモリ(GB)× 65536 を起点にトラフィック実測で調整するのが現実的です。

・メモリ 4GB のサーバー: 4 × 65536 = 262144
・メモリ 8GB のサーバー: 8 × 65536 = 524288
・メモリ 16GB のサーバー: 16 × 65536 = 1048576

ただし、エントリ1件あたり約400バイト消費するため、最大値を上げすぎると高負荷時にメモリを圧迫します。増やす幅は現在の最大値の2~4倍を上限に、段階的に調整することを推奨します。

2. sysctlで一時変更と永続化

# 現在の最大値を確認 sysctl net.netfilter.nf_conntrack_max # net.netfilter.nf_conntrack_max = 131072 # 一時的に変更(再起動で元に戻る) sudo sysctl -w net.netfilter.nf_conntrack_max=262144 # 永続化:/etc/sysctl.d/ 配下に専用ファイルを作成する sudo tee /etc/sysctl.d/99-conntrack.conf <<'EOF' net.netfilter.nf_conntrack_max = 262144 EOF # 設定を反映(再起動なしで有効化) sudo sysctl -p /etc/sysctl.d/99-conntrack.conf # 変更を確認 cat /proc/sys/net/netfilter/nf_conntrack_max # 262144

3. nf_conntrack_hashsizeも合わせて調整する

conntrackはハッシュテーブルでエントリを管理しており、ハッシュテーブルサイズ(hashsize)はnf_conntrack_maxの1/4が推奨値です。maxだけ増やしてhashsizeを放置すると、同一バケツに多くのエントリが集中してルックアップ性能が低下します。

# 現在のhashsizeを確認 cat /sys/module/nf_conntrack/parameters/hashsize # 32768 # 実行中のカーネルへ即時反映(再起動で元に戻る) echo 65536 | sudo tee /sys/module/nf_conntrack/parameters/hashsize # 永続化:modprobeの設定ファイルに記載する echo "options nf_conntrack hashsize=65536" | sudo tee /etc/modprobe.d/nf_conntrack.conf # 設定確認 cat /etc/modprobe.d/nf_conntrack.conf # options nf_conntrack hashsize=65536

hashsizeは nf_conntrack_max ÷ 4 が目安です。上の例では max=262144 に対して hashsize=65536 と設定しています。

conntrackエントリのタイムアウトを調整して無駄なエントリを削減する

nf_conntrack_maxを増やすだけでなく、不要なエントリを早めに削除することも有効な対策です。特にTCP ESTABLISHEDのデフォルトタイムアウトは432000秒(5日間)と非常に長く、長時間接続していないセッションのエントリが大量に残留することがあります。

1. 現在のタイムアウト値を確認する

# TCP各状態のタイムアウト値を一覧確認 sysctl -a 2>/dev/null | grep nf_conntrack_tcp_timeout # net.netfilter.nf_conntrack_tcp_timeout_close = 10 # net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60 # net.netfilter.nf_conntrack_tcp_timeout_established = 432000 # net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120 # net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30 # net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60 # net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120 # net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120

2. ESTABLISHED タイムアウトを短縮する

通常の業務システムでは、ESTABLISHED接続が5日間完全にアイドルになることはほとんどありません。サービスの性質に応じて1時間(3600秒)~1日(86400秒)程度に短縮するのが現実的です。

# ESTABLISHED タイムアウトを1時間(3600秒)に変更 sudo sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600 # 永続化(先ほど作成した 99-conntrack.conf に追記) cat >> /etc/sysctl.d/99-conntrack.conf <<'EOF' net.netfilter.nf_conntrack_tcp_timeout_established = 3600 net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30 EOF sudo sysctl -p /etc/sysctl.d/99-conntrack.conf

TIME_WAITのタイムアウトも120秒から30秒程度に短縮すると、大量の短命TCP接続がある環境で効果的です。ただし、短くしすぎると通信の正常終了確認ができなくなるため、最低でも10秒以上は残してください。

3. 変更後のエントリ数推移を確認する

タイムアウト変更後は、conntrackエントリ数が減少しているかを一定時間観察します。

# 5秒間隔でエントリ数を監視 watch -n 5 'echo "conntrack count: $(cat /proc/sys/net/netfilter/nf_conntrack_count) / $(cat /proc/sys/net/netfilter/nf_conntrack_max)"' # conntrack count: 87432 / 262144 # conntrack count: 84119 / 262144 # conntrack count: 81206 / 262144

本記事のまとめ

conntrackテーブルの枯渇は、症状(接続タイムアウト)だけを見るとネットワーク障害やアプリケーション障害と見分けがつかず、原因特定まで時間がかかりがちです。以下のチェック手順を定番の初動調査フローとして覚えておくことを推奨します。

確認項目 コマンド・ファイル
テーブル枯渇ログの確認 sudo dmesg | grep nf_conntrack
現在のエントリ数と上限 cat /proc/sys/net/netfilter/nf_conntrack_count
最大値の確認 cat /proc/sys/net/netfilter/nf_conntrack_max
エントリ一覧 sudo conntrack -L
特定プロトコルの絞り込み sudo conntrack -L -p tcp --state ESTABLISHED
最大値の増加(一時) sudo sysctl -w net.netfilter.nf_conntrack_max=262144
永続化ファイルの作成 /etc/sysctl.d/99-conntrack.conf
hashsizeの調整(永続化) /etc/modprobe.d/nf_conntrack.conf
ESTABLISHEDタイムアウト短縮 net.netfilter.nf_conntrack_tcp_timeout_established=3600

「nf_conntrack_maxを増やす」「タイムアウトを短縮する」の2つを組み合わせることで、急増トラフィックとアイドルセッション残留の両方に対処できます。定期的に conntrack -C でエントリ数をモニタリングし、使用率が70%を超えたら事前に増量するよう運用設計しておくことが重要です。

通信障害の原因をカーネル層から読み解くには、Linux基盤の体系的な理解が欠かせません

conntrackやNetfilterの動作を正確に把握するためには、Linuxのネットワーク処理・プロセス管理・ファイルシステムを体系的に学ぶことが重要です。断片的なコマンド知識を積み上げるより、現場で実際に使われる設計パターンを一度体系的に身につけることで、障害の本質を素早く特定できるようになります。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。