ネットワーク
概要
DNS・TCP・TLS・HTTP を一本の流れで理解する
Web、API、動画配信、チャット。現代のシステムはほとんどネットワークの上で動いています。このテキストでは、ネットワークを層に分けて理解し、実際の Web 通信がどのように成立するかを追います。
この章で重視すること
- DNS、TCP、TLS、HTTP を別々の単語で終わらせず、1本の通信として追う
- トラブル時に「どの層が怪しいか」を切り分ける
- HTTP/2 や HTTP/3 の"何が変わったのか"を意味と運び方の違いで捉える
- TCP の輻輳制御の進化(Reno → CUBIC → BBR → BBRv3)を実務的に理解する
- DNS、TLS の詳細仕様と実装トレードオフを深掘りする
- CDN、ロードバランサ、ファイアウォール、VPN などの実装戦略を一通り扱う
目次
- ネットワークの歴史
- 層に分ける理由
- OSI 参照モデルと TCP/IP の対応
- 物理層とリンク層
- ネットワーク層(IPv4・IPv6)
- ルーティングプロトコル
- パケットとルーティング
- トランスポート層の概観
- TCP の詳細
- UDP の詳細
- ソケットプログラミング
- DNS の詳細
- DHCP と ARP
- HTTP の進化
- HTTP/1.1 の詳細
- HTTP/2 の詳細
- HTTP/3 と QUIC
- TLS の詳細
- WebSocket と Server-Sent Events
- ネットワークセキュリティの基礎
- プロキシと逆プロキシ
- CDN と負荷分散
- ファイアウォールと VPN
- ネットワーク仮想化
- ネットワーク観測とトラブルシューティング
- 性能チューニングと最適化
- 2025-2026 の動向
- 参考文献
ネットワークの歴史
ネットワーク技術の進化を理解すると、なぜ今の設計になっているのかが見えやすくなります。
ARPANET から TCP/IP へ
1969 年、アメリカ国防総省の ARPA(Advanced Research Projects Agency)が資金を出し、複数の大学をつなぐ実験的ネットワーク ARPANET が誕生しました。
-
初期(1960-70s): ARPANET では、メッセージが複数のパケットに分割され、ルータ経由で目的地に届けられるという考え方が確立されました。これは、中央の交換機に依存する電話網と異なり、障害時の耐性が高い設計です。
-
TCP/IP の登場(1983): 1983 年、ARPANET は標準通信プロトコルとして TCP/IP を採用しました。これは、異なるネットワーク同士を相互接続するための統一された仕組みを提供しました。
World Wide Web と HTTP/0.9
1989 年、CERN の Tim Berners-Lee が、情報共有システムとして World Wide Web を発明しました。HTTP/0.9 は極めてシンプルで、GET メソッドのみ、レスポンスはテキストのみ、という特徴がありました。
GET /page.html\r\n
\r\n
レスポンスは HTML をそのまま返すだけでした。ステータスコード、ヘッダ、メタデータという概念は存在しませんでした。
HTTP/1.0 と メタデータの導入
HTTP/1.0(1996)では、リクエスト・レスポンスの構造が確立されました。
GET /page.html HTTP/1.0
Host: example.com
User-Agent: Mozilla/1.0
レスポンスは以下のように構造化されました:
HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 1234
<html>...</html>
ステータスコード、ヘッダフィールドが導入され、複数の型をサポートできるようになりました。ただし接続は 1 リクエストごとに切断される(コネクションレス)という特徴がありました。
HTTP/1.1 と 持続接続
HTTP/1.1(1997・1999)では、デフォルトで 1 本の TCP 接続を複数リクエストで再利用する「持続接続」(Keep-Alive)が標準化されました。これにより、接続確立のオーバーヘッドが大幅に削減されました。
GET /page1.html HTTP/1.1
Host: example.com
Connection: keep-alive
(接続は再利用)
GET /page2.html HTTP/1.1
Host: example.com
(接続を閉じる)
同時に、キャッシュ制御(Cache-Control、ETag)、チャンク転送(Transfer-Encoding: chunked)、条件付き GET(If-Modified-Since)などの機能が追加されました。
層に分ける理由
ネットワークは複雑なので、役割ごとに層に分けます。
これにより、「どこが怪しいか」を切り分けやすくなります。
なぜ層が必要なのか
層の考え方は、ネットワークだけの特殊事情ではありません。複雑な仕組みを
- 名前解決(DNS、どの IP へ届ける?)
- 転送(TCP/UDP、どう届ける?)
- 暗号化(TLS、安全に届ける?)
- アプリの意味(HTTP、何を届ける?)
のように分けることで、変更に強くし、責任範囲を明確にします。
たとえば HTTP を理解したいからといって、毎回ルータの実装まで意識する必要はありません。逆に TCP の再送を考えるとき、HTTP のステータスコードは脇へ置けます。層とは、考える単位を分ける技法 です。
OSI 参照モデルと TCP/IP の対応
ネットワークの層構造を理解するには、OSI 参照モデルと実際の TCP/IP スタックの関係を把握することが重要です。
| 層 | OSI 名称 | 主な機能 | TCP/IP での対応 |
|---|---|---|---|
| 7 | アプリケーション | ユーザ向けサービス | HTTP, SMTP, DNS, SSH |
| 6 | プレゼンテーション | データ表現変換 | TLS, gzip |
| 5 | セッション | セッション管理 | HTTP ステートレス + Cookie |
| 4 | トランスポート | エンドツーエンド転送 | TCP, UDP, QUIC |
| 3 | ネットワーク | ルーティング | IPv4, IPv6, ICMP |
| 2 | データリンク | フレーム送受信 | Ethernet, Wi-Fi, PPP |
| 1 | 物理 | 物理伝送 | 光ファイバ、銅線、電波 |
実務では TCP/IP モデル(4 層)のほうが使われることが多いです:
- アプリケーション層(5-7 層をまとめる)
- トランスポート層(4 層)
- インターネット層(3 層)
- リンク層(2-1 層をまとめる)
物理層とリンク層
物理層の進化
データを電気信号として物理的に送受信する層です。
銅線(イーサネット)
10Base-T(10 Mbps、CAT3)→ 100Base-TX(100 Mbps、CAT5)
→ 1000Base-T(1 Gbps、CAT5e)→ 10GBase-T(10 Gbps、CAT6A)
RJ-45 コネクタで接続され、距離は通常 100m が目安です。
光ファイバ
シングルモード(遠距離・高速)→ 100km 以上
マルチモード(短距離・低コスト)→ 2km 程度
データセンタ間の長距離リンクには光ファイバが使われます。現在、400 Gbps リンクも実装されつつあります。
無線(Wi-Fi・5G・衛星)
Wi-Fi の進化:
802.11a/b/g(<54 Mbps)
→ 802.11n(Wi-Fi 4, 600 Mbps)
→ 802.11ac(Wi-Fi 5, 3.5 Gbps)
→ 802.11ax(Wi-Fi 6, 10 Gbps)
→ 802.11be(Wi-Fi 7, 46 Gbps)
5G・衛星:
- 5G: 下り最大 10 Gbps、遅延 1-10ms
- 6G 研究中(2030 年代想定)
- Starlink などの衛星通信:遅延 20-40ms、カバレッジが広い
リンク層(データリンク層)
Ethernet フレーム構造
MAC アドレスは 48 ビット(6 オクテット)で、通常は 00:1A:2B:3C:4D:5E の形式です。
VLAN(仮想 LAN)
物理的には 1 本のケーブルでも、論理的に複数の LAN に分割できます。
VLAN は 802.1Q タグで実装され、フレームに 4B のタグ情報を挿入します。異なる VLAN は直接通信できず、L3 スイッチやルータでルーティングが必要です。
Spanning Tree Protocol(STP)
複数のスイッチが接続されたときにループが生じるのを防ぎます。ツリー構造を動的に計算し、一部のリンクをブロック状態にします。
ネットワーク層(IPv4・IPv6)
IPv4 の構造
IP アドレスは 32 ビット(4 オクテット)で表現されます。
CIDR(クラスレス・ドメイン・ルーティング)
CIDR 記法 192.0.2.0/24 は、最初の 24 ビットがネットワークを表します。
192.0.2.0/24 → ネットワーク: 192.0.2.0
ブロードキャスト: 192.0.2.255
ホスト数: 254(.0 と .255 は予約)
サブネットマスク 255.255.255.0 と同じ意味です。
プライベートアドレス(RFC 1918)
10.0.0.0/8 → 10.0.0.0 ~ 10.255.255.255(1677万個)
172.16.0.0/12 → 172.16.0.0 ~ 172.31.255.255(104万個)
192.168.0.0/16 → 192.168.0.0 ~ 192.168.255.255(65000個)
これらはインターネット上にはルーティングされず、社内ネットワークで自由に使用できます。
IPv6 の構造
IPv6 は 128 ビット(16 オクテット)で、 2^128 個(約 340 兆の兆倍)のアドレスを提供します。
2001:0db8:85a3:0000:0000:8a2e:0370:7334
短縮記法:
2001:db8:85a3::8a2e:370:7334
連続するゼロは :: で 1 回だけ省略できます。
IPv6 アドレスの種類
| タイプ | プレフィックス | 用途 |
|---|---|---|
| ユニキャスト | 2000::/3 | 通常のアドレス |
| リンク・ローカル | fe80::/10 | リンク内通信(自動設定) |
| マルチキャスト | ff00::/8 | 1 対多通信 |
| ループバック | ::1/128 | 自ホスト(IPv4 の 127.0.0.1) |
IPv6 の利点
- アドレス空間が十分:NAT が理論上不要
- ステートレス自動設定:DHCP 不要で EUI-64 などで自動生成
- セキュリティの組み込み:IPsec をサポート
- 簡潔なヘッダ:処理が高速化
ICMP(Internet Control Message Protocol)
IP ネットワークの診断・制御に使われます。
ping(echo request/reply)
→ ネットワーク到達性確認
traceroute(TTL を段階的に増やし、各ルータの応答を観察)
→ ルート経路の確認
IPv6 の NDP(Neighbor Discovery Protocol)
IPv6 では ARP の代わりに NDP が使われます。
- Router Advertisement(RA): ルータが定期的に自身の情報を送信
- Neighbor Solicitation(NS): 「このアドレスは誰か」と問い合わせ(ARP に相当)
ルーティングプロトコル
スタティック・ルーティング
ルータの管理者が手動で経路を設定します。
route add 192.168.1.0/24 via 10.0.0.1
小規模ネットワークでは十分ですが、大規模・複雑なネットワークではスケールしません。
ダイナミック・ルーティング
ルータ同士が自動的に経路情報を交換し、最適な道を見つけます。
RIP(Routing Information Protocol)
最古のダイナミック・ルーティングプロトコル。ホップ数(リンク数)を基準に経路を選択。ただしホップ上限 15 と制限が厳しく、現代ではほぼ使われません。
OSPF(Open Shortest Path First)
リンク状態型プロトコル。各ルータが全ネットワークの位相図を持ち、Dijkstra アルゴリズムで最短経路を計算します。
利点:
- スケーラビリティ(数千ホップ以上対応)
- 収束が高速
- エリア分割で管理性向上
欠点:
- 計算コスト大
- 設定が複雑
BGP(Border Gateway Protocol)
自律システム(AS)間のルーティングに使われます。インターネットの主要なルーティングプロトコルです。
AS1 AS2 AS3
↔ BGP ↔ ↔ BGP ↔
BGP は経路長(ホップ数)だけでなく、ポリシー(経由したくない、優先する)をルーティング決定に含めます。
MPLS(Multiprotocol Label Switching)
IP の前に短いラベルを付加し、ラベル交換でパケットを高速に転送します。QoS や TE(トラフィックエンジニアリング)に用いられます。
IP ヘッダ | MPLS ラベル | ペイロード
パケットとルーティング
データは巨大な塊のままではなく、パケットに分けて送られます。
- 分割: 大きなデータを小さなパケットに分割
- 再送: 失われたパケットだけを再送
- 経路選択: 個々のパケットが異なる経路を取ることもある
ルータは「次の一歩」を決めながらパケットを目的地へ運びます。
ルーティングテーブルと最長一致
ルータは受信パケットの宛先 IP を見て、ルーティングテーブルから「次はどこへ」を決定します。複数のエントリがマッチする場合、最長マスク一致(Longest Prefix Match)が優先されます。
ルーティングテーブル例:
宛先 ネクストホップ
192.168.1.0/24 eth0
192.168.0.0/16 eth1
0.0.0.0/0 10.0.0.1(デフォルトゲートウェイ)
宛先が 192.168.1.5 の場合、192.168.1.0/24 にマッチし eth0 へ送出;192.168.2.5 の場合、192.168.0.0/16 にマッチし eth1 へ送出されます。
端から端まで一直線ではない
インターネット通信は、専用線のように固定の道をそのまま流れるとは限りません。途中には複数のルータ、ISP、データセンタ、CDN などがあり、その時々の経路選択や障害状況によって通り道が変わることがあります。
このため、
- あるときだけ遅い
- 一部地域だけつながらない
- 片方向だけおかしい
といった現象が起こりえます。
TTL と「どこまで進んだか」
各パケットは TTL(Time To Live) という 8 ビットのカウンタを持ちます。ルータを通過するたびに 1 減少し、0 になるとパケットは廃棄されます。これにより、無限ループを防ぎます。
初期 TTL = 64(Linux)や 128(Windows)
ルータ 1 通過後:63
ルータ 2 通過後:62
...
TTL = 0 になったら廃棄
traceroute はこの TTL を段階的に増やし、各ステップで ICMP Time Exceeded を集めることで、経路を観察します。
$ traceroute example.com
1 192.168.1.1 (192.168.1.1) 1.234 ms
2 203.0.113.1 (203.0.113.1) 5.678 ms
3 198.51.100.1 (198.51.100.1) 12.345 ms
...
トランスポート層の概観
トランスポート層は、エンドツーエンドの通信チャネルを提供し、ポート番号によって複数のアプリケーションを多重化します。
ポート番号の役割
同一 IP でも異なるポートに複数のサービスが動作する場合がありますが、これはトランスポート層が実現しています。
TCP と UDP
| 特性 | TCP | UDP |
|---|---|---|
| 信頼性 | ○(再送) | ×(ベストエフォート) |
| 順序保証 | ○ | × |
| コネクション | ○(3-way handshake) | × |
| オーバーヘッド | 中程度 | 低い |
| 用途 | HTTP, SMTP, SSH | DNS, VoIP, ゲーム, QUIC |
TCP の詳細
TCP の 3 者ハンドシェイク(3-Way Handshake)
TCP はいきなり本編を送り始めるのではなく、接続の準備をします。
-
クライアント → サーバ:
SYN(シーケンス番号 = 100)- クライアントが「接続したい」とシグナルを送信
- クライアント側の状態:
-
サーバ → クライアント:
SYN-ACK(シーケンス番号 = 300、確認番号 = 101)- サーバが「わかった、こちらも準備できた」と応答
- サーバ側の状態:
-
クライアント → サーバ:
ACK(シーケンス番号 = 101、確認番号 = 301)- クライアントが受信を確認し、接続確立
- 両側の状態:
ESTABLISHED
この 3 ステップはネットワークの遅延を勘案しており、双方が確実に「接続準備できた」ことを確認します。
なぜ 3 ステップ必要か
2 ステップだと、サーバがクライアントの最初の SYN を確認できません。仮に SYN-ACK が返されたとしても、サーバ側は「本当にクライアントがそれを受け取ったか」が不明です。3 ステップ目の ACK でこれが確認されます。
シーケンス番号と確認番号
TCP は各バイトに番号を付けることで、順序性と信頼性を実現します。
クライアント → サーバ
バイト 1-100:seq=1000, ack=2000(サーバからの seq=2000 を受け取ったことを示す)
バイト 101-200:seq=1100, ack=2000
サーバ → クライアント
バイト 1-50:seq=2000, ack=1001(クライアントのバイト 1-100 を受け取ったことを示す)
TCP の状態遷移
TCP コネクションには複数の状態があります。
フロー制御(Flow Control)
相手の受け皿の大きさに合わせて、送信量を調整します。
スライディングウィンドウ
TCP 受信側は RWND(Receive Window)という値を送信側へ通知し、「この量までなら受け取れる」と伝えます。
送信側の送信可能な区間:
次送信シーケンス番号:100
確認済みシーケンス番号:50
RWND = 1000
送信可能な範囲:50 + 1000 = 1050 まで
受信側のバッファが詰まると RWND が小さくなり、送信側は送信速度を落とします。
輻輳制御(Congestion Control)
ネットワーク全体の混雑に合わせて、送信量を調整します。
TCP Slow Start(スロースタート)
新規接続や再送後は、段階的に送信量を増やしていきます。
初期 CWND(Congestion Window)= 1 MSS
ラウンドトリップタイム(RTT)ごとに倍増:
1 → 2 → 4 → 8 → 16 → ...
しきい値(SSTHRESH)に達したら線形増加に移行
TCP Reno
長らく標準だったアルゴリズム。パケット損失時は CWND を半減し、その後線形に増加。
CWND = 16 MSS 時にパケット損失
↓
CWND = 8 MSS に低下
↓
8 → 9 → 10 → 11 ... と線形増加
TCP CUBIC
Linux 3.2 以降のデフォルト。数学的に計算された 3 次曲線を使い、ネットワーク遡及時間(RTT)の違いに自動適応します。
CWND = C * (t - K)^3 + W_max
C:スケーリング定数
t:時間
K:回復点
W_max:直前のパケット損失時の最大 CWND
CUBIC は異なる RTT のフロー間で比較的公平に頻域を共有します。
TCP BBR(Bottleneck Bandwidth and RTT)
Google が開発した革新的なアルゴリズム。パケット損失ではなく、到達可能な帯域幅と往復遅延を測定し、それに基づいて CWND を決定します。
パケット到着率の測定 → 推定帯域幅
RTT 測定 → 推定遅延
CWND = 推定帯域幅 × RTT
利点:
- パケット損失がない環境でも効率的に帯域を使用
- バッファ充満(bufferbloat)を軽減
- 衛星通信など遅延が大きい環境で有効
TCP BBRv3(2024 年登場)
BBR の改良版。複数フロー間の公平性向上と、初期化フェーズの改善。
Nagle アルゴリズム
小さなパケットが多数送信されるのを防ぐため、確認されていないデータがあれば、次のデータを待ってまとめて送信します。これは遅延を増加させるため、リアルタイム性が重要なアプリ(SSH、オンラインゲーム)では無効化(TCP_NODELAY)されることが多い。
Karn のアルゴリズム
再送されたパケットへの応答を、RTT 測定に含めません。そうしないと、本当の RTT が分からなくなるからです。
Fast Retransmit と Fast Recovery
3 つの重複した ACK を受け取ったら、タイムアウト待たずに即座に再送します。
正常系:
データ 1, 2, 3, 4, 5 送信
ACK 1, ACK 2, ACK 3(正常)
異常系:
データ 1, 2, 3, 4, 5 送信
ACK 1, ACK 2, ACK 2, ACK 2(データ 3 が欠損)
→ 3 つの重複 ACK で即座にデータ 3 を再送
UDP の詳細
UDP は「最小限の輸送層」です。信頼性制御をアプリに委ねることで、低遅延・低オーバーヘッドを実現します。
UDP ヘッダ
わずか 8 バイトです。TCP のヘッダ(最小 20 バイト)と比べ、オーバーヘッドが小さい。
UDP の用途
DNS(Domain Name System)
ほぼすべての DNS クエリが UDP port 53 を使用(大規模レスポンスは TCP にフォールバック)。要求・応答が 1 往復で済み、遅延が重要だからです。
クライアント → DNS サーバ(UDP port 53)
↓
サーバが即座に応答
↓
クライアント受信
VoIP(Voice over IP)
遅延が重要。一部のパケット損失は音声品質低下で許容可能。
オンラインゲーム
低遅延が命。プレイヤー位置の同期などは UDP で行い、クリティカルなデータ(クエストの進行など)は TCP で確認するハイブリッドアプローチもあります。
HTTP/3 と QUIC
HTTP/3 は UDP 上の QUIC で動作します。QUIC 自体が UDP 上に信頼性制御を実装しており、事実上、アプリケーション層で TCP のような機能を実現しています。
ソケットプログラミング
アプリケーションがネットワークを使うとき、多くの場合はソケット API を通ります。ソケットは「ネットワーク通信のためのファイル記述子のような窓口」と考えるとわかりやすいです。
BSD ソケット API
UNIX / Linux の標準ソケット API。
TCP サーバの基本形
// Node.js の例
const net = require('net');
const server = net.createServer((socket) => {
socket.on('data', (data) => {
console.log('受信:', data.toString());
socket.write('エコー: ' + data);
});
socket.on('end', () => {
console.log('接続終了');
});
});
server.listen(3000, '127.0.0.1');
TCP クライアント
const net = require('net');
const socket = net.createConnection(3000, '127.0.0.1', () => {
socket.write('Hello Server');
});
socket.on('data', (data) => {
console.log('レスポンス:', data.toString());
});
ソケットの I/O モデル
ブロッキング I/O
// socket.read() は データが来るまで待機
const data = socket.read();
シンプルですが、複数クライアントを扱う場合は各クライアント分のスレッドが必要になり、スケールしません。
ノンブロッキング I/O
// データがなければすぐに null を返す
const data = socket.read();
if (data === null) {
// データがない
}
複数クライアントを 1 スレッドで処理できますが、ポーリングが必要です。
マルチプレクシング
複数のソケットの状態を効率的に監視します。
select(古い、ポータブル):
fd_set readfds;
FD_SET(socket_fd, &readfds);
select(max_fd + 1, &readfds, NULL, NULL, &timeout);
if (FD_ISSET(socket_fd, &readfds)) {
// このソケットにデータが来た
}
制限:監視できるソケット数が OS の上限(通常 1024)。
poll(select より良い):
struct pollfd fds[100];
fds[0].fd = socket_fd;
fds[0].events = POLLIN;
poll(fds, 100, timeout);
select より制限が緩い(ただし O(n) の線形走査)。
epoll(Linux、高速):
int epfd = epoll_create1(0);
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = socket_fd;
epoll_ctl(epfd, EPOLL_CTL_ADD, socket_fd, &event);
struct epoll_event events[100];
int nready = epoll_wait(epfd, events, 100, timeout);
epoll はカーネルが内部的にレディー状態のソケットを追跡し、O(k) で k 個のレディーソケットを返します(k は少数)。Linux サーバアプリケーションの標準です。
kqueue(BSD / macOS):
int kq = kqueue();
struct kevent kev;
EV_SET(&kev, socket_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &kev, 1, NULL, 0, NULL);
struct kevent events[100];
int nready = kevent(kq, NULL, 0, events, 100, &timeout);
BSD/macOS の高効率なマルチプレクシング。
io_uring(Linux 5.1+、最新):
従来のシステムコール(epoll_wait など)をキューイングし、バッチ処理することで、システムコールのオーバーヘッドを大幅に削減。
struct io_uring ring;
io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_read(sqe, fd, buf, BUF_SIZE, 0);
io_uring_submit(&ring);
struct io_uring_cqe *cqe;
io_uring_wait_cqe(&ring, &cqe);
// 完了情報を処理
バッファと TCP Nagle アルゴリズム
送信バッファ
socket.write('Hello'); // すぐには送信されず、バッファに溜まる
socket.write(' World'); // まとめて送信されるかもしれない
TCP_NODELAY オプションで Nagle アルゴリズムを無効化し、即座に送信。
socket.setNoDelay(true); // TCP_NODELAY を有効
受信バッファ
socket.on('data', (chunk) => {
// chunk はアプリケーションで決定した単位ではなく、
// TCP が区切った単位(通常 1-64 KB)
});
アプリケーションは「1 read = 1 write」を仮定できません。複数のパケットがまとめて来たり、1 つのパケットが複数の read に分かれることもあります。
DNS の詳細
DNS 階層構造
DNS は分散データベースであり、単一の電話帳ではありません。
DNS クエリ方式
再帰クエリ(Recursive Query)
「この名前を解いてくれ」とリゾルバに問い合わせ。リゾルバが全責任で回答を返す。
クライアント: "www.example.com のアドレスは?"
リゾルバ: "192.0.2.1 です"
反復クエリ(Iterative Query)
「この名前のサーバはどこ?」と問い合わせ。相手は「ここなら知ってるよ」という示唆を返す。
クライアント: "www.example.com はどこ?"
ルート: "TLD サーバがいるよ → 198.51.100.1"
クライアント: "198.51.100.1 へ、www.example.com はどこ?"
TLD: "権威サーバがいるよ → 203.0.113.1"
DNS レコードタイプ
| タイプ | 用途 | 例 |
|---|---|---|
| A | IPv4 アドレス | www.example.com → 192.0.2.1 |
| AAAA | IPv6 アドレス | www.example.com → 2001:db8::1 |
| MX | メールサーバ | example.com → mail.example.com |
| CNAME | 別名 | www.example.com → example.com |
| NS | ネームサーバ | example.com → ns1.example.com |
| TXT | テキスト・その他 | SPF・DKIM 検証など |
| SOA | ゾーン情報 | シリアル番号・TTL など |
| SRV | サービス位置 | _sip._tcp.example.com |
DNS キャッシュと TTL
リゾルバが www.example.com を解き、A レコード(TTL: 3600)を取得
→ 3600 秒間、ローカルキャッシュに保持
→ 次の同一クエリはキャッシュから即座に返却
→ 3600 秒経過後、再度権威サーバへ問い合わせ
TTL が短いと(60 秒など)、キャッシュ効果が低く問い合わせが頻繁。長いと(86400 秒 = 1 日など)、変更反映が遅い。
DNSSEC(DNS Security Extensions)
DNS への中間者攻撃(DNS ポイズニング、キャッシュ汚染)を防ぐため、デジタル署名を使用。
権威サーバが DNSKEY(公開鍵)と RRSIG(署名)を返却
→ リゾルバが署名を検証
→ 改ざんされたレスポンスを検出可能
チェーン検証:子ゾーン(example.com)の DNSKEY は、親ゾーン(.com)の DS レコードで署名される。これにより信頼の連鎖が確立されます。
DoT(DNS over TLS)と DoH(DNS over HTTPS)
通常の DNS は平文で送受信されるため、盗聴・改ざんが可能。
DoT:DNS over TLS
DNS クエリを TLS で暗号化。
クライアント --TLS→ DNS サーバ(port 853)
↓
DNS クエリが TLS で保護される
DoH:DNS over HTTPS
DNS クエリを HTTPS(HTTP/2 や HTTP/3)で送信。
POST https://dns.example.com/dns-query?dns=... HTTP/1.1
(base64 エンコードされた DNS メッセージ)
DoH はネットワーク監視ツール(企業ファイアウォール)による検査が難しいため、プライバシーはより強い一方で、組織のポリシー執行が難しくなるという議論もあります。
DoQ(DNS over QUIC)
QUIC を使い、0-RTT での問い合わせが可能。HTTP/3 対応のインフラが整うにつれて普及予定。
DHCP と ARP
DHCP(Dynamic Host Configuration Protocol)
ネットワーク接続時に、IP アドレスを自動割り当て。
DHCP リース:IP は一時的な貸与。期間(デフォルト 24-48 時間)を過ぎると返却。ホストは期間中盤で更新要求(DHCP RENEW)。
ARP(Address Resolution Protocol)
IP アドレスから MAC アドレスを解く。
「192.168.1.1 の MAC アドレスは?」というブロードキャスト
→ 192.168.1.1 を持つホストが応答
→ MAC アドレスを習得
同一 LAN 内(同一サブネット)の通信では、ARP で相手の MAC アドレスを習得してから Ethernet フレームを送信します。
ARP スプーフィング攻撃:異なるホストが「私が 192.168.1.1 です」と偽る ARP Reply を送り、トラフィックをリダイレクト。対策:ARP テーブルの検証、VLAN 分離など。
HTTP の進化
HTTP/0.9
GET /index.html\r\n
\r\n
返却:
<HTML>
...
</HTML>
メソッドは GET のみ、ヘッダなし、ステータスコードなし。
HTTP/1.0
GET /index.html HTTP/1.0\r\n
Host: www.example.com\r\n
User-Agent: Mozilla/1.0\r\n
\r\n
レスポンス:
HTTP/1.0 200 OK\r\n
Content-Type: text/html\r\n
Content-Length: 1234\r\n
Connection: close\r\n
\r\n
<HTML>...</HTML>
- ステータスコード導入
- ヘッダフィールド導入
- コネクション毎に 1 リクエスト(接続オーバーヘッド大)
HTTP/1.1
GET /index.html HTTP/1.1\r\n
Host: www.example.com\r\n
Connection: keep-alive\r\n
\r\n
同一接続で複数リクエスト可能(Keep-Alive)。
GET /image1.png HTTP/1.1\r\n
Host: www.example.com\r\n
\r\n
(接続を再利用)
GET /image2.png HTTP/1.1\r\n
Host: www.example.com\r\n
\r\n
HTTP/1.1 の主な機能
- キャッシュ制御:
,
ETag,Last-Modified - チャンク転送:
Transfer-Encoding: chunked(コンテンツサイズ未知のときに有用) - 範囲リクエスト: (動画・大容量ファイルの部分取得)
- 条件付き GET:
If-Modified-Since,If-None-Match(キャッシュ検証)
HTTP/1.1 の課題
Head-of-Line Blocking (HoL):
request 1 送信 → response 1 受信待ち
request 2 送信 → response 1 が来るまで待機(応答が遅いと HoL)
request 3 送信 → request 2 と同様に待機
1 本の接続で複数リクエストを順番に処理するため、前のレスポンス待ちで後ろが止まります。
HTTP/1.1 の詳細
HTTP メソッド
| メソッド | 用途 | 冪等性 |
|---|---|---|
| GET | リソース取得 | ○ |
| POST | データ送信・新規作成 | × |
| PUT | リソース更新(全置換) | ○ |
| DELETE | リソース削除 | ○ |
| PATCH | リソース部分更新 | × |
| HEAD | GET と同じ(本体なし) | ○ |
| OPTIONS | 利用可能メソッド確認 | ○ |
冪等性:同じリクエストを複数回実行しても同じ結果が得られること。GET・PUT・DELETE は冪等;POST・PATCH は非冪等(重複実行で重複副作用)。
ステータスコード
| 範囲 | 分類 | 例 |
|---|---|---|
| 1xx | 情報応答 | 100 Continue |
| 2xx | 成功 | 200 OK, 201 Created, 204 No Content |
| 3xx | リダイレクト | 301 Moved Permanently, 302 Found, 304 Not Modified |
| 4xx | クライアントエラー | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found |
| 5xx | サーバエラー | 500 Internal Server Error, 503 Service Unavailable |
HTTP ヘッダ
リクエストヘッダ
Host: 要求先ホスト(必須)User-Agent: クライアント識別Accept: クライアントが受け付けるコンテンツタイプAccept-Language: 言語Cookie: セッション・トラッキング情報Authorization: 認証情報Content-Type: 本体のデータ形式Content-Length: 本体サイズ
レスポンスヘッダ
Server: サーバ識別(Apache、nginx など)Content-Type: 本体のデータ形式Content-Length: 本体サイズCache-Control: キャッシュ指示ETag: 一意なバージョン識別子Last-Modified: 最終更新日時Set-Cookie: クライアント側に cookie を保存Location: リダイレクト先 URLStrict-Transport-Security: HTTPS 強制
キャッシュ戦略
Cache-Control: max-age=3600
→ 3600 秒はキャッシュを使用、サーバ問い合わせなし
Cache-Control: no-cache
→ キャッシュ使用前に条件付き GET(If-None-Match)でサーバ確認
Cache-Control: no-store
→ キャッシュするな(機密情報など)
Cookie と Session
レスポンス:
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Strict
クライアント保存:
Cookie: session_id=abc123
次のリクエスト:
GET /page HTTP/1.1
Host: example.com
Cookie: session_id=abc123
HttpOnly: JavaScript から access 不可(XSS 対策)Secure: HTTPS のみ送信SameSite: CSRF 対策(Strict / Lax / None)
Content Negotiation(コンテンツ交渉)
クライアントが Accept ヘッダで希望形式を示し、サーバが最適なバージョンを返す。
GET /api/user HTTP/1.1
Accept: application/json, application/xml;q=0.9
(application/json が優先度高い)
サーバは JSON を返す可能性が高い。q パラメータで優先度を指定。
HTTP/2 の詳細
HTTP/1.1 の Head-of-Line Blocking を解決するため、HTTP/2 は複数のリクエスト・レスポンスを 1 本の TCP 接続で多重化します。
バイナリフレーミング
HTTP/1.1 はテキスト(改行区切り)。HTTP/2 は固定長フレーム。
バイナリ形式により、高速パース・効率的なフレーミングが可能。
ストリーム
HTTP/2 では、1 本の TCP 接続内に複数の「ストリーム」があり、各ストリーム内でリクエスト・レスポンスのペアが独立して動作。
ストリーム ID は奇数(クライアント発信)と偶数(サーバ発信)で区別。
多重化のメリット:
- Head-of-Line Blocking 回避(1 リクエスト遅延が他に影響しない)
- 接続確立オーバーヘッド削減
- TCP ウィンドウ共有(効率的な帯域利用)
HPACK(圧縮ヘッダ)
HTTP/1.1 では各リクエストで同一ヘッダが繰り返されるため、無駄が多い。
GET /page1.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: */*
GET /page2.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: */*
(User-Agent と Accept が重複)
HPACK は動的テーブルを使い、既出のヘッダを参照インデックスで送信。
フレーム 1:
HEADERS + Literal(User-Agent: Mozilla/5.0)→ テーブルに記録、インデックス 62 に登録
フレーム 2:
HEADERS + インデックス 62(ユーザーエージェントは前と同じ)
圧縮率は通常 30~50%。
優先度付けとリソースヒント
ストリーム同士で優先度を指定可能。
サーバはこの優先度に基づき、帯域割り当てを最適化。
Server Push
サーバが「このリソースはいるだろう」と推測し、クライアントの要求なしに送信。
クライアント:
GET /page.html
サーバ(PUSH_PROMISE フレーム):
「/page.html に関連する /style.css と /script.js も送るね」
(その後、DATA フレームで 3 リソース全て送信)
ただし誤ったプッシュはネットワーク浪費につながるため、慎重な使用が必要。
HTTP/3 と QUIC
HTTP/3 は、QUIC というプロトコル(UDP 上で TCP 並みの信頼性を実装)上で動作。従来の TCP ベースではなく、UDP ベースで多くの改善を実現。
QUIC の特徴
接続確立の高速化
TCP では 3-way handshake で 1 RTT、TLS 1.2 では 1 RTT(合計 2 RTT)必要。
TCP/TLS 1.2:
Client → Server: SYN
Server → Client: SYN-ACK
Client → Server: ACK, TLS ClientHello
Server → Client: TLS ServerHello, ...
(データ送信は 2 RTT 後)
QUIC では初回接続も 1 RTT で済みます。さらに 0-RTT(resumption token により初期化パラメータを再利用)を使えば、接続直後にデータ送信可能。
QUIC 0-RTT:
Client → Server: Initial + Handshake + データ(1 パケット)
Server → Client: レスポンス
(即座に通信開始)
コネクションマイグレーション
TCP は IP・ポートペア(5-tuple)で識別するため、ネットワーク変更(WiFi → LTE)でコネクション喪失。
QUIC は Connection ID を使い、IP 変更後も同一接続を継続。
初期接続:192.168.1.10 (WiFi)
↓(WiFi 圏外になり LTE に切り替わり)
↓ IP が 203.0.113.5 に変更
→ QUIC は Connection ID で同一接続と認識、継続
モバイル環境で大幅な改善。
多重化の改善
HTTP/2 は TCP 上で多重化するため、1 パケット損失が全ストリームに影響(Head-of-Line Blocking)。
TCP のコンテキスト:
パケット A(Stream 1 の DATA)
パケット B(Stream 2 の DATA)
パケット C(Stream 3 の DATA)
パケット B 喪失 → 再送待ちの間、Stream 2 停止
(Stream 1・3 は続行)
ただし TCP のバッファ・セグメント化により、局所化される
QUIC ではパケット損失がそのストリームのみに限定。
QUIC のコンテキスト:
フレーム A(Stream 1 の DATA)
フレーム B(Stream 2 の DATA)
フレーム C(Stream 3 の DATA)
フレーム B 喪失 → Stream 2 だけ再送
Stream 1・3 は影響なし(QUIC レベルでの独立性)
組み込み暗号化
QUIC はハンドシェイクから暗号化。盗聴・改ざんへの耐性が高い。
TCP/TLS 1.2:
SYN(平文)
SYN-ACK(平文)
ClientHello(TLS ハンドシェイク初期、部分的に平文)
QUIC:
Initial Packet(全て Handshake Key で暗号化)
HTTP/3 フレーム
HTTP/2 と基本構造は共通ですが、QUIC フレーム上に多重化。
HTTP/3 の実装状況
2024 年時点:
- Chrome・Firefox などのモダンブラウザ:対応済み
- AWS・Google・CloudFlare など主要 CDN:対応済み
- 一部エンタープライズネットワーク:QUIC ポートブロック(port 80・443 のみ許可など)
ブロックチェーンやゲーム、ビデオストリーミングで急速に採用が進行中。
TLS の詳細
TLS 1.2 と TLS 1.3 の比較
TLS 1.2 ハンドシェイク(1.5 RTT)
TLS 1.2:
- ClientHello(クライアントの対応 cipher suite・乱数を送信)
- ServerHello(サーバが選択した cipher suite・乱数、証明書、鍵交換パラメータを送信)
- ClientKeyExchange(クライアントが鍵交換完了)
- 双方で Finished(ハンドシェイク検証)
TLS 1.3 ハンドシェイク(1 RTT)
TLS 1.3:
- ClientHello に鍵交換パラメータを含める(1 度のメッセージで共有鍵を計算可能)
- ServerHello 受信直後にデータ送信可能
- 事実上 1 RTT に短縮
0-RTT(Early Data)
TLS 1.3 では、以前のハンドシェイク情報を再利用し、サーバへの接認証なしに初期データを送信可能(ただしリプレイ攻撃のリスクあり)。
セッション 1:
Client → Server: ClientHello
Server → Client: ServerHello + session_ticket
セッション 2(別日など):
Client → Server: ClientHello + session_ticket + Early Data(0-RTT)
(サーバがすぐに Early Data を処理開始)
Cipher Suite(暗号スイート)
TLS では、以下の 4 要素の組み合わせを「Cipher Suite」と呼ぶ。
- 鍵交換(Key Exchange): RSA, ECDHE(楕円曲線 Diffie-Hellman 鍵交換), DHE など
- 認証(Authentication): RSA, ECDSA, EdDSA など
- 暗号化(Encryption): AES-128-GCM, AES-256-GCM, ChaCha20-Poly1305 など
- メッセージ認証(MAC): SHA-256, SHA-384 など
例:
- ECDHE で鍵交換
- RSA で認証
- AES-256-GCM で暗号化
- SHA-384 で整合性確認
Forward Secrecy(前方秘匿性)
ECDHE など「短命な」鍵を使うことで、長期秘密鍵(サーバの秘密鍵)が漏洩しても過去の通信は解読されない。
古い方式(RSA 鍵交換):
過去に記録した通信
+ サーバ秘密鍵をハッキング取得
= 過去通信をすべて復号化可能(危険!)
新しい方式(ECDHE):
過去に記録した通信
+ サーバ秘密鍵をハッキング取得
= 過去通信は復号化不可(各セッションが独立鍵を使用)
証明書と PKI(Public Key Infrastructure)
X.509 証明書
サーバが持つ公開鍵の正当性を確認するため、信頼される認証局(CA)が署名した証明書。
[ 証明書 ]
Subject: www.example.com
Issuer: Let's Encrypt Authority X3
Public Key: ... (RSA 2048)
Valid From: 2024-01-01
Valid To: 2025-01-01
Serial: 0x1234...
Signature: [SHA-256 with RSA]
ブラウザは証明書チェーンを検証:
www.example.com 証明書
↓(署名検証用に Parent CA の公開鍵を使用)
↓
Let's Encrypt Authority X3 証明書
↓
Let's Encrypt Root CA 証明書(ブラウザの信頼ストアに含まれる)
CA と信頼チェーン
複数の CA が階層をなす:
中間 CA が漏洩してもルート CA は影響を受けない設計。
Let’s Encrypt と ACME(Automated Certificate Management Environment)
ACME を使い、証明書の自動取得・更新・失効を実現。
1. サーバが Let's Encrypt へ「www.example.com の証明書がほしい」と要求
2. Let's Encrypt が「その IP からアクセスできるか」を検証(DNS TXT レコード確認など)
3. 検証成功時、証明書を発行
4. サーバが設定・有効化
無料かつ 90 日有効期限が短く、自動更新前提の設計。
OCSP(Online Certificate Status Protocol)
証明書の失効状況をリアルタイム確認。
ブラウザ → OCSP レスポンダ:
「証明書 SN=0x1234... はまだ有効?」
OCSP レスポンダ → ブラウザ:
「有効です(署名付き)」
ただし OCSP レスポンダへのアクセスが遅い場合があるため、OCSP Stapling(サーバが事前に OCSP レスポンスを取得しておき、TLS ハンドシェイク時に一緒に送信)で改善。
WebSocket と Server-Sent Events
HTTP は Request-Response の同期モデル。リアルタイム双方向通信にはこれらの技術を使用。
WebSocket
HTTP upgrade メカニズムで、HTTP から WebSocket プロトコルへ昇格。
GET / HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
サーバが受け入れると:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
以降、 TCP 上で全二重通信(双方向同時)が可能。
WebSocket フレーム
FIN bit | RSV | opcode(TEXT/BINARY/CLOSE)| mask | payload length | payload
1 bit | 3 | 4 bits | 1 | 7-64 bits | variable
- TEXT(0x1): テキストデータ
- BINARY(0x2): バイナリデータ
- CLOSE(0x8): 接続閉鎖
- PING/PONG(0x9/0xA): keep-alive
WebSocket のメリット・デメリット
メリット:
- 低遅延の双方向通信
- チャット、リアルタイム通知に最適
デメリット:
- 中間プロキシ・ファイアウォール無視の可能性
- ステートフル(サーバ側の接続維持が必要)
Server-Sent Events(SSE)
サーバからクライアントへの一方向リアルタイム配信。HTTP 上で実装可能。
GET /stream HTTP/1.1
Accept: text/event-stream
サーバが以下のように流送:
data: {"msg": "Hello"}\n
\n
retry: 5000\n
\n
event: notification\n
data: {"alert": "Warning"}\n
\n
クライアント(JavaScript):
const sse = new EventSource('/stream');
sse.addEventListener('notification', (e) => {
console.log(JSON.parse(e.data));
});
メリット:
- シンプル(HTTP の上に乗る)
- プロキシ・ファイアウォール親和性高い
デメリット:
- 一方向のみ(サーバ → クライアント)
ネットワークセキュリティの基礎
ネットワークレイヤーでの主要な脅威と対策。
ARP Spoofing(ARP なりすまし)
攻撃者が「私は 192.168.1.1 です(MAC: AA:BB:CC:DD:EE:FF)」と偽の ARP Reply を送信。
ホスト A が 192.168.1.1 へのトラフィックを攻撃者へ誤ります(中間者攻撃)。
正常な ARP:
ホスト A: 「192.168.1.1 の MAC は?」
ホスト B: 「私です。MAC は XX:XX:XX:XX:XX:XX」
攻撃:
ホスト A: 「192.168.1.1 の MAC は?」
攻撃者: 「私です。MAC は AA:BB:CC:DD:EE:FF」
ホスト A: (騙される)
対策:
- VLAN 分離
- ARP テーブル固定設定(スタティック ARP)
- Dynamic ARP Inspection(DAI)
DNS Poisoning(DNS 汚染)
攻撃者が DNS リゾルバのキャッシュに偽のレコードを挿入。
正常:example.com → 192.0.2.1
攻撃後:example.com → 198.51.100.1(攻撃者の IP)
ユーザーが example.com にアクセスするとフィッシングサイトへ。
対策:
- DNSSEC(署名検証)
- 信頼できるリゾルバ使用(8.8.8.8 など)
- DoT / DoH
MITM(中間者攻撃)
攻撃者がクライアント・サーバ間の通信を傍受・改ざん。
クライアント ← 攻撃者 → サーバ
攻撃者:
- クライアント ↔ 攻撃者 間では攻撃者の証明書を提示(ブラウザ警告)
- 攻撃者 ↔ サーバ 間では正規の接続
対策:
- TLS(暗号化・認証)
- 証明書ピンニング(モバイルアプリ)
- HSTS(HTTP Strict-Transport-Security)
DDoS(Distributed Denial of Service)
複数の攻撃元からのトラフィック爆増でサービス停止。
ボットネット(感染コンピュータ群)
↓
同時多数のリクエスト
↓
サーバ過負荷 or ネットワーク飽和
種類:
- L3/L4 DDoS: 大量の SYN・UDP パケット(ネットワーク層)
- L7 DDoS: 正当な HTTP リクエスト大量送信(アプリ層)
対策:
- レート制限(Rate Limiting)
- DDoS 対策サービス(Cloudflare など)
- トラフィック分散(Anycast)
- BGP フィルタリング
TLS ストリップ(SSL Stripping)
攻撃者が HTTPS を HTTP にダウングレード。
クライアント → 攻撃者(HTTPS を HTTP に変換)→ サーバ
サーバ → 攻撃者(HTTP) → クライアント(HTTP で見える)
対策:
- HSTS(ブラウザが自動的に HTTPS 強制)
- Strict-Transport-Security ヘッダ
Strict-Transport-Security: max-age=31536000; includeSubDomains
プロキシと逆プロキシ
Forward Proxy(フォワードプロキシ)
クライアント側に置かれ、クライアントからの要求を代理。
クライアント → Proxy → インターネット
Proxy は:
- キャッシュ
- アクセス制御
- コンテンツフィルタリング
企業内ネットワークで、社員のインターネットアクセス監視・制限。
Reverse Proxy(リバースプロキシ)
サーバ側に置かれ、外部からのリクエストを内部サーバへ代理。
インターネット → Reverse Proxy → 内部サーバ
Proxy は:
- TLS 終端
- キャッシュ
- 複数サーバへの振り分け(Load Balancing)
- 圧縮
実装例:nginx,Apache,HAProxy。
TLS 終端
クライアント --HTTPS--> Reverse Proxy --HTTP--> 内部サーバ
(TLS) (平文)
リバースプロキシが TLS を終端することで、内部通信はシンプル化。ただし Proxy 内部通信は平文(信頼できるネットワーク内と仮定)。
キャッシュ
レスポンスをキャッシュし、同一リクエストは内部サーバへ接続せず返却。
リクエスト → Proxy(キャッシュにあり)→ すぐレスポンス
(以降も同一リクエストはキャッシュから)
キャッシュ無効化(Cache Invalidation):
- TTL 経過
- サーバがキャッシュクリア指令
- クライアントが強制更新(Ctrl+Shift+R)
CDN と負荷分散
CDN(Content Delivery Network)
世界中に散在するエッジサーバで、利用者に近い場所からコンテンツを配信。
クライアント(東京)
↓ 直近の CDN POP(東京)から取得
↓
オリジン(us-west)へのアクセス削減
CDN の例
- Cloudflare: グローバルに 200+ POP
- Akamai: 大規模・エンタープライズ向け
- AWS CloudFront: AWS インテグレーション
- Fastly: Varnish ベース、高速エッジコンピューティング
キャッシュヒット率向上
Cache-Control: max-age=31536000, immutable
(1 年キャッシュ、ファイル内容が変わらないことを保証)
バージョン付き URL:
/assets/app.min.js → /assets/app-abc123def456.min.js
(バージョン変更時のみ新 URL)
Load Balancer(ロードバランサ)
複数のバックエンドサーバへリクエストを振り分け。
L4(Layer 4)Load Balancer
IP・ポート情報でみ振り分け(TCP/UDP ポート)。高速だが、アプリケーション内容は見ない。
クライアント1 → LB → サーバ A
クライアント2 → LB → サーバ B(ラウンドロビン)
実装:Linux IPVS,Maglev(Google),など。
L7(Layer 7)Load Balancer
HTTP ヘッダ・パス・ホスト名などアプリケーション情報で振り分け。
GET /api/* → バックエンド API サーバ群
GET /static/* → キャッシュサーバ
GET /admin* → 管理者向けサーバ
実装:nginx,HAProxy,AWS ALB,など。
ヘルスチェック
LB が定期的(例 5 秒ごと)に各サーバへヘルスチェック
GET /health HTTP/1.1
返却 200 OK → サーバは健康
返却エラー or タイムアウト → サーバを一時除外
ファイアウォールと VPN
ファイアウォール
ネットワーク・エッジでパケットを検査・フィルタリング。
Stateless Firewall
各パケットを個別に検査。
ルール例:
- 外部 → 内部:TCP port 80・443 のみ許可
- 内部 → 外部:すべて許可
高速だが、フロー単位の判定ができない。
Stateful Firewall
通信状態を追跡し、確立された接続は許可。
ステップ 1:クライアント → サーバ(TCP SYN)
Firewall:「新規接続」として記録、許可
ステップ 2:サーバ → クライアント(TCP SYN-ACK)
Firewall:「応答パケット」として記録済み接続の一部と認識、許可
ステップ 3 以降:通常許可(状態テーブルに基づく)
NGFW(Next-Generation Firewall)
さらに HTTP・HTTPS・DNS などアプリケーション層まで検査。
検査項目:
- URL カテゴリ(ブロックリスト)
- マルウェア署名
- 異常なアプリケーション動作
VPN(Virtual Private Network)
公開ネットワーク上に暗号化トンネルを構築。
IPsec
IP レイヤーでの暗号化。
トランスポートモード(エンドツーエンド)とトンネルモード(ゲートウェイ間)。
WireGuard
シンプル・高速の VPN。最小限の暗号化情報で完全な秘密性を実現。
設定例:
[Interface]
PrivateKey = ...
Address = 10.0.0.1/24
ListenPort = 51820
[Peer]
PublicKey = ...
AllowedIPs = 10.0.0.2/32
OpenVPN
TLS ベースの VPN。TCP・UDP サポート。
ネットワーク仮想化
VXLAN(Virtual Extensible LAN)
L2 ネットワークを L3 のトンネルで拡張。
データセンタ間で L2 セグメントを仮想的に拡張する際に使用。
Geneve(Generic Network Virtualization Encapsulation)
VXLAN より柔軟で、拡張性が高い。
GRE(Generic Routing Encapsulation)
任意のプロトコルをトンネル化。
ネットワーク観測とトラブルシューティング
tcpdump
ネットワークインターフェースのトラフィックをキャプチャ・表示。
# すべてのパケットをキャプチャ
tcpdump -i eth0
# DNS トラフィックのみ
tcpdump -i eth0 'port 53'
# ホスト 192.0.2.1 との通信
tcpdump -i eth0 'host 192.0.2.1'
# HTTP・HTTPS
tcpdump -i eth0 'port 80 or port 443'
# ファイルに保存・再生
tcpdump -i eth0 -w capture.pcap
tcpdump -r capture.pcap
Wireshark
tcpdump のビジュアル版。パケットを詳細に解析。
UI:
- Packet List(キャプチャ一覧)
- Packet Bytes(16 進数表示)
- Packet Details(レイヤ別の解析)
フィルタ例:
ip.src == 192.0.2.1
tcp.port == 443
http.request.method == "GET"
ss(socket statistics)
ソケット・ネットワーク接続の統計。netstat の改良版。
# すべての接続
ss -tunap
# TCP listening
ss -tlnp
# 統計情報
ss -s
netstat(deprecated)
# ルーティングテーブル
netstat -rn
# 接続状態
netstat -tan
dig(DNS Lookup)
DNS クエリ。
# A レコード取得
dig example.com
# 特定タイプ
dig example.com MX
# 再帰無しで権威サーバへ直接問い合わせ
dig @ns1.example.com example.com +norec
# trace オプションで全経路表示
dig +trace example.com
ngrep(Network Grep)
パケット内容をテキストで検索。
# HTTP GET リクエスト
ngrep 'GET ' 'tcp port 80'
# SMTP の MAIL FROM を検索
ngrep 'MAIL FROM' 'tcp port 25'
curl(HTTP クライアント)
HTTP リクエストテスト・デバッグ。
# verbose(ヘッダ含む詳細表示)
curl -v https://example.com
# HTTP/2
curl --http2 https://example.com
# HTTP/3(QUIC)
curl --http3 https://example.com
# DNS resolution 時間を含め詳細表示
curl -w @format.txt https://example.com
# format.txt の例:
# time_namelookup: %{time_namelookup}\n
# time_connect: %{time_connect}\n
# time_appconnect: %{time_appconnect}\n
# time_starttransfer: %{time_starttransfer}\n
# time_total: %{time_total}\n
traceroute・mtr
ルート経路と遅延測定。
# traceroute:各ホップの応答時間
traceroute example.com
# mtr:リアルタイム・継続的
mtr example.com
性能チューニングと最適化
TCP ウィンドウサイズチューニング
TCP ウィンドウは帯域と遅延に合わせて最適化。
理想的なウィンドウサイズ = 帯域幅(bps)× RTT(秒)
例:100 Mbps・100 ms RTT
→ 100,000,000 × 0.1 / 8 = 1,250,000 バイト(約 1.2 MB)
設定:
$ sysctl -w net.ipv4.tcp_window_scaling=1
$ sysctl -w net.core.rmem_max=134217728
RPS(Receive Packet Steering)・RFS(Receive Flow Steering)
マルチコア CPU で受信パケットを複数コアに分散。
RPS(IP tuple ハッシュで CPU に割り当て):
# コア 0・1・2・3 で 4 コア case
echo "f" > /sys/class/net/eth0/queues/rx-0/rps_cpus
(16 進 f = 0b1111 = 4 コア)
RFS(同一フロー内のパケットを同一 CPU で処理、キャッシュ効率向上):
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
NIC オフロード機能
NIC がパケット処理の一部を担当。
- TSO(TCP Segmentation Offload):
大きなパケットを NIC が 1500B 単位に分割
- LRO(Large Receive Offload):
複数のパケットを NIC が 1 つに結合
- Checksum Offload:
チェックサム計算を NIC で実施
有効化:
ethtool -K eth0 tso on gro on gso on
BBR による高遅延リンク最適化
BBR は衛星・海外リンクなど遅延が大きい環境で特に有効。
TCP Reno vs BBR(遅延 100ms、帯域 10 Mbps、バッファ小さい)
Reno:
CWND = 32 → パケット損失 → CWND = 16(スループット落ちる)
BBR:
帯域幅 10 Mbps と RTT 100ms から自動計算
CWND = 125 KB(10 Mbps × 0.1s)で安定
(パケット損失なし・スループット維持)
2025-2026 の動向
Multipath QUIC
複数のネットワークパス(WiFi + LTE)を同時利用し、片方が遅くなったら自動切り替え。
WiFi(速いが不安定) + LTE(安定)
→ QUIC がパケットを両方に分散
→ 片方失敗時の遅延・再送削減
HTTP/3・QUIC の急速普及
2024 年末時点で、Cloudflare・Google・Facebook などトップサイトの 30-40% が HTTP/3 対応。
Post-Quantum TLS
量子コンピュータ攻撃への耐性を持つ暗号化へ移行。NIST が標準化候補を発表(2022-)。
現在:RSA 2048 など離散対数問題ベース
2025-2030:CRYSTALS-Kyber(格子問題ベース)など検証・移行期
IPv6 の加速
IPv4 アドレス枯渇により、IPv6 採用が加速。
2024 年時点:
- Google:利用者の 50% が IPv6
- トランスポート層での IPv6 トラフィック:30-40%
eBPF によるネットワーク高度化
カーネル空間でプログラム可能な BPF VM により、ファイアウォール・ロードバランサ・トレーシングをユーザー空間で実装。
XDP(eXpress Data Path):
NIC 直後でパケット処理(前方エラー制御)
tc(traffic control):
いろいろな制御ポイントで BPF プログラム実行
AF_XDP:
ユーザー空間で高速パケット処理(DPDK に近い)
io_uring による非同期 I/O 効率化
従来の epoll・select より、バッチ処理でシステムコール削減。
epoll_wait(context switch コスト)× 100 クライアント
↓
io_uring(共有リングバッファで 1 context switch)
→ 数倍高速化
5G・6G・衛星通信の融合
Starlink などの衛星通信が遅延 20-40ms まで改善し、5G と組み合わせたハイブリッド通信が現実化。
低遅延:地上 5G
カバレッジ広い:衛星通信
エッジ遅延:衛星 → キャッシュサーバ → ユーザー
補足
第7章 ネットワーク
この章が実務で役立つ場面
- Web アプリや API の遅延・接続失敗の切り分け
- TLS 設定、DNS 問題、HTTP 層の挙動理解
- CDN、ロードバランサ、HTTP/2・HTTP/3 の理解
7.1 なぜ層に分けるのか
ネットワークは複雑なので、役割ごとに層に分けて考えます。
【図18】TCP/IP 階層モデル:
7.2 パケットという考え方
データは一度に巨大な塊で運ばれるのではなく、パケットという小さな単位に分かれて送られます。
これにより、
- 分割送信
- 再送
- 経路選択
がしやすくなります。
7.3 TCP と UDP
TCP
- 信頼性重視
- 順序保証
- 再送あり
- コネクションあり
TCP はアプリケーションに対して、信頼できる順序付きのバイトストリーム を提供します。ここで大事なのは、「メッセージ単位」ではなく「バイト列単位」だという点です。送った write() 1回ぶんが、そのまま 1回の read() に対応するとは限りません。
UDP
- 軽量
- 順序保証なし
- 再送なし
- コネクションなし
UDP は最小限の仕組みでデータグラムを送ります。配送保証や重複防止は標準では持たないので、必要ならアプリケーション側で補います。
7.3.1 再送と輻輳制御
TCP が「信頼できる」ように見えるのは、ただ再送するからだけではありません。ネットワークが混んでいるときに、自分の送り方を抑える 輻輳制御も重要です。
もし全員が「落ちたからもっと送る」を繰り返すと、ネットワーク全体がさらに詰まります。そこで TCP は、届き方を見ながら送信速度を調整します。
ここで見るべきなのは、
- 損失
- RTT
- 再送
- ウィンドウサイズ
の関係です。Web の遅さが、アプリではなくネットワーク輻輳から来ることもあります。
7.3.2 フロー制御と輻輳制御の違い
この2つは名前が似ていますが、見ている相手が違います。
- フロー制御: 受信側が処理しきれる量に合わせる
- 輻輳制御: ネットワーク全体の混雑に合わせる
前者は「相手が飲み込めるか」、後者は「道が渋滞していないか」を見ています。
この違いがわかると、TCP が単に「丁寧な配送」ではなく、送信側・受信側・経路の三者を見ながら振る舞う仕組みだと見えてきます。
7.4 IP アドレスとルーティング
IP は「どこへ送るか」を扱い、ルータはパケットを次へ転送します。
ルーティングの直感は、「目的地までの次の一歩を選び続けること」です。
【図18-2】クライアントからサーバへ届くまで:
7.5 DNS
人間向けの名前を IP アドレスへ変換する仕組みです。
【図19】DNS による名前解決:
DNS は単なる「電話帳」ではなく、木構造の名前空間として設計されています。www.example.com は 1つの塊ではなく、ラベルの列として扱われます。この見方があると、サブドメイン、委任、ゾーンという概念も理解しやすくなります。
【図20】DNS の木構造(名前空間):
7.6 HTTP の流れ
Web ではざっくり次の流れで通信します。
- DNS で名前解決
- HTTP/1.1 や HTTP/2 なら TCP 接続、HTTP/3 なら QUIC / UDP の接続確立
- 必要なら TLS ハンドシェイク
- HTTP リクエスト送信
- HTTP レスポンス受信
HTTP は stateless な request/response プロトコルです。つまり、基本形では「1回のリクエストに対して1回のレスポンスを返す」ことを中心に考えます。ログイン状態や買い物かごのような継続的な状態は、Cookie やセッション、トークンなどを使って別途表現します。なお、上の流れは Web ブラウジングでよく見る典型例で、後述の HTTP/3 では運び方が TCP ではなく QUIC / UDP になります。
【図20-2】ブラウザでページを開くまでの流れ:

7.6.1 HTTP/1.1 と HTTP/2
HTTP の「意味」は共通でも、運び方には世代差があります。
- HTTP/1.1: メッセージ構文、フレーミング、接続管理が重要
- HTTP/2: 同じ意味を、より効率のよいフレーム化と多重化で運ぶ
HTTP/2 では接続が persistent で、1本の接続の上で複数のやり取りを効率よく流せます。なので「HTTP/2 は HTTP の意味が変わる」というより、「HTTP の意味は保ったまま、運び方が洗練された」と見るのが自然です。
【図21】HTTP セマンティクスとトランスポートの関係:
7.6.2 ロードバランサ、プロキシ、CDN
実際の Web システムでは、クライアントがいきなりアプリ本体へ到達するとは限りません。間に、
- リバースプロキシ
- ロードバランサ
- CDN
が入ることが多いです。
これらはそれぞれ、
- 入口を一本化する
- 複数サーバへ振り分ける
- 静的コンテンツを利用者の近くで返す
という役割を持ちます。
なので「HTTP の問題」と見えても、実際には CDN のキャッシュ設定やロードバランサのヘルスチェックが原因、ということもあります。
7.7 ソケット
アプリケーションがネットワークを使う入口がソケットです。
- 送信先を指定する
- 接続を張る
- データを送る / 受ける
ソケットは「ネットワーク版のファイル記述子のような窓口」と見るとイメージしやすいです。実際、Unix 系では read / write に近い感覚で扱える場面が多く、OS のファイル I/O とネットワーク I/O の設計思想がつながっています。
7.8 TLS は何を足しているか
TLS は、通信路の上に
- 盗み見されにくさ
- 改ざん検出
- 相手確認
を足します。HTTPS は「HTTP over TLS」と見るとわかりやすいです。
TLS 1.3(RFC 8446、2018年)の主な改善:
- ハンドシェイク 1-RTT:初回接続の待ち時間を半減
- 0-RTT:再訪問時に即座にデータ送信(リスクあり)
- 古いアルゴリズム削除:RC4、3DES、SHA-1、RSA 鍵交換を除去
- 前方秘匿性(PFS)必須:鍵漏洩時の過去通信保護
7.9 HTTP/3 と QUIC
2022 年 RFC 9114 で標準化された HTTP/3 は QUIC プロトコル(RFC 9000)の上に構築される。QUIC は TCP の代替で、以下の特徴を持つ:
- UDP 上に構築:カーネル実装を待たずユーザ空間で進化可能
- TLS 1.3 統合:暗号化は必須、ハンドシェイクを 1-RTT に削減
- head-of-line blocking の解消:TCP は 1 パケット遅れで全部詰まるが、QUIC はストリーム単位で独立
- 接続マイグレーション:IP アドレスが変わっても接続維持(モバイル向け)
7.10 レイテンシとスループット
- レイテンシ: 1回の往復の遅さ
- スループット: 単位時間あたりの量
この2つは別物です。帯域が太くても最初の応答が遅いことはあります。
7.11 ミニ比較表
| 概念 | 何をするか | 混同しやすいもの | 違い |
|---|---|---|---|
| TCP | 信頼性ある転送 | UDP | 順序保証と再送がある |
| IP | 宛先へ届ける | DNS | DNS は名前解決 |
| DNS | 名前をIPへ変換 | HTTP | HTTP はアプリ通信 |
| レイテンシ | 1回の遅さ | スループット | 量ではなく時間 |
7.12 よくある誤解
7.13 例題
【図22】ネットワーク問題の切り分け手順:
例題1: example.com を開く前に DNS が必要な理由を述べよ。
解説: 名前から IP アドレスを知る必要があるからです。
例題2: TCP が UDP より重い代わりに得るものは何か。
解説: 順序保証と再送による信頼性です。
7.14 練習問題
- DNS は何を何へ変換するか。
- 順序保証があるのは TCP と UDP のどちらか。
- 1回の応答の遅さを見る指標は何か。
- アプリケーションがネットワークを使う入口を何と呼ぶか。
7.15 練習問題の答え
- 名前を IP アドレスへ
- TCP
- レイテンシ
- ソケット
7.16 ユースケース
Web API
- DNS, TCP, TLS, HTTP が全部関わる
- 遅い原因はどの層にもありえる
動画配信
- スループット重視
- 再送より連続再生が大事な場面もある
まとめ
ネットワークは、層ごとの役割を押さえつつ、実際の通信を一本の流れとして追うことが大切です。DNS、TCP、TLS、HTTP をつなげて理解すると、設計にもトラブルシューティングにも強くなれます。