本章では、ネットワークを単に「つながる・つながらない」という観点ではなく、 TCP/IP、パケット、ソケット、DNS、ルーティング、MTU、NAT、TLS、 Linuxネットワークスタックなどの内部構造まで掘り下げて解析する。
tcpdump、Wireshark、ss、dig、traceroute、mtrなどのツールを利用し、 「通信が遅い」「接続できない」「特定条件でのみ通信が失敗する」といった問題を、 推測ではなく観測データから特定できる能力を身につけることを目的とする。
1. ネットワーク障害をレイヤーで分解する
高度なネットワーク解析で最も重要なのは、 「ネットワークがおかしい」という曖昧な状態から脱却することである。
通信障害は、OSI参照モデルやTCP/IPモデルを利用してレイヤーごとに分解できる。
Application
↓
HTTP / HTTPS / DNS
↓
TCP / UDP / QUIC
↓
IP
↓
Ethernet
↓
NIC
↓
Physical Network
例えばWeb APIへ接続できない場合でも、原因として以下が考えられる。
- DNS名前解決が失敗している
- ルーティングが存在しない
- TCP接続を確立できない
- TLS Handshakeが失敗している
- HTTPリクエスト後のアプリケーション処理が遅い
障害解析では、どのレイヤーまで正常に処理されているのかを順番に確認する。
2. パケットのカプセル化
アプリケーションが送信したデータは、そのままネットワークへ流れるわけではない。 各プロトコルのヘッダが追加されながら下位レイヤーへ渡される。
Application Data
↓
TCP Segment
↓
IP Packet
↓
Ethernet Frame
↓
Physical Network
受信側では逆方向に処理される。
Ethernet Frame
↓
IP Packet
↓
TCP Segment
↓
Application Data
この構造を理解すると、 パケットキャプチャから通信のどの段階で異常が発生しているのかを追跡できる。
3. TCP 3-Way Handshake
TCPではデータを送信する前に、3-Way Handshakeによって接続を確立する。
Client Server
-------- SYN -------->
<----- SYN / ACK ------
-------- ACK -------->
ESTABLISHED
この3パケットだけでも、多くの接続障害を分析できる。
■ SYNを送信しても応答がない
- Firewallによる破棄
- ルーティング障害
- ネットワーク経路障害
- サーバが到達不能
■ RSTが返ってくる
- 対象ポートでサービスがListenしていない
- 接続が明示的に拒否されている
したがって、Connection TimeoutとConnection Refusedは同じ障害ではない。
4. TCP状態遷移
TCP接続は、接続開始から終了まで複数の状態を遷移する。
- LISTEN
- SYN-SENT
- SYN-RECEIVED
- ESTABLISHED
- FIN-WAIT-1
- FIN-WAIT-2
- CLOSE-WAIT
- CLOSING
- LAST-ACK
- TIME-WAIT
- CLOSED
特定状態の接続が異常に増加している場合、 アプリケーションやネットワークの問題を推測できる。
■ CLOSE-WAITが大量に存在する
相手側からFINを受信しているにもかかわらず、 ローカルアプリケーションがソケットを適切にcloseしていない可能性がある。
■ SYN-RECVが大量に存在する
接続要求を受け取ったものの、Handshakeが完了していない接続が増えている状態である。 ネットワーク異常や大量接続などを調査する必要がある。
■ TIME-WAITが大量に存在する
短時間に大量のTCP接続が生成・終了されている可能性がある。 ただしTIME-WAITはTCPの正常な状態でもあるため、数だけを見て障害と判断してはいけない。
5. ssによるソケット解析
Linuxではssコマンドを利用してソケットの状態を確認できる。
■ TCP全体の統計
ss -s
■ TCP接続一覧
ss -tan
■ Listenポートとプロセス
ss -lntp
■ ESTABLISHEDのみ確認
ss -tan state established
■ TIME-WAITのみ確認
ss -tan state time-wait
接続数だけではなく、TCP状態を分類して確認することで、 接続確立・通信中・切断処理のどこで問題が発生しているのかを分析できる。
6. Sequence NumberとAcknowledgment Number
TCPはSequence NumberとAcknowledgment Numberを利用して、 データの順序と到達確認を管理する。
Sender
SEQ = 1000
Data = 500 bytes
↓
Receiver
ACK = 1500
ACK=1500は、 「1499まで受信したため、次は1500から送ってほしい」という意味になる。
この仕組みによりTCPは、 パケット損失や順序入れ替わりが発生しても信頼性のあるデータ転送を実現できる。
7. TCP Retransmission
送信したデータが正常に届かなかった場合、 TCPではRetransmission(再送)が発生する。
Client Server
Packet A ------------------>
Packet B -------- X
Packet C ------------------>
<---------------- ACK
Packet B ------------------>
Retransmission
再送が頻繁に発生すると、 通信速度やレスポンスタイムが大きく悪化する。
■ 主な原因
- ネットワーク混雑
- パケットロス
- NICやネットワーク機器の問題
- キューの飽和
- 無線通信品質の低下
- 経路上でのパケット破棄
回線の最大帯域が十分でも、 Packet Lossによって実効スループットが低下することがある。
8. RTT・Latency・Jitter
■ Latency
データがネットワーク上を移動するときに発生する遅延である。
■ RTT(Round Trip Time)
送信元から宛先へデータを送り、 応答が戻るまでの往復時間である。
■ Jitter
Latencyの時間的な変動を表す。
例えばRTTが平均20msでも、 ある瞬間は5ms、別の瞬間は100msとなる場合、 平均値だけでは通信品質を正しく評価できない。
Jitterは特に以下のシステムで重要となる。
- VoIP
- ビデオ会議
- オンラインゲーム
- リアルタイム動画配信
- リアルタイム制御システム
9. TCP Windowとフロー制御
TCPでは、受信側が処理可能なデータ量をWindowとして送信側へ通知する。
Sender Receiver
DATA --------------------->
<------ ACK + Window
これにより、受信側が処理できない量のデータを送信することを防ぐ。 この仕組みをFlow Controlという。
受信Windowが極端に小さくなると、 回線帯域に余裕があってもスループットが低下する。
10. Bandwidth-Delay Product
高帯域・高遅延ネットワークでは、 Bandwidth-Delay Product(BDP)が重要となる。
BDP = Bandwidth × RTT
BDPは、通信経路上に同時に存在できるデータ量を考えるための指標である。
例えば高速回線であってもRTTが大きく、 TCP Windowが十分に確保されていなければ、 回線能力を最大限利用できない場合がある。
特に長距離・大容量データ転送では重要な概念となる。
11. TCP輻輳制御
TCPでは、ネットワークの混雑状態に応じて送信速度を調整する Congestion Control(輻輳制御)が行われる。
■ 代表的な概念
- Congestion Window(cwnd)
- Slow Start
- Congestion Avoidance
- Fast Retransmit
- Fast Recovery
送信側はACKやPacket Lossなどからネットワーク状態を推測し、 送信可能なデータ量を動的に調整する。
■ CUBIC
Linuxで広く利用されるLoss-basedな輻輳制御アルゴリズムである。
■ BBR
帯域幅やRTTを推定しながら送信量を制御する方式であり、 高帯域・高遅延環境などで利用される。
単純な回線速度だけではなく、 TCPの輻輳制御まで理解することで実効性能を説明できるようになる。
12. tcpdumpによるパケットキャプチャ
tcpdumpはLinux上を流れるパケットを直接取得するための代表的なツールである。
■ インターフェース指定
tcpdump -i eth0
■ TCP 443番ポートのみ
tcpdump -i eth0 tcp port 443
■ 特定ホストとの通信
tcpdump -i eth0 host 192.0.2.10
■ pcapファイルとして保存
tcpdump -i eth0 -w capture.pcap
取得したpcapファイルはWiresharkなどで詳細に解析できる。
本番環境のパケットには認証情報や個人情報などが含まれる可能性があるため、 取得権限・保存先・保持期間・共有範囲を厳格に管理する必要がある。
13. Wiresharkによる詳細解析
Wiresharkでは、キャプチャした通信をプロトコル単位で詳細に確認できる。
- Source / Destination IP
- Source / Destination Port
- TCP Flags
- Sequence Number
- Acknowledgment Number
- Window Size
- Retransmission
- RTT
- TLS Handshake
- DNS Query / Response
例えばTCP再送を調査する場合、 WiresharkのDisplay Filterを利用して対象パケットを絞り込める。
tcp.analysis.retransmission
パケット数が数万件存在する場合でも、 フィルタリングによって必要な通信だけを抽出できる。
14. DNS名前解決の内部構造
DNS障害はWebサービス全体を停止させる可能性があるため、 高度なネットワーク解析では名前解決の内部構造も理解する必要がある。
Client
↓
Recursive Resolver
↓
Root DNS
↓
TLD DNS
↓
Authoritative DNS
↓
IP Address
■ DNSキャッシュ
取得したDNS情報はTTLに基づいてキャッシュされる。
DNSレコードを変更しても、 TTLが切れるまでは古い情報が利用される可能性がある。
15. digによるDNS解析
■ 基本的な名前解決
dig example.com
■ IPv4アドレス
dig example.com A
■ IPv6アドレス
dig example.com AAAA
■ DNS解決経路
dig +trace example.com
+traceを利用すると、 Root DNSからAuthoritative DNSまでの委任関係を追跡できる。
DNS障害では「名前解決できるか」だけではなく、 応答時間、TTL、回答レコード、利用しているResolverなども確認する。
16. Linuxルーティングテーブル
LinuxカーネルはRouting Tableを参照して、 パケットをどの経路へ送信するか判断する。
ip route
ルーティングテーブルには主に以下の情報が含まれる。
- Destination
- Gateway
- Interface
- Metric
ルーティングでは基本的にLongest Prefix Matchによって、 最も具体的な経路が選択される。
複数の経路が存在するシステムでは、 「想定したインターフェースから通信が出ているか」という確認も重要となる。
17. tracerouteとmtrによる経路解析
インターネット通信では複数のルータを経由して宛先へ到達する。
Client
↓
Router A
↓
Router B
↓
Router C
↓
Server
■ traceroute
traceroute example.com
宛先までの経路を確認する。
■ mtr
mtr example.com
経路・RTT・Lossなどを継続的に観測できる。
ただし、中間ルータは診断用パケットへの応答を制限することがある。 そのため、途中のホップだけLoss率が高く表示されても、 後続ホップと最終宛先にLossがなければ通信障害とは限らない。
18. MTUとPath MTU Discovery
MTU(Maximum Transmission Unit)は、 ネットワークインターフェースが一度に扱えるIPパケットサイズの上限である。
Ethernetでは1500 bytesが一般的である。
通信経路の途中に小さなMTUを持つネットワークが存在すると、 パケットサイズが問題になる場合がある。
■ Path MTU Discovery
送信元から宛先までの経路で利用可能な最大パケットサイズを判断する仕組みである。
■ MTU問題で発生する代表的な症状
- pingは通るのにWeb通信が失敗する
- 小さなHTTPレスポンスは成功する
- 大きなデータ転送だけ停止する
- VPN接続時だけ通信が不安定になる
- TLS通信が途中で停止する
MTU問題はアプリケーション障害と誤認しやすいネットワーク障害の一つである。
19. NATの内部構造
NAT(Network Address Translation)は、 通信時にIPアドレスなどを変換する仕組みである。
Private Network
10.0.0.10:50001
10.0.0.11:50002
10.0.0.12:50003
↓
NAT
↓
203.0.113.10
↓
Internet
複数の内部ホストが単一の外部IPアドレスを共有する場合、 ポート番号などを利用して通信を識別する。
大量の外向き通信が存在するシステムでは、 NATそのものがスケーラビリティ上の制約となる場合がある。
20. Connection Tracking
Linuxではconntrackによって、 ネットワーク接続の状態を追跡できる。
Connection Trackingでは概念的に以下のような情報が管理される。
- 送信元IP
- 送信元ポート
- 宛先IP
- 宛先ポート
- プロトコル
- 接続状態
大量の接続を処理するサーバでは、 Connection Tracking Tableの容量も考慮する必要がある。
CPUやメモリに余裕があっても、 ネットワークスタック内部の状態管理がボトルネックになる場合がある。
21. Ephemeral Port Exhaustion
TCPクライアントが外部へ接続するとき、 OSは一時的な送信元ポートであるEphemeral Portを利用する。
192.0.2.10:49152 → API Server:443
192.0.2.10:49153 → API Server:443
192.0.2.10:49154 → API Server:443
短時間に大量の接続を作成すると、 利用可能な送信元ポートが不足する可能性がある。
■ 発生しやすい設計
- 大量の外部API通信
- HTTP Connection Poolを利用していない
- Keep-Aliveを利用していない
- 大量の短時間TCP接続を生成する
- NAT配下から大量の通信を行う
この問題はサーバスペックを単純に増強しても解決できない場合がある。
22. HTTP Keep-AliveとConnection Pool
毎回TCP接続を新しく作成すると、 HandshakeやTLS処理などのオーバーヘッドが発生する。
Request
↓
TCP Handshake
↓
TLS Handshake
↓
HTTP Request
↓
HTTP Response
↓
Connection Close
これを大量に繰り返すことは効率が悪い。
Keep-AliveやConnection Poolを利用すると、 既存接続を再利用できる。
Connection
├─ Request 1
├─ Request 2
├─ Request 3
└─ Request 4
高負荷APIでは、 アプリケーションコードだけではなく接続再利用戦略も重要な性能設計となる。
23. HTTP/1.1・HTTP/2・HTTP/3
■ HTTP/1.1
- TCP上で動作
- Keep-Aliveによる接続再利用
- 複数接続を利用した並列化が行われる場合がある
■ HTTP/2
- TCP上で動作
- 1つの接続上で複数ストリームを多重化
- バイナリフレーミング
- HPACKによるヘッダ圧縮
■ HTTP/3
- QUICを利用
- UDPを基盤として動作
- TLS 1.3を統合
- ストリーム単位で独立性を高める
HTTP/2ではTCPレイヤーでパケットロスが発生すると、 同一TCP接続上の複数ストリームが影響を受ける可能性がある。
QUICではストリームごとに配送状態を管理できるため、 あるストリームのパケット損失が他のストリームを直接停止させる問題を軽減できる。
24. TLS Handshake
HTTPSでは、HTTP通信の前にTLSによって安全な通信路を確立する。
Client
|
| TCP / QUIC Connection
|
| TLS Handshake
|
| Encrypted HTTP
|
Server
TLSでは主に以下の処理が行われる。
- 利用する暗号方式の決定
- サーバ証明書の提示
- 証明書の検証
- 鍵交換
- セッション鍵の確立
- 暗号化通信の開始
HTTPSだけ接続できない場合には、 TCP接続だけではなくTLSレイヤーを調査する必要がある。
■ 代表的なTLS障害
- 証明書の有効期限切れ
- ホスト名不一致
- 証明書チェーンの問題
- 対応TLSバージョンの不一致
- 暗号スイートの不一致
25. Linuxネットワークスタック
Linuxでは、NICが受信したパケットが直接アプリケーションへ渡されるわけではない。
Network
↓
NIC
↓
Device Driver
↓
Kernel Network Stack
↓
IP
↓
TCP / UDP
↓
Socket Buffer
↓
Application
送信時には概ね逆方向に処理される。
高負荷サーバでは以下の要素が性能に影響する。
- NIC性能
- Receive / Transmit Queue
- 割り込み処理
- SoftIRQ
- Socket Buffer
- CPU処理能力
- パケット処理速度
したがってネットワーク性能問題は、 必ずしも物理回線や帯域幅だけが原因とは限らない。
26. Socket Bufferとバックプレッシャー
アプリケーションとネットワークスタックの間にはSocket Bufferが存在する。
Network
↓
Kernel
↓
Receive Buffer
↓
Application
アプリケーションの処理速度が受信速度に追いつかない場合、 Receive Bufferへデータが蓄積する。
バッファが逼迫すると、 TCP Windowの縮小などを通じて送信側へ処理能力の低下が伝達される。
このように下流の処理能力に合わせて上流側を抑制する考え方を Backpressureと呼ぶ。
大規模システムでは、 ネットワークだけではなくメッセージングやストリーム処理でも重要な設計概念となる。
27. SYN BacklogとAccept Queue
サーバがTCP接続を受け付ける際には、 接続状態を管理するキューが関係する。
Client
↓ SYN
SYN Backlog
↓ Handshake Complete
Accept Queue
↓
Application accept()
大量の接続要求が短時間に発生した場合、 アプリケーションが十分な速度で接続を処理できなければ、 キューが飽和する可能性がある。
この場合、CPU使用率だけを確認しても原因を特定できないことがある。
高トラフィックシステムでは、 TCP接続数・Listen Queue・アプリケーションのaccept処理まで含めて解析する必要がある。
28. ネットワーク障害解析の基本フロー
例えば「APIへのアクセスが遅い」という障害が発生した場合、 以下の順序で調査する。
- DNS名前解決が正常か確認する
- 宛先IPが正しいか確認する
- ルーティングを確認する
- TCP接続確立時間を確認する
- TLS Handshake時間を確認する
- RTTとJitterを確認する
- Packet LossとRetransmissionを確認する
- TCP Windowを確認する
- Socket状態と接続数を確認する
- HTTPレスポンス時間を確認する
- アプリケーション処理時間を確認する
- DBや外部APIなど依存サービスを確認する
重要なのは、最初から「ネットワークが原因」と決めつけないことである。
29. 実践障害解析:APIレスポンスが50msから2秒になった
通常50ms程度で応答するAPIが、 突然2秒以上かかるようになったケースを考える。
Step 1:DNSを確認する
dig api.example.com
名前解決時間と返却されたIPアドレスを確認する。
Step 2:ルーティングを確認する
ip route
想定した経路が利用されているか確認する。
Step 3:経路品質を確認する
mtr api.example.com
RTTやPacket Loss、経路変化を確認する。
Step 4:TCP状態を確認する
ss -tan
接続数、TIME-WAIT、CLOSE-WAIT、SYN-RECVなどを確認する。
Step 5:パケットを取得する
tcpdump -i eth0 host 192.0.2.10 -w api.pcap
WiresharkでHandshake、Retransmission、Window、RTTなどを確認する。
Step 6:TLSを確認する
TCP接続が高速に確立されているにもかかわらず、 HTTPS接続開始まで時間がかかる場合にはTLSレイヤーを調査する。
Step 7:アプリケーションへ調査範囲を移す
ネットワーク上の通信が正常で、 HTTPリクエスト送信後からレスポンスまでが遅い場合には、 DB・外部API・スレッドプール・ロック・I/Oなどを調査する。
このように各処理時間を分解することで、 「APIが遅い」という現象を具体的なボトルネックへ変換できる。
30. 応用エンジニアに求められるネットワーク解析能力
基礎レベルでは、 「pingが通る」「ポートが開いている」といった確認でも一定の切り分けが可能である。
しかし応用レベルでは、 より具体的な説明が求められる。
- SYN送信後にSYN/ACKが返っていない
- TCP Retransmissionが継続的に発生している
- 平均RTTではなくJitterが増大している
- Receive Window縮小によってスループットが制限されている
- Path MTUの問題で特定サイズ以上の通信が失敗している
- DNS Resolverの応答遅延が全体Latencyを増加させている
- Ephemeral Portが逼迫して新規接続を生成できない
- Connection Trackingがボトルネックになっている
- TLS Handshakeで接続処理が停止している
- Socket Bufferの飽和によってBackpressureが発生している
- Accept Queueが飽和して新規接続処理が遅延している
ネットワークを「通信経路」ではなく、 複数のプロトコル・キュー・状態機械・OS処理が連携するシステムとして理解することが重要である。
本章のゴール
本章のゴールは、 ネットワーク通信をブラックボックスとして扱わず、 パケット・プロトコル・Linuxカーネルの挙動から障害原因を分析できるようになることである。
- TCP/IP通信をパケット単位で説明できる
- 3-Way Handshakeから接続障害を判断できる
- TCP状態遷移を利用して異常接続を分析できる
- Sequence / ACK / Retransmissionを理解できる
- RTT・Latency・Jitterを区別できる
- TCP Windowと輻輳制御を説明できる
- DNS・Routing・MTU・NATを横断して調査できる
- Ephemeral Port Exhaustionを理解できる
- HTTP/2・HTTP/3・QUICの通信特性を理解できる
- TLS Handshakeを通信障害の観点から解析できる
- Linuxネットワークスタックの内部構造を理解できる
- Socket BufferやAccept Queueまで含めて性能を分析できる
- tcpdump・Wireshark・ss・dig・mtrを使い分けられる
- ネットワーク障害とアプリケーション障害の境界を判断できる
これにより、 「ネットワークが遅い」という曖昧な表現ではなく、 どのレイヤーで、どのプロトコルが、どのような状態になっているのかを 技術的根拠とともに説明できるようになる。