Access to www.amazon.com
PCの電源ボタンを押してから www.amazon.com のレスポンスを受信するまで ― 完全技術解説
はじめに
「PCの電源ボタンを押して、ブラウザで www.amazon.com を開く」― この一見シンプルな操作の裏側では、ハードウェアの初期化からOSの起動、ネットワークスタックの構築、名前解決、暗号化通信の確立、HTTPリクエストの送受信、そしてブラウザのレンダリングに至るまで、膨大な数の技術レイヤーが階層的に連携している。
本稿では、この一連のプロセスを以下の大きなフェーズに分けて詳述する。
| フェーズ | 概要 |
|---|---|
| Phase 1 | ハードウェア初期化(電源投入〜POST〜UEFI/BIOS) |
| Phase 2 | ブートローダーとOSカーネルの起動 |
| Phase 3 | ネットワークインターフェースの初期化とIPアドレスの取得(DHCP) |
| Phase 4 | ブラウザ起動とURL入力 |
| Phase 5 | DNS名前解決(再帰的・反復的クエリ) |
| Phase 6 | TCP接続の確立(3ウェイハンドシェイク) |
| Phase 7 | TLS/SSLハンドシェイク(暗号化通信の確立) |
| Phase 8 | HTTPリクエストとレスポンス |
| Phase 9 | ブラウザのレンダリングパイプライン |
| Phase 10 | 接続の終了とリソースの解放 |
各フェーズでは、OSI参照モデルおよびTCP/IPモデルのどのレイヤーで何が行われているかを明示し、パケットキャプチャの例やコマンド出力例も交えて解説する。
参照モデルの対応表
本稿で繰り返し参照するOSI参照モデルとTCP/IPモデルの対応を示す。
┌─────────────────────────────────────────────────────┐
│ OSI参照モデル │ TCP/IPモデル │
├─────────────────────────────────────────────────────┤
│ 第7層: アプリケーション層 │ │
│ 第6層: プレゼンテーション層 │ アプリケーション層 │
│ 第5層: セッション層 │ │
├─────────────────────────────────────────────────────┤
│ 第4層: トランスポート層 │ トランスポート層 │
├─────────────────────────────────────────────────────┤
│ 第3層: ネットワーク層 │ インターネット層 │
├─────────────────────────────────────────────────────┤
│ 第2層: データリンク層 │ ネットワーク │
│ 第1層: 物理層 │ インターフェース層 │
└─────────────────────────────────────────────────────┘
Phase 1: ハードウェア初期化 ― 電源投入からPOST、UEFI/BIOSまで
1.1 電源ボタンの物理的動作
PCの電源ボタンを押すと、以下の一連の電気的・論理的イベントが発生する。
-
電源ユニット(PSU)への信号送出: 電源ボタンはマザーボード上の電源ヘッダーピンに接続されており、ボタンを押すことでPSUの
PS_ON#信号線がLowに引かれる。これによりPSUがスタンバイモードからフル稼働モードに移行する。 -
電圧レールの安定化: PSUは各電圧レール(+3.3V, +5V, +12V)を安定させ、全レールが規定範囲内に到達すると
Power Good(PWR_OK)信号をマザーボードに送出する。この信号がHighになるまで、CPUはリセット状態に保持される。
電源ボタン押下
│
▼
PS_ON# → Low (PSU起動)
│
▼
電圧レール安定化 (+3.3V, +5V, +12V)
│
▼
PWR_OK → High (CPU リセット解除)
│
▼
CPU がリセットベクタから実行開始
- CPUのリセットベクタ:
PWR_OK信号を受けたCPUは、リセットベクタ(x86_64アーキテクチャでは通常0xFFFFFFF0)からの命令フェッチを開始する。このアドレスはUEFI/BIOSファームウェアが格納されたフラッシュROMにマッピングされている。
1.2 UEFI/BIOSの初期化フェーズ
現代のPCでは、従来のレガシーBIOSに代わりUEFI(Unified Extensible Firmware Interface)が標準的に使用されている。UEFIの起動プロセスはPI(Platform Initialization)仕様に基づき、以下のフェーズで進行する。
SEC(Security Phase)
- CPUキャッシュをRAMとして使用(CAR: Cache As RAM)
- 最小限のC言語実行環境を構築
- ファームウェアの整合性検証(Secure Bootの前段階)
- TPM(Trusted Platform Module)の初期化開始
PEI(Pre-EFI Initialization Phase)
- メモリコントローラの初期化
- DRAMの検出とトレーニング(メモリタイミングの最適化)
- PEIMと呼ばれるモジュール群がハードウェアの初期構成を実施
- HOB(Hand-Off Block)を介してDXEフェーズに情報を引き継ぐ
SEC Phase
│ CAR (Cache As RAM) を使用
│ ファームウェア整合性検証
▼
PEI Phase
│ メモリコントローラ初期化
│ DRAM検出・トレーニング
│ HOBの構築
▼
DXE Phase
│ デバイスドライバのロード
│ プロトコルの登録
│ ブートデバイスの列挙
▼
BDS Phase
│ ブートオプションの評価
│ ブートローダーの起動
▼
TSL → RT (OS起動)
DXE(Driver Execution Environment Phase)
- UEFIドライバのロードと実行
- PCIeバスの列挙とデバイス検出
- NVMeコントローラ、USBコントローラ、ネットワークコントローラなどの初期化
- UEFI Boot Servicesプロトコルの登録
- GOP(Graphics Output Protocol)によるディスプレイ出力の初期化
BDS(Boot Device Selection Phase)
- NVRAM内のブート変数(
Boot0001,Boot0002...)の読み出し - ブート順序(
BootOrder変数)に従ったブートデバイスの列挙 - EFIシステムパーティション(ESP)上のブートローダー検出
# Linuxでのブート変数確認例
$ efibootmgr -v
BootCurrent: 0001
BootOrder: 0001,0002,0003
Boot0001* ubuntu HD(1,GPT,xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,0x800,0x100000)/File(\EFI\ubuntu\shimx64.efi)
Boot0002* Windows Boot Manager HD(1,GPT,yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy,0x800,0x82000)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
Boot0003* UEFI: Network PciRoot(0x0)/Pci(0x1f,0x6)/MAC(xxxxxxxxxxxx,1)
1.3 POST(Power-On Self-Test)
POST はDXEフェーズの一部として実行され、主要なハードウェアコンポーネントの動作を検証する。
| 検査項目 | 内容 |
|---|---|
| CPU | レジスタ、キャッシュ、命令実行の基本テスト |
| メモリ | DRAM全容量の読み書きテスト、ECC検証 |
| GPU | VRAM初期化、基本的な描画テスト |
| ストレージ | NVMe/SATA コントローラの応答確認 |
| キーボード | PS/2 または USB HID の検出 |
| ネットワーク | NIC(Network Interface Card)のPCIe列挙と基本初期化 |
POSTエラーはビープコード(レガシー)またはUEFI POST コード(LPC/SPI経由でPOSTカードに出力)として通知される。
1.4 Secure Boot
UEFI Secure Bootが有効な場合、ブートローダーの署名が以下のデータベースに照合される。
- PK(Platform Key): プラットフォームの所有者鍵(通常はハードウェアメーカー)
- KEK(Key Exchange Key): 署名データベースの更新を許可された鍵
- db(Authorized Signature Database): 信頼された署名のリスト
- dbx(Forbidden Signature Database): 拒否される署名のリスト
ブートローダー (.efi)
│
▼
署名の抽出
│
▼
db に署名が存在するか? ──Yes──→ 起動許可
│
No
▼
dbx に署名が存在するか? ──Yes──→ 起動拒否
│
No
▼
起動拒否(デフォルト拒否ポリシー)
Phase 2: ブートローダーとOSカーネルの起動
2.1 ブートローダー(GRUB2 / Windows Boot Manager)
Linux環境の場合(GRUB2)
UEFIがESP上のshimx64.efi(Secure Boot対応の場合)またはgrubx64.efiをロードすると、GRUB2ブートローダーが制御を引き継ぐ。
# GRUB2設定ファイルの例 (/boot/grub/grub.cfg 抜粋)
menuentry 'Ubuntu 24.04 LTS' --class ubuntu --class gnu-linux {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
insmod part_gpt
insmod ext2
set root='hd0,gpt2'
linux /vmlinuz-6.8.0-generic root=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ro quiet splash
initrd /initrd.img-6.8.0-generic
}
GRUB2は以下を順次実行する:
grub.cfgの解析とメニュー表示- カーネルイメージ(
vmlinuz)のメモリへのロード - 初期RAMディスク(
initrd/initramfs)のロード - カーネルコマンドラインパラメータの設定
- UEFI Boot Servicesの終了(
ExitBootServices()) - カーネルのエントリポイントへのジャンプ
Windows環境の場合
bootmgfw.efi → winload.efi → ntoskrnl.exeの順にロードされる。BCD(Boot Configuration Data)ストアに基づいてブートオプションが決定される。
# BCDストアの確認例
PS> bcdedit /enum
Windows Boot Manager
--------------------
identifier {bootmgr}
device partition=\Device\HarddiskVolume1
path \EFI\Microsoft\Boot\bootmgfw.efi
default {current}
Windows Boot Loader
-------------------
identifier {current}
device partition=C:
path \Windows\system32\winload.efi
systemroot \Windows
2.2 カーネルの起動シーケンス
Linuxカーネルの場合
カーネル起動は大きく以下のステップで進む:
GRUB2 → vmlinuz (圧縮カーネル) ロード
│
▼
カーネル展開 (gzip/lz4/zstd)
│
▼
start_kernel() [init/main.c]
│
├─ setup_arch() ← アーキテクチャ固有の初期化
├─ mm_init() ← メモリ管理サブシステム
├─ sched_init() ← スケジューラ
├─ init_IRQ() ← 割り込みコントローラ (APIC)
├─ time_init() ← タイマーサブシステム
├─ console_init() ← コンソール
├─ vfs_caches_init() ← VFS初期化
├─ page_alloc_init() ← ページアロケータ
├─ signals_init() ← シグナル処理
├─ proc_root_init() ← /procファイルシステム
├─ rest_init()
│ ├─ kernel_thread(kernel_init) ← PID 1
│ └─ kernel_thread(kthreadd) ← PID 2
│
▼
kernel_init()
│
├─ initramfs の展開とマウント
├─ デバイスドライバのロード (モジュール)
├─ ルートファイルシステムのマウント
│ (initramfs内のスクリプトが実行)
│ (root=UUID=xxx に基づくルートFS切替)
├─ /sbin/init の実行 (→ systemd)
│
▼
systemd (PID 1) の起動
主要なカーネルサブシステムの初期化
| サブシステム | 関数 | 役割 |
|---|---|---|
| メモリ管理 | mm_init() | 物理/仮想メモリ、スラブアロケータ |
| プロセス管理 | sched_init() | CFS/RTスケジューラ、idle thread |
| VFS | vfs_caches_init() | inode/dentry キャッシュ |
| ネットワーク | sock_init() | ソケット層の初期化 |
| デバイスモデル | driver_init() | sysfs、kobject、デバイスツリー |
| ネットワークデバイス | net_dev_init() | ネットデバイスの基盤初期化 |
2.3 initシステム(systemd)の起動
systemdはPID 1として起動し、ユニットファイルに基づいてシステムサービスを並列起動する。
# systemdのブートプロセスの依存関係(一部)
$ systemd-analyze critical-chain
graphical.target @15.234s
└─multi-user.target @15.233s
└─NetworkManager.service @5.102s +1.234s
└─dbus.service @4.892s +0.156s
└─basic.target @4.889s
└─sockets.target @4.888s
└─dbus.socket @4.886s
└─sysinit.target @4.883s
└─systemd-journald.service @1.023s +0.234s
└─systemd-journald.socket @1.019s
└─system.slice @1.015s
└─-.slice @1.010s
ネットワーク関連で重要なのは以下のユニット:
# ネットワーク関連systemdユニットの例
$ systemctl list-units --type=service | grep -i network
NetworkManager.service loaded active running Network Manager
systemd-networkd.service loaded active running Network Service
systemd-resolved.service loaded active running Network Name Resolution
wpa_supplicant.service loaded active running WPA supplicant
2.4 カーネルのネットワークスタック初期化
カーネル起動時に、ネットワークサブシステムは以下の順序で初期化される:
-
ソケット層の初期化 (
sock_init):sk_buffキャッシュの作成(ネットワークパケットの基本データ構造)- ソケットファイルシステム(sockfs)の登録
-
Netlinkソケットの初期化 (
netlink_proto_init):- カーネルとユーザー空間のネットワーク設定通信用
-
ネットデバイス初期化 (
net_dev_init):- loopbackデバイス (
lo) の登録 - Per-CPU パケット処理キュー(softnet_data)の初期化
- NAPI(New API)ポーリングの準備
- loopbackデバイス (
-
プロトコルファミリの登録:
inet_init(): IPv4プロトコルスタック(TCP, UDP, ICMP, IGMP)inet6_init(): IPv6プロトコルスタックpacket_init(): rawソケット(tcpdump等が使用)
// カーネルソースにおけるプロトコル登録の概念的な流れ
// net/ipv4/af_inet.c
static int __init inet_init(void)
{
// TCP/UDP/ICMPプロトコルの登録
proto_register(&tcp_prot, 1);
proto_register(&udp_prot, 1);
proto_register(&raw_prot, 1);
proto_register(&ping_prot, 1);
// ソケットタイプの登録
sock_register(&inet_family_ops);
// ARP初期化
arp_init();
// IPルーティングテーブル初期化
ip_init();
// TCPスタック初期化
tcp_init();
// UDP初期化
udp_init();
return 0;
}
Phase 3: ネットワークインターフェースの初期化とIPアドレスの取得
3.1 NICドライバのロードとリンクアップ
OSI参照モデル: 第1層(物理層)・第2層(データリンク層)
OSが起動すると、PCIeバスのスキャンによってNIC(Network Interface Card)が検出され、対応するカーネルモジュール(ドライバ)がロードされる。
# NICの検出とドライバのロード確認
$ lspci | grep -i ethernet
03:00.0 Ethernet controller: Intel Corporation I225-V (rev 03)
$ lsmod | grep igc
igc 245760 0
$ dmesg | grep igc
[ 2.345678] igc 0000:03:00.0: PCIe Gen3 x1
[ 2.345890] igc 0000:03:00.0: 2.500 Gbps Full Duplex
[ 2.346012] igc 0000:03:00.0: MAC Address: aa:bb:cc:dd:ee:ff
[ 2.456789] igc 0000:03:00.0 eth0: renamed from enp3s0
物理層(Layer 1)の確立
有線イーサネットの場合:
-
オートネゴシエーション: NIC間でリンク速度とデュプレックスモードを交渉
- IEEE 802.3ab (1000BASE-T) / 802.3bz (2.5GBASE-T / 5GBASE-T)
- FLP(Fast Link Pulse)バーストによる能力アドバタイズ
-
リンクアップ: 物理的な電気信号レベルでの接続確立
- キャリア検出(Carrier Detect)
- NICのLEDが点灯(Link LED: 点灯、Activity LED: 点滅)
# リンク状態の確認
$ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
2500baseT/Full
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
$ ip link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff
Wi-Fiの場合は追加で以下のステップが発生する:
- 無線インターフェースの初期化:
cfg80211/mac80211サブシステム - スキャン: 周囲のSSIDをプローブリクエストで探索
- 認証: Open System / SAE(WPA3)
- アソシエーション: APとの接続確立
- 4ウェイハンドシェイク(WPA2/WPA3): PTK/GTKの導出
# Wi-Fi接続状態の確認
$ iw dev wlan0 link
Connected to xx:xx:xx:xx:xx:xx (on wlan0)
SSID: HomeNetwork
freq: 5180
signal: -45 dBm
tx bitrate: 866.7 MBit/s VHT-MCS 9 80MHz short GI VHT-NSS 2
security: WPA2
データリンク層(Layer 2)の確立
- MACアドレスの設定(NICのEEPROMから読み出し、またはソフトウェア設定)
- イーサネットフレームの送受信能力の確立
- MTU(Maximum Transmission Unit)のデフォルト値設定(通常1500バイト)
3.2 DHCP によるIPアドレスの取得
OSI参照モデル: 第3層(ネットワーク層)・第7層(アプリケーション層) TCP/IPモデル: インターネット層・アプリケーション層
ほとんどの家庭・企業ネットワークでは、DHCP(Dynamic Host Configuration Protocol)によりIPアドレスが自動的に割り当てられる。
DHCP 4段階プロセス (DORA)
クライアント (PC) DHCPサーバー (ルーター)
│ │
│ 1. DHCP DISCOVER │
│ src: 0.0.0.0:68 │
│ dst: 255.255.255.255:67 │
│ (ブロードキャスト) │
│ ─────────────────────────────────────→ │
│ │
│ 2. DHCP OFFER │
│ src: 192.168.1.1:67 │
│ dst: 255.255.255.255:68 │
│ 提案: IP=192.168.1.100 │
│ ←───────────────────────────────────── │
│ │
│ 3. DHCP REQUEST │
│ src: 0.0.0.0:68 │
│ dst: 255.255.255.255:67 │
│ 要求: IP=192.168.1.100 │
│ ─────────────────────────────────────→ │
│ │
│ 4. DHCP ACK │
│ src: 192.168.1.1:67 │
│ dst: 255.255.255.255:68 │
│ 確認: IP=192.168.1.100 │
│ Subnet=255.255.255.0 │
│ Gateway=192.168.1.1 │
│ DNS=192.168.1.1, 8.8.8.8 │
│ Lease=86400s │
│ ←───────────────────────────────────── │
│ │
DHCPパケットの詳細構造
イーサネットフレーム:
┌─────────────┬──────────────┬───────────┬──────────────────────────────────┐
│ dst MAC │ src MAC │ EtherType │ ペイロード │
│ ff:ff:ff:.. │ aa:bb:cc:.. │ 0x0800 │ IP → UDP → DHCP │
│ (broadcast) │ (クライアント) │ (IPv4) │ │
└─────────────┴──────────────┴───────────┴──────────────────────────────────┘
IPv4ヘッダ (DHCP DISCOVER):
┌──────────┬──────┬────────────┬──────────────────┐
│ src IP │ TTL │ Protocol │ dst IP │
│ 0.0.0.0 │ 128 │ 17 (UDP) │ 255.255.255.255 │
└──────────┴──────┴────────────┴──────────────────┘
UDPヘッダ:
┌────────────┬────────────┬────────┐
│ src port │ dst port │ length │
│ 68 │ 67 │ varies │
└────────────┴────────────┴────────┘
DHCPメッセージ:
┌───────────┬────────────────────────────────────────────────┐
│ Op │ 1 (BOOTREQUEST) │
│ HType │ 1 (Ethernet) │
│ HLen │ 6 │
│ XID │ 0x12345678 (トランザクションID) │
│ CIAddr │ 0.0.0.0 (クライアントIP - まだなし) │
│ YIAddr │ 0.0.0.0 (割り当てIP - DISCOVERでは空) │
│ SIAddr │ 0.0.0.0 (サーバーIP) │
│ CHAddr │ aa:bb:cc:dd:ee:ff (クライアントMAC) │
│ Options │ 53: DHCP Message Type = Discover │
│ │ 55: Parameter Request List │
│ │ [1: Subnet Mask, 3: Router, 6: DNS, │
│ │ 15: Domain Name, 28: Broadcast, │
│ │ 51: Lease Time] │
│ │ 61: Client Identifier = aa:bb:cc:dd:ee:ff │
│ │ 12: Hostname = "my-desktop" │
└───────────┴────────────────────────────────────────────────┘
# tcpdumpによるDHCPパケットキャプチャ例
$ sudo tcpdump -i eth0 -vvv port 67 or port 68
15:30:01.123456 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
proto UDP (17), length 328)
0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from aa:bb:cc:dd:ee:ff,
length 300, xid 0x12345678, Flags [Broadcast]
Client-Ethernet-Address aa:bb:cc:dd:ee:ff
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message (53), length 1: Discover
Hostname (12), length 10: "my-desktop"
Parameter-Request (55), length 13:
Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6),
Domain-Name (15), Broadcast-Address (28), Lease-Time (51)
DHCP取得後のネットワーク設定
# IPアドレスの確認
$ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff
inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic eth0
valid_lft 86100sec preferred_lft 86100sec
inet6 fe80::a8bb:ccff:fedd:eeff/64 scope link
valid_lft forever preferred_lft forever
# ルーティングテーブルの確認
$ ip route show
default via 192.168.1.1 dev eth0 proto dhcp metric 100
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.100 metric 100
# DNSリゾルバの確認
$ cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 192.168.1.1
nameserver 8.8.8.8
# またはsystemd-resolvedの場合
$ resolvectl status
Global
Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (eth0)
Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 192.168.1.1
DNS Servers: 192.168.1.1 8.8.8.8
DNS Domain: lan
3.3 ARP(Address Resolution Protocol)
OSI参照モデル: 第2層(データリンク層)/ 第3層(ネットワーク層)の境界
IPアドレスを取得した後、実際にパケットを送信するにはデフォルトゲートウェイ(ルーター)のMACアドレスが必要である。ARPがこの解決を担う。
PC (192.168.1.100) ルーター (192.168.1.1)
│ │
│ ARP Request (ブロードキャスト) │
│ "Who has 192.168.1.1? │
│ Tell 192.168.1.100" │
│ ─────────────────────────────────→ │
│ │
│ ARP Reply (ユニキャスト) │
│ "192.168.1.1 is at │
│ 11:22:33:44:55:66" │
│ ←───────────────────────────────── │
│ │
│ ARPテーブルに記録 │
│ 192.168.1.1 → 11:22:33:44:55:66 │
# ARPテーブルの確認
$ ip neigh show
192.168.1.1 dev eth0 lladdr 11:22:33:44:55:66 REACHABLE
# ARPパケットキャプチャ例
$ sudo tcpdump -i eth0 -en arp
15:30:01.500000 aa:bb:cc:dd:ee:ff > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806),
length 42: Request who-has 192.168.1.1 tell 192.168.1.100
15:30:01.500234 11:22:33:44:55:66 > aa:bb:cc:dd:ee:ff, ethertype ARP (0x0806),
length 42: Reply 192.168.1.1 is-at 11:22:33:44:55:66
3.4 IPv6とNDP(Neighbor Discovery Protocol)
IPv6環境ではARPの代わりにNDP(RFC 4861)が使用される。
# IPv6のリンクローカルアドレス(自動設定)
$ ip -6 addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
inet6 fe80::a8bb:ccff:fedd:eeff/64 scope link
valid_lft forever preferred_lft forever
inet6 2001:db8:1::100/64 scope global dynamic mngtmpaddr
valid_lft 2591800sec preferred_lft 604600sec
# RA (Router Advertisement) で取得したIPv6情報
$ rdisc6 eth0
Soliciting ff02::2 (ff02::2) on eth0...
Hop limit : 64 ( 0x40)
Router lifetime : 1800 (0x00000708) seconds
Router preference: medium
Source link-layer address: 11:22:33:44:55:66
Prefix : 2001:db8:1::/64
Valid lifetime : 2592000 (30 days)
Pref. lifetime : 604800 ( 7 days)
from fe80::1
Phase 4: ブラウザの起動とURL入力
4.1 ブラウザプロセスの起動
ユーザーがデスクトップ環境でブラウザ(例: Google Chrome)のアイコンをダブルクリックすると、OSは以下の処理を行う。
ユーザー操作 (ダブルクリック)
│
▼
デスクトップ環境 (GNOME/KDE/Windows Explorer)
│
▼
fork() + execve("/usr/bin/google-chrome", ...)
│
├─ ELFバイナリのロード(Linuxの場合)
│ └─ 動的リンカー (ld-linux.so) による共有ライブラリロード
│ ├─ libc.so (C標準ライブラリ)
│ ├─ libpthread.so (スレッド)
│ ├─ libssl.so / libcrypto.so (OpenSSL/BoringSSL)
│ ├─ libnspr4.so (Netscape Portable Runtime)
│ └─ libnss3.so (Network Security Services)
│
▼
Chromeマルチプロセスアーキテクチャの初期化
├─ Browser Process (メインプロセス)
│ ├─ UI Thread
│ ├─ Network Thread (ネットワークI/O)
│ └─ Storage Thread
├─ GPU Process
├─ Utility Process
└─ (必要に応じて) Renderer Process × N
4.2 Chromeのマルチプロセスアーキテクチャ
Chromeはセキュリティとパフォーマンスのために複数のプロセスに分離されている。
| プロセス | 役割 | サンドボックス |
|---|---|---|
| Browser Process | UI、タブ管理、ネットワーク、ストレージ | なし(特権プロセス) |
| Renderer Process | HTML/CSS解析、JavaScript実行、DOM構築 | あり(厳格) |
| GPU Process | 描画コマンドの実行、コンポジティング | あり |
| Network Service | ネットワークI/O(Chrome 76+で分離) | あり |
| Plugin Process | Flash等のプラグイン(廃止傾向) | あり |
# Chromeのプロセス一覧確認例
$ ps aux | grep chrome | head -10
user 12345 2.5 3.2 1234567 265432 ? Sl 15:30 0:05 /usr/bin/google-chrome
user 12350 0.1 0.8 456789 67890 ? S 15:30 0:01 /usr/bin/google-chrome --type=zygote
user 12355 0.5 1.5 567890 123456 ? Sl 15:30 0:02 /usr/bin/google-chrome --type=gpu-process
user 12360 0.3 1.2 345678 98765 ? Sl 15:30 0:01 /usr/bin/google-chrome --type=utility --utility-sub-type=network.mojom.NetworkService
4.3 URL入力とナビゲーション開始
ユーザーがアドレスバーに www.amazon.com と入力してEnterを押すと、以下の処理が開始される。
ユーザー入力: "www.amazon.com"
│
▼
Omnibox(アドレスバー)の処理
│
├─ 入力がURLか検索クエリかの判定
│ "www.amazon.com" → URLとして認識
│
├─ スキームの補完
│ "www.amazon.com" → "https://www.amazon.com/"
│ (HSTS Preload List に amazon.com が含まれるため https に強制)
│
├─ ブラウザキャッシュの確認
│ ├─ HTTP キャッシュ (disk cache / memory cache)
│ ├─ Service Worker キャッシュ
│ └─ Preload / Prefetch キャッシュ
│
▼
ナビゲーション開始
│
├─ Browser Process → Network Thread に要求
│
▼
DNS名前解決の開始 (Phase 5へ)
4.4 HSTS(HTTP Strict Transport Security)
amazon.comはHSTS Preload Listに登録されているため、ブラウザはHTTPSへの接続を強制する。
ブラウザ内部の判定フロー:
│
▼
HSTS Preload List のチェック
│ (ブラウザにハードコードされたリスト)
│ amazon.com → includeSubDomains: true
│
├─ リストに存在 → https:// を強制
│
└─ リストに不在 → ローカルHSTSキャッシュを確認
│
├─ キャッシュにエントリあり → https:// を強制
│ (過去のStrict-Transport-Securityヘッダ由来)
│
└─ キャッシュにもなし → http:// でまず接続
(サーバーからのHTTPSリダイレクトを待つ)
# Chromeの内部HSTS確認 (chrome://net-internals/#hsts)
# Domain: amazon.com
# Found:
# static_sts_domain: amazon.com
# static_upgrade_mode: FORCE_HTTPS
# static_sts_include_subdomains: true
Phase 5: DNS名前解決
5.1 DNS解決の全体像
OSI参照モデル: 第7層(アプリケーション層) TCP/IPモデル: アプリケーション層 プロトコル: DNS(UDP/53、TCP/53、DoH/443、DoT/853)
ブラウザが www.amazon.com にアクセスするには、まずこのドメイン名を対応するIPアドレスに変換する必要がある。
"www.amazon.com" のDNS解決フロー:
┌─────────────────────────────────────────────────────────────────────┐
│ ブラウザ内部キャッシュ │
│ chrome://net-internals/#dns で確認可能 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ www.amazon.com → 未キャッシュ → 次のステップへ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ (キャッシュミス)
▼
┌─────────────────────────────────────────────────────────────────────┐
│ OSのDNSリゾルバキャッシュ │
│ Linux: systemd-resolved / nscd │
│ Windows: DNS Client サービス │
│ macOS: mDNSResponder │
│ ┌─────────────────────────────────────────────────┐ │
│ │ www.amazon.com → 未キャッシュ → 次のステップへ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ (キャッシュミス)
▼
┌─────────────────────────────────────────────────────────────────────┐
│ /etc/hosts ファイルの確認 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 127.0.0.1 localhost │ │
│ │ ::1 localhost │ │
│ │ # www.amazon.com のエントリなし → 次のステップへ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ (エントリなし)
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 再帰的DNSリゾルバへのクエリ送信 │
│ (192.168.1.1 → ルーターのDNSフォワーダー、 │
│ またはISPのDNSサーバー、またはパブリックDNS) │
└─────────────────────────────────────────────────────────────────────┘
5.2 名前解決の順序(nsswitch.conf)
Linuxでは/etc/nsswitch.confでDNS解決の順序が定義される。
$ cat /etc/nsswitch.conf | grep hosts
hosts: files mdns4_minimal [NOTFOUND=return] dns mymachines
# files = /etc/hosts を参照
# mdns4 = mDNS (Avahi) - .local ドメイン
# dns = DNSリゾルバ (/etc/resolv.conf)
# mymachines = systemd-machined (コンテナ)
5.3 DNSクエリの構造
ブラウザのNetwork ThreadからOSのgetaddrinfo() → stubリゾルバ → 再帰リゾルバ → 権威サーバーという流れでクエリが処理される。
DNSクエリパケット (UDP/53):
┌──────────────────────────────────────────────────────────┐
│ イーサネットヘッダ (14 bytes) │
│ dst: 11:22:33:44:55:66 src: aa:bb:cc:dd:ee:ff │
│ EtherType: 0x0800 (IPv4) │
├──────────────────────────────────────────────────────────┤
│ IPv4ヘッダ (20 bytes) │
│ src: 192.168.1.100 dst: 192.168.1.1 │
│ Protocol: 17 (UDP) TTL: 64 │
├──────────────────────────────────────────────────────────┤
│ UDPヘッダ (8 bytes) │
│ src port: 54321 dst port: 53 │
├──────────────────────────────────────────────────────────┤
│ DNSメッセージ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Header: │ │
│ │ ID: 0xABCD (トランザクションID) │ │
│ │ Flags: 0x0100 │ │
│ │ QR=0 (Query), Opcode=0 (Standard) │ │
│ │ RD=1 (Recursion Desired) │ │
│ │ QDCOUNT: 1, ANCOUNT: 0, NSCOUNT: 0, ARCOUNT: 1 │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Question Section: │ │
│ │ QNAME: www.amazon.com │ │
│ │ QTYPE: A (IPv4アドレス) │ │
│ │ QCLASS: IN (Internet) │ │
│ ├──────────────────────────────────────────────────────┤ │
│ │ Additional Section (EDNS0): │ │
│ │ OPT RR: UDP payload size=4096 │ │
│ │ EDNS version: 0 │ │
│ │ EDNS Client Subnet: 192.168.1.0/24 (optional) │ │
│ └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
5.4 再帰的クエリと反復的クエリ
クライアントから再帰DNSリゾルバへのクエリは再帰的クエリ(リゾルバに完全な解決を委任)であり、リゾルバから権威サーバーへのクエリは反復的クエリ(各段階で次の参照先を返す)である。
クライアント 再帰リゾルバ ルートDNS .com TLD DNS amazon.com 権威DNS
(192.168.1.100) (192.168.1.1 (a.root-servers (a.gtld-servers (ns-1.amazon
→ ISP DNS) .net) .net) dns.com)
│ │ │ │ │
│ 再帰クエリ │ │ │ │
│ "www.amazon.com │ │ │ │
│ のAレコードは?" │ │ │ │
│ ──────────────→ │ │ │ │
│ │ │ │ │
│ │ 反復クエリ │ │ │
│ │ "www.amazon.com?" │ │ │
│ │ ──────────────→ │ │ │
│ │ │ │ │
│ │ リファラル応答 │ │ │
│ │ "com.の権威は │ │ │
│ │ a.gtld-servers │ │ │
│ │ .net (192.5.6.30)"│ │ │
│ │ ←────────────── │ │ │
│ │ │ │ │
│ │ 反復クエリ │ │
│ │ "www.amazon.com?" │ │
│ │ ──────────────────────────────────→ │ │
│ │ │ │
│ │ リファラル応答 │ │
│ │ "amazon.comの権威は │ │
│ │ ns-1.amazondns.com │ │
│ │ (205.251.192.64)" │ │
│ │ ←────────────────────────────────── │ │
│ │ │ │
│ │ 反復クエリ │
│ │ "www.amazon.com?" │
│ │ ──────────────────────────────────────────────────────→ │
│ │ │
│ │ 最終回答 │
│ │ "www.amazon.com → CNAME → d3ag4hukkh62yn.cloudfront.net │
│ │ → A 99.84.191.123" │
│ │ ←────────────────────────────────────────────────────── │
│ │ │
│ 最終回答 │ │
│ "www.amazon.com │ │
│ = 99.84.191.123" │ │
│ ←────────────── │ │
5.5 DNSレスポンスの詳細
# digコマンドによるDNS解決の確認
$ dig www.amazon.com +trace +additional
; <<>> DiG 9.18.28 <<>> www.amazon.com +trace +additional
;; global options: +cmd
. 86400 IN NS a.root-servers.net.
. 86400 IN NS b.root-servers.net.
;; Received 525 bytes from 192.168.1.1#53(192.168.1.1) in 1 ms
com. 172800 IN NS a.gtld-servers.net.
a.gtld-servers.net. 172800 IN A 192.5.6.30
;; Received 839 bytes from 198.41.0.4#53(a.root-servers.net) in 15 ms
amazon.com. 172800 IN NS ns-1.amazondns.com.
amazon.com. 172800 IN NS ns-2.amazondns.co.uk.
amazon.com. 172800 IN NS ns-3.amazondns.org.
amazon.com. 172800 IN NS ns-4.amazondns.net.
ns-1.amazondns.com. 172800 IN A 205.251.192.64
;; Received 289 bytes from 192.5.6.30#53(a.gtld-servers.net) in 20 ms
www.amazon.com. 60 IN CNAME tp.47cf2c8c9-frontier.amazon.com.
tp.47cf2c8c9-frontier.amazon.com. 60 IN CNAME d3ag4hukkh62yn.cloudfront.net.
d3ag4hukkh62yn.cloudfront.net. 60 IN A 99.84.191.123
d3ag4hukkh62yn.cloudfront.net. 60 IN A 99.84.191.50
d3ag4hukkh62yn.cloudfront.net. 60 IN A 99.84.191.74
d3ag4hukkh62yn.cloudfront.net. 60 IN A 99.84.191.28
;; Received 227 bytes from 205.251.192.64#53(ns-1.amazondns.com) in 25 ms
5.6 amazon.comのDNS構成の特徴
amazon.comのDNS応答を解析すると、いくつかの重要な特徴が見える:
- CNAMEチェイン:
www.amazon.com→ frontier(Amazonの内部ルーティングシステム)→cloudfront.net(CDN) - CloudFront CDN: 最終的なAレコードはCloudFrontのエッジロケーションのIPアドレスを返す
- 地理ベースルーティング: DNSの応答は、クライアントの地理的位置に基づいて最寄りのCloudFrontエッジのIPを返す(Anycast + GeoDNS)
- 短いTTL: CDNのAレコードのTTLは60秒と短く、トラフィック誘導の柔軟性を確保
5.7 DNS over HTTPS (DoH) / DNS over TLS (DoT)
最新のブラウザでは、プライバシーとセキュリティのためにDNS over HTTPS(DoH)を使用する場合がある。
従来のDNS (UDP/53):
クライアント → [平文DNSクエリ] → リゾルバ
⚠ 中間者による盗聴・改ざんが可能
DNS over TLS (DoT, RFC 7858):
クライアント → [TLS暗号化] → tcp/853 → リゾルバ
✓ 暗号化されるが、ポート853の使用がDNSトラフィックであることを示す
DNS over HTTPS (DoH, RFC 8484):
クライアント → [HTTPS] → tcp/443 → リゾルバ
✓ 通常のHTTPSトラフィックと区別不可
✓ ChromeではデフォルトでDoHが有効化可能
# DoHでのDNS問い合わせ例 (curlを使用)
$ curl -s -H 'accept: application/dns-json' \
'https://dns.google/resolve?name=www.amazon.com&type=A' | python3 -m json.tool
{
"Status": 0,
"TC": false,
"RD": true,
"RA": true,
"AD": false,
"CD": false,
"Question": [
{
"name": "www.amazon.com.",
"type": 1
}
],
"Answer": [
{
"name": "www.amazon.com.",
"type": 5,
"TTL": 60,
"data": "tp.47cf2c8c9-frontier.amazon.com."
},
{
"name": "tp.47cf2c8c9-frontier.amazon.com.",
"type": 5,
"TTL": 60,
"data": "d3ag4hukkh62yn.cloudfront.net."
},
{
"name": "d3ag4hukkh62yn.cloudfront.net.",
"type": 1,
"TTL": 60,
"data": "99.84.191.123"
}
]
}
5.8 DNSキャッシュとTTL管理
DNS解決結果は複数のレベルでキャッシュされ、後続のリクエストを高速化する。
| キャッシュレベル | 場所 | 確認方法 |
|---|---|---|
| ブラウザDNSキャッシュ | Chrome/Firefox内部 | chrome://net-internals/#dns |
| OS DNSキャッシュ | systemd-resolved / Windows DNS Client | resolvectl statistics / ipconfig /displaydns |
| ルーターDNSキャッシュ | ホームルーター | ルーター管理画面 |
| ISP DNSキャッシュ | ISPの再帰リゾルバ | 外部からは不可視 |
# Linux: systemd-resolvedのキャッシュ統計
$ resolvectl statistics
DNSSEC supported by current servers: no
Transactions
Current Transactions: 0
Total Transactions: 1234
Cache
Current Cache Size: 45
Cache Hits: 890
Cache Misses: 344
Phase 6: TCP接続の確立(3ウェイハンドシェイク)
6.1 TCP/IPモデルにおける位置づけ
OSI参照モデル: 第4層(トランスポート層) TCP/IPモデル: トランスポート層
DNS解決によりIPアドレス(例: 99.84.191.123)を得たブラウザは、次にTCPコネクションを確立する。HTTPSのデフォルトポートは443である。
6.2 ソケットの作成
ブラウザ(Network Thread)は、OSに対してソケットの作成を要求する。
// 概念的なシステムコール
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// AF_INET: IPv4
// SOCK_STREAM: TCPストリームソケット
// IPPROTO_TCP: TCPプロトコル
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(443);
inet_pton(AF_INET, "99.84.191.123", &server_addr.sin_addr);
connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
// connect()の内部で3ウェイハンドシェイクが実行される
6.3 3ウェイハンドシェイクの詳細
クライアント (192.168.1.100:54321) サーバー (99.84.191.123:443)
│ │
│ ① SYN │
│ Seq=1000000000 (ISN: Initial Sequence Number) │
│ Window=65535 │
│ MSS=1460, SACK Permitted, Timestamps │
│ Window Scale=7 (Factor=128) │
│ ─────────────────────────────────────────────→ │
│ │
│ ② SYN-ACK │
│ Seq=2000000000 (サーバーのISN) │
│ Ack=1000000001 (クライアントのISN+1) │
│ Window=65535 │
│ MSS=1460, SACK Permitted, Timestamps │
│ Window Scale=9 (Factor=512) │
│ ←───────────────────────────────────────────── │
│ │
│ ③ ACK │
│ Seq=1000000001 │
│ Ack=2000000001 │
│ Window=65535 │
│ ─────────────────────────────────────────────→ │
│ │
│ TCP接続確立完了 (ESTABLISHED) │
6.4 TCPセグメントの構造
TCPセグメント (SYNパケットの例):
┌──────────────────────────────────────────────────────────┐
│ イーサネットフレーム │
│ dst: 11:22:33:44:55:66 (ゲートウェイMAC) │
│ src: aa:bb:cc:dd:ee:ff (自分のMAC) │
│ EtherType: 0x0800 │
├──────────────────────────────────────────────────────────┤
│ IPv4ヘッダ (20 bytes) │
│ Version: 4 │
│ IHL: 5 (20 bytes) │
│ DSCP: 0 (Best Effort) │
│ Total Length: 60 │
│ Identification: 0x1234 │
│ Flags: DF (Don't Fragment) │
│ TTL: 64 │
│ Protocol: 6 (TCP) │
│ Checksum: 0xABCD │
│ src: 192.168.1.100 │
│ dst: 99.84.191.123 │
├──────────────────────────────────────────────────────────┤
│ TCPヘッダ (40 bytes - オプション含む) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Source Port: 54321 │ │
│ │ Destination Port: 443 │ │
│ │ Sequence Number: 1000000000 │ │
│ │ Acknowledgment Number: 0 │ │
│ │ Data Offset: 10 (40 bytes) │ │
│ │ Flags: SYN │ │
│ │ Window Size: 65535 │ │
│ │ Checksum: 0xEF01 │ │
│ │ Urgent Pointer: 0 │ │
│ │ │ │
│ │ Options: │ │
│ │ MSS: 1460 │ │
│ │ SACK Permitted │ │
│ │ Timestamps: TSval=123456 TSecr=0 │ │
│ │ NOP │ │
│ │ Window Scale: 7 │ │
│ └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
6.5 TCPオプションの解説
| オプション | 説明 | 値の例 |
|---|---|---|
| MSS (Maximum Segment Size) | 1つのセグメントで送信可能な最大データサイズ。MTU(1500) - IPヘッダ(20) - TCPヘッダ(20) = 1460 | 1460 |
| Window Scale | ウィンドウサイズを拡張するシフト値。65535 × 2^7 = 8MB のウィンドウが可能 | 7 |
| SACK Permitted | 選択的確認応答の使用を許可。パケットロス時の再送効率が向上 | (フラグ) |
| Timestamps | RTT計測とPAWS(Protection Against Wrapped Sequences)に使用 | TSval, TSecr |
| ECN (Explicit Congestion Notification) | ネットワーク輻輳の明示的通知 | ECE, CWR |
6.6 パケットがネットワークを通過する経路
TCPのSYNパケットがクライアントからサーバーに到達するまでの物理的な経路を追跡する。
PC (192.168.1.100)
│ [イーサネット: L2スイッチング]
▼
ホームルーター (192.168.1.1)
│ [NAT: 192.168.1.100:54321 → <グローバルIP>:54321]
│ [PPPoE/IPoE でISPに接続]
▼
ISP アクセスネットワーク
│ [光ファイバー / DOCSIS]
▼
ISP コアルーター
│ [BGPルーティング: AS間経路選択]
▼
Internet Exchange Point (IXP)
│ [ピアリング/トランジット]
▼
Amazon CloudFront エッジロケーション (PoP)
│ [Anycast → 最寄りのエッジ]
▼
CloudFront エッジサーバー (99.84.191.123)
# tracerouteによる経路確認例
$ traceroute -n www.amazon.com
traceroute to d3ag4hukkh62yn.cloudfront.net (99.84.191.123), 30 hops max, 60 byte packets
1 192.168.1.1 1.234 ms 1.123 ms 1.098 ms # ホームルーター
2 10.0.0.1 5.678 ms 5.432 ms 5.321 ms # ISP アクセス
3 172.16.0.1 10.123 ms 10.234 ms 10.345 ms # ISP コア
4 72.14.209.81 12.345 ms 12.234 ms 12.123 ms # ピアリング
5 99.84.191.123 15.678 ms 15.567 ms 15.456 ms # CloudFront エッジ
# MTR (My Traceroute) によるリアルタイム経路品質監視
$ mtr -r -c 10 99.84.191.123
Loss% Snt Last Avg Best Wrst StDev
1. 192.168.1.1 0.0% 10 1.2 1.3 1.0 1.8 0.2
2. 10.0.0.1 0.0% 10 5.4 5.6 5.1 6.2 0.3
3. 172.16.0.1 0.0% 10 10.2 10.4 10.0 11.1 0.3
4. 72.14.209.81 0.0% 10 12.3 12.5 12.1 13.2 0.3
5. 99.84.191.123 0.0% 10 15.6 15.8 15.4 16.5 0.3
6.7 NAT(Network Address Translation)
ほとんどの家庭ネットワークでは、ルーターがNAT(特にNAPT/PAT)を実行し、プライベートIPアドレスをグローバルIPアドレスに変換する。
┌──────────── NAT変換テーブル ────────────────────────────────────────┐
│ │
│ 内部アドレス 外部アドレス プロトコル │
│ ─────────────────────── ─────────────────────── ────────── │
│ 192.168.1.100:54321 → 203.0.113.10:54321 TCP (SYN) │
│ 192.168.1.100:54322 → 203.0.113.10:54322 TCP (established) │
│ 192.168.1.101:50000 → 203.0.113.10:50000 UDP │
│ │
└────────────────────────────────────────────────────────────────────┘
送信時:
src: 192.168.1.100:54321 → src: 203.0.113.10:54321
dst: 99.84.191.123:443 → dst: 99.84.191.123:443 (変更なし)
受信時 (SYN-ACK):
src: 99.84.191.123:443 → src: 99.84.191.123:443 (変更なし)
dst: 203.0.113.10:54321 → dst: 192.168.1.100:54321
6.8 TCP Congestion Control
TCP接続が確立されると、輻輳制御アルゴリズムがデータ送信レートを管理する。
┌───────────────────────────────────────────────────┐
│ TCP輻輳制御の主要アルゴリズム │
├───────────────────────────────────────────────────┤
│ │
│ Slow Start Phase: │
│ cwnd: 1→2→4→8→16→...→ssthresh │
│ (指数的増加: RTTごとにcwndが2倍) │
│ │
│ Congestion Avoidance Phase: │
│ cwnd: ssthresh→ssthresh+1→ssthresh+2→... │
│ (線形増加: RTTごとにcwndが1増加) │
│ │
│ パケットロス検出時: │
│ ├─ 3重ACK: cwnd = cwnd/2 (Fast Recovery) │
│ └─ タイムアウト: cwnd = 1 (Slow Start再開) │
│ │
│ Linux デフォルト: CUBIC │
│ Google推奨: BBR (Bottleneck Bandwidth and RTT) │
│ │
└───────────────────────────────────────────────────┘
# 現在のTCP輻輳制御アルゴリズムの確認
$ sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic
# 利用可能なアルゴリズム
$ sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = reno cubic bbr
# TCP接続の状態確認
$ ss -tnp | grep 443
ESTAB 0 0 192.168.1.100:54321 99.84.191.123:443 users:(("chrome",pid=12345,fd=42))
Phase 7: TLS/SSLハンドシェイク(暗号化通信の確立)
7.1 TLSの位置づけ
OSI参照モデル: 第5層(セッション層)/ 第6層(プレゼンテーション層) TCP/IPモデル: アプリケーション層(TCPとHTTPの間)
TCP接続が確立された直後、HTTPSではTLS(Transport Layer Security)ハンドシェイクが開始される。amazon.comは2024年現在TLS 1.3を使用している。
7.2 TLS 1.3 ハンドシェイク
TLS 1.3はTLS 1.2と比較してハンドシェイクのラウンドトリップ数が削減されている(2-RTT → 1-RTT、0-RTT resumptionも可能)。
クライアント (Chrome) サーバー (CloudFront)
│ │
│ ① ClientHello │
│ ├─ TLS Version: 1.3 │
│ ├─ Random: [32 bytes] │
│ ├─ Session ID: [32 bytes] │
│ ├─ Cipher Suites: │
│ │ TLS_AES_256_GCM_SHA384 (0x1302) │
│ │ TLS_AES_128_GCM_SHA256 (0x1301) │
│ │ TLS_CHACHA20_POLY1305_SHA256 (0x1303) │
│ ├─ Compression Methods: null │
│ ├─ Extensions: │
│ │ server_name (SNI): www.amazon.com │
│ │ supported_versions: TLS 1.3, 1.2 │
│ │ supported_groups: x25519, secp256r1 │
│ │ signature_algorithms: ecdsa_secp256r1_sha256, │
│ │ rsa_pss_rsae_sha256 │
│ │ key_share: x25519 [32 bytes] │
│ │ psk_key_exchange_modes: psk_dhe_ke │
│ │ application_layer_protocol_negotiation: │
│ │ h2 (HTTP/2), http/1.1 │
│ │ encrypted_client_hello (ECH) (if supported)│
│ └─ Pre-Shared Key (if resumption) │
│ ─────────────────────────────────────────────→ │
│ │
│ ② ServerHello │
│ ├─ TLS Version: 1.3 │
│ ├─ Random: [32 bytes] │
│ ├─ Cipher Suite: TLS_AES_128_GCM_SHA256 │
│ ├─ Extensions: │
│ │ supported_versions: TLS 1.3 │
│ │ key_share: x25519 [32 bytes] │
│ │ │
│ ── 以降のメッセージはすべて暗号化 ── │
│ │ │
│ ③ EncryptedExtensions │
│ │ application_layer_protocol_negotiation: h2 │
│ │ │
│ ④ Certificate │
│ │ サーバー証明書チェイン: │
│ │ [0] *.amazon.com (エンドエンティティ) │
│ │ [1] Amazon RSA 2048 M02 (中間CA) │
│ │ [2] Amazon Root CA 1 (ルートCA) │
│ │ │
│ ⑤ CertificateVerify │
│ │ 署名: rsa_pss_rsae_sha256 │
│ │ (サーバーの秘密鍵で署名) │
│ │ │
│ ⑥ Finished │
│ │ verify_data: [HMAC of handshake] │
│ ←───────────────────────────────────────────── │
│ │
│ ⑦ Finished (クライアント) │
│ │ verify_data: [HMAC of handshake] │
│ ─────────────────────────────────────────────→ │
│ │
│ TLS 1.3 ハンドシェイク完了 │
│ Application Data の送受信開始 │
7.3 鍵交換の仕組み(ECDHE with x25519)
TLS 1.3では、前方秘匿性(Forward Secrecy)を保証するためにECDHE(Elliptic Curve Diffie-Hellman Ephemeral)が必須である。
鍵交換プロセス (x25519):
クライアント:
1. 秘密鍵 a を生成 (ランダムな256ビット値)
2. 公開鍵 A = a × G を計算 (Gは基点)
3. ClientHelloのkey_share拡張にAを含める
サーバー:
1. 秘密鍵 b を生成 (ランダムな256ビット値)
2. 公開鍵 B = b × G を計算
3. ServerHelloのkey_share拡張にBを含める
4. 共有秘密 S = b × A = b × a × G を計算
クライアント:
1. 共有秘密 S = a × B = a × b × G を計算
(a × b × G == b × a × G → 同一の共有秘密)
共有秘密 S から鍵スケジュール:
┌──────────────────────────────────────────┐
│ S (共有秘密) │
│ │ │
│ ▼ HKDF-Extract │
│ Early Secret │
│ │ │
│ ▼ Derive-Secret │
│ Handshake Secret │
│ ├─ client_handshake_traffic_secret │
│ └─ server_handshake_traffic_secret │
│ │ │
│ ▼ Derive-Secret │
│ Master Secret │
│ ├─ client_application_traffic_secret │
│ └─ server_application_traffic_secret │
│ │ │
│ ▼ │
│ AES-128-GCM の暗号化鍵とIVが導出される │
└──────────────────────────────────────────┘
7.4 証明書検証チェイン
ブラウザはサーバーから受信した証明書チェインを以下の手順で検証する。
サーバーから送信される証明書チェイン:
[0] エンドエンティティ証明書
Subject: CN=*.amazon.com
Issuer: CN=Amazon RSA 2048 M02
有効期間: 2024-01-01 ~ 2025-01-01
SANs: *.amazon.com, amazon.com, *.amazon.co.jp, ...
公開鍵: RSA 2048-bit
Key Usage: Digital Signature, Key Encipherment
Extended Key Usage: Server Authentication
OCSP: http://ocsp.r2m02.amazontrust.com
CRL: http://crl.r2m02.amazontrust.com/r2m02.crl
│
│ 発行者の署名で検証
▼
[1] 中間CA証明書
Subject: CN=Amazon RSA 2048 M02
Issuer: CN=Amazon Root CA 1
有効期間: 2022-08-23 ~ 2030-08-23
│
│ 発行者の署名で検証
▼
[2] ルートCA証明書 (ブラウザ/OSのトラストストアに存在)
Subject: CN=Amazon Root CA 1
Issuer: CN=Amazon Root CA 1 (自己署名)
有効期間: 2015-05-25 ~ 2038-01-17
─────────────────────────────────
✓ OSのトラストストアに存在 → 信頼確立
検証項目:
✓ 証明書チェインの署名が有効
✓ 各証明書の有効期限内
✓ SNI (www.amazon.com) がSANsに含まれる
✓ 鍵の用途が適切
✓ OCSP/CRL で失効していないことを確認
✓ Certificate Transparency ログに登録済み
# opensslで証明書チェインを確認
$ openssl s_client -connect www.amazon.com:443 -servername www.amazon.com < /dev/null 2>/dev/null | openssl x509 -noout -text | head -30
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
0a:1b:2c:3d:4e:5f:6a:7b:8c:9d:0e:1f:2a:3b:4c:5d
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, O = Amazon, CN = Amazon RSA 2048 M02
Validity
Not Before: Jan 1 00:00:00 2024 GMT
Not After : Jan 1 23:59:59 2025 GMT
Subject: CN = *.amazon.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:*.amazon.com, DNS:amazon.com, DNS:*.amazon.co.jp, ...
7.5 OCSP Stapling
サーバー証明書の失効確認にはOCSP Staplingが使われることが多い。
従来のOCSP:
ブラウザ → OCSPレスポンダ → "この証明書は有効?"
問題: プライバシー (CAにアクセス先が漏れる)、パフォーマンス
OCSP Stapling:
サーバーが定期的にOCSPレスポンダから署名付きレスポンスを取得し、
TLSハンドシェイク中にクライアントに「ステープル」(添付) して送信。
サーバー ──定期取得──→ OCSPレスポンダ
│
│ TLSハンドシェイク時に添付
▼
クライアント: OCSP署名を検証 → 証明書は有効
7.6 ALPN(Application-Layer Protocol Negotiation)
TLSハンドシェイク中に、アプリケーション層プロトコルの選択が行われる。
ClientHello:
ALPN Extension:
Protocol: h2 (HTTP/2) ← 優先
Protocol: http/1.1 ← フォールバック
ServerHello / EncryptedExtensions:
ALPN Extension:
Protocol: h2 ← HTTP/2が選択された
→ この接続ではHTTP/2が使用される
7.7 TLS 1.3 の 0-RTT (Early Data)
再接続時には、前回のセッションで取得したPSK(Pre-Shared Key)を使用して0-RTTデータ送信が可能。
再接続時 (0-RTT):
クライアント サーバー
│ │
│ ClientHello + Early Data │
│ ├─ PSK (前回のセッションから) │
│ ├─ key_share │
│ ├─ early_data │
│ └─ [暗号化されたHTTPリクエスト] │
│ GET / HTTP/2 │
│ ─────────────────────────────────────→ │
│ │
│ ServerHello + EncryptedExtensions │
│ + Finished │
│ + [暗号化されたHTTPレスポンス] │
│ ←───────────────────────────────────── │
│ │
注意: 0-RTTデータはリプレイ攻撃の可能性があるため、
冪等なリクエスト(GETなど)にのみ使用すべき。
7.8 TLSハンドシェイク完了後の状態
# opensslでTLS接続の詳細確認
$ openssl s_client -connect www.amazon.com:443 -servername www.amazon.com -tls1_3
CONNECTED(00000003)
---
SSL handshake has read 4567 bytes and written 345 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_128_GCM_SHA256
Session-ID: ABCDEF1234567890...
Master-Key: (not available in TLS 1.3)
PSK identity: None
Start Time: 1700000000
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
---
# Chromeのセキュリティタブでの確認:
# 鍵のアイコンをクリック → "Connection is secure"
# Protocol: TLS 1.3
# Key Exchange: X25519
# Cipher: AES_128_GCM
# Certificate: *.amazon.com (Amazon RSA 2048 M02)
Phase 8: HTTPリクエストとレスポンス
8.1 HTTP/2 プロトコルの概要
OSI参照モデル: 第7層(アプリケーション層) TCP/IPモデル: アプリケーション層
TLSハンドシェイクのALPNでHTTP/2が選択されると、バイナリフレーミング層の上でHTTP通信が行われる。
8.2 HTTP/2 接続の初期化
HTTP/2 Connection Preface:
クライアント → サーバー:
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" (マジック文字列, 24 bytes)
SETTINGS Frame (Stream 0):
HEADER_TABLE_SIZE: 65536
ENABLE_PUSH: 1
MAX_CONCURRENT_STREAMS: 100
INITIAL_WINDOW_SIZE: 6291456
MAX_FRAME_SIZE: 16384
MAX_HEADER_LIST_SIZE: 262144
サーバー → クライアント:
SETTINGS Frame (Stream 0):
MAX_CONCURRENT_STREAMS: 128
INITIAL_WINDOW_SIZE: 65535
MAX_FRAME_SIZE: 16777215
クライアント → サーバー:
SETTINGS ACK Frame (空)
サーバー → クライアント:
SETTINGS ACK Frame (空)
8.3 HTTP/2フレームの構造
HTTP/2 フレーム:
┌─────────────────────────────────────────────┐
│ Length (24 bits) │ Type (8 bits) │
├────────────────────────┼────────────────────┤
│ Flags (8 bits) │ Reserved (1 bit) │
│ │ Stream ID (31 bits) │
├─────────────────────────────────────────────┤
│ Frame Payload (可変長) │
└─────────────────────────────────────────────┘
主要なフレームタイプ:
DATA (0x0) : HTTPボディデータ
HEADERS (0x1) : HTTPヘッダ (HPACK圧縮)
PRIORITY (0x2) : ストリーム優先度
RST_STREAM (0x3): ストリームの終了
SETTINGS (0x4) : 接続設定
PUSH_PROMISE (0x5): サーバープッシュ
PING (0x6) : 死活監視
GOAWAY (0x7) : 接続の終了
WINDOW_UPDATE (0x8): フロー制御
8.4 HTTPリクエストの送信
ブラウザがwww.amazon.comのトップページをリクエストする。
HTTP/2 HEADERS Frame (Stream 1):
┌──────────────────────────────────────────────────────────┐
│ :method = GET │
│ :scheme = https │
│ :authority = www.amazon.com │
│ :path = / │
│ user-agent = Mozilla/5.0 (X11; Linux x86_64) │
│ AppleWebKit/537.36 (KHTML, like Gecko) │
│ Chrome/120.0.0.0 Safari/537.36 │
│ accept = text/html,application/xhtml+xml, │
│ application/xml;q=0.9,image/avif, │
│ image/webp,image/apng,*/*;q=0.8 │
│ accept-encoding = gzip, deflate, br, zstd │
│ accept-language = ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7 │
│ cache-control = no-cache │
│ sec-ch-ua = "Not_A Brand";v="8","Chromium";v="120", │
│ "Google Chrome";v="120" │
│ sec-ch-ua-mobile = ?0 │
│ sec-ch-ua-platform = "Linux" │
│ sec-fetch-dest = document │
│ sec-fetch-mode = navigate │
│ sec-fetch-site = none │
│ sec-fetch-user = ?1 │
│ upgrade-insecure-requests = 1 │
│ cookie = session-id=xxx-xxxxxxx-xxxxxxx; │
│ session-id-time=xxxxxxxxxx; │
│ i18n-prefs=JPY; ... │
└──────────────────────────────────────────────────────────┘
8.5 HPACK ヘッダ圧縮
HTTP/2ではHPACKによりヘッダが効率的に圧縮される。
HPACK圧縮の仕組み:
1. 静的テーブル (61エントリ):
Index 1: :authority → (空)
Index 2: :method → GET
Index 3: :method → POST
Index 4: :path → /
Index 5: :path → /index.html
...
Index 61: www-authenticate → (空)
2. 動的テーブル (接続中に構築):
最初のリクエストで送信したヘッダがテーブルに追加される。
2回目以降はインデックス番号だけで参照可能。
例:
1回目: ":method GET" → 静的テーブル Index 2 → 1バイト
"user-agent: Mozilla/5.0..." → リテラル送信 → 50+バイト
(動的テーブルに追加)
2回目: "user-agent: Mozilla/5.0..." → 動的テーブル Index 62 → 1バイト
圧縮効果:
非圧縮ヘッダ: ~800 bytes
HPACK圧縮後: ~150 bytes (約80%削減)
8.6 HTTPレスポンスの受信
HTTP/2 HEADERS Frame (Stream 1):
┌──────────────────────────────────────────────────────────┐
│ :status = 200 │
│ content-type = text/html; charset=UTF-8 │
│ content-encoding = gzip │
│ content-length = 245678 │
│ server = Server │
│ date = Sat, 01 Jan 2025 12:00:00 GMT │
│ x-amz-rid = XXXXXXXXXXXXXXXXX │
│ set-cookie = session-id=xxx-xxxxxxx-xxxxxxx; │
│ Domain=.amazon.com; Path=/; │
│ Expires=Sat, 01 Jan 2035 00:00:00 GMT; │
│ Secure; HttpOnly │
│ set-cookie = session-id-time=xxxxxxxxxx; │
│ Domain=.amazon.com; Path=/; │
│ Secure; HttpOnly │
│ strict-transport-security = max-age=47474747; │
│ includeSubDomains │
│ x-content-type-options = nosniff │
│ x-frame-options = SAMEORIGIN │
│ x-xss-protection = 1; mode=block │
│ content-security-policy = ... │
│ cache-control = no-cache, no-store, must-revalidate │
│ pragma = no-cache │
│ expires = 0 │
│ vary = Accept-Encoding,User-Agent,Content-Type │
│ x-amz-cf-pop = NRT51-P2 │
│ x-amz-cf-id = XXXXXXXXXXXXXXXXXXXXXXX │
└──────────────────────────────────────────────────────────┘
HTTP/2 DATA Frames (Stream 1):
┌──────────────────────────────────────────────────────────┐
│ [gzip圧縮されたHTMLコンテンツ] │
│ 複数のDATAフレームに分割して送信 │
│ Frame 1: 16384 bytes │
│ Frame 2: 16384 bytes │
│ Frame 3: 16384 bytes │
│ ... │
│ Frame N: 残りバイト (END_STREAMフラグ) │
└──────────────────────────────────────────────────────────┘
8.7 レスポンスヘッダの重要な要素
| ヘッダ | 値 | 意味 |
|---|---|---|
strict-transport-security | max-age=47474747; includeSubDomains | HSTS: 約1.5年間HTTPSを強制 |
content-encoding | gzip | レスポンスボディがgzip圧縮されている |
x-amz-cf-pop | NRT51-P2 | CloudFrontのエッジロケーション(NRT=成田=東京リージョン) |
cache-control | no-cache, no-store, must-revalidate | キャッシュ禁止(パーソナライズされたコンテンツ) |
content-security-policy | (長文) | XSS防止のためのCSPポリシー |
x-frame-options | SAMEORIGIN | クリックジャッキング防止 |
8.8 HTTP/2のマルチプレキシング
メインのHTMLを受信した後、ブラウザは追加リソース(CSS、JS、画像等)を並列リクエストする。HTTP/2では単一のTCP接続上で複数のストリームが同時に通信できる。
Stream 1: GET / (HTML) ← 最初のリクエスト
Stream 3: GET /css/main.css ← HTMLパース中に発見
Stream 5: GET /js/app.bundle.js ← HTMLパース中に発見
Stream 7: GET /images/logo.png ← HTMLパース中に発見
Stream 9: GET /api/recommendations ← JavaScriptから
Stream 11: GET /images/product1.jpg ← レンダリング中に発見
HTTP/2 マルチプレキシングの可視化:
┌──────────────────────────────────────────────────────────┐
│ 時間→ │
│ │
│ Stream 1: [HEADERS][DATA][DATA][DATA][DATA]...[END] │
│ Stream 3: [HEADERS][DATA][DATA][END] │
│ Stream 5: [HEADERS][DATA][DATA][DATA]...[END] │
│ Stream 7: [HEADERS][DATA][END] │
│ Stream 9: [HEADERS]...[DATA][END] │
│ Stream 11: [HEADERS][DATA][DATA][END] │
│ │
│ ← 単一のTCP接続上で全ストリームがインターリーブ → │
└──────────────────────────────────────────────────────────┘
HTTP/1.1との比較:
HTTP/1.1: 6本のTCP接続 × 1リクエスト/接続 = 順次処理
HTTP/2: 1本のTCP接続 × N個のストリーム = 並列処理
8.9 Amazon CloudFront CDNのアーキテクチャ
www.amazon.comへのリクエストはCloudFront CDNを経由する。
ユーザーのリクエスト経路:
ブラウザ
│
│ HTTPS (TLS 1.3 + HTTP/2)
▼
CloudFront エッジロケーション (例: NRT51 = 東京)
│
├─ キャッシュヒット → 即座にレスポンス返却
│
└─ キャッシュミス
│
│ Amazon内部ネットワーク
▼
CloudFront リージョナルエッジキャッシュ
│
├─ キャッシュヒット → レスポンス返却
│
└─ キャッシュミス
│
│ Amazon内部ネットワーク
▼
オリジンサーバー (Amazon EC2/ELB)
│
│ アプリケーション処理
│ (パーソナライゼーション、推薦エンジン等)
▼
レスポンス生成 → 逆順に返却
CloudFront エッジロケーション (2024年時点):
450+ PoP (Points of Presence)
50+ 国・地域
日本: 東京(NRT), 大阪(KIX) 等
Phase 9: ブラウザのレンダリングパイプライン
9.1 レンダリングプロセスの全体像
ブラウザがHTMLレスポンスを受信した後、以下のパイプラインで画面上にWebページが描画される。
HTMLバイト受信 (gzip圧縮データ)
│
▼ gzip展開
HTMLテキスト
│
▼ HTMLパーサー (トークナイズ → ツリー構築)
DOM (Document Object Model) ツリー
│ CSS受信
│ │
│ ▼ CSSパーサー
│ CSSOM (CSS Object Model)
│ │
└──────────┬───────────────────────┘
│
▼ スタイル計算
Render Tree (表示されるノードのみ)
│
▼ レイアウト (Layout / Reflow)
Layout Tree (各要素の座標・サイズ計算)
│
▼ ペイント (Paint)
Paint Records (描画命令のリスト)
│
▼ コンポジット (Compositing)
レイヤー分割 → GPU転送 → 画面合成
│
▼
画面表示 (60fps = 16.67ms/フレーム)
9.2 HTMLパースとDOM構築
受信HTML (簡略化):
<!DOCTYPE html>
<html lang="ja-JP">
<head>
<meta charset="UTF-8">
<title>Amazon | 本, ファッション, 家電から食品まで | アマゾン</title>
<link rel="stylesheet" href="/css/main.css">
<script defer src="/js/app.bundle.js"></script>
</head>
<body>
<div id="a-page">
<header id="navbar">
<div id="nav-logo">
<a href="/">
<img src="/images/amazon-logo.png" alt="Amazon">
</a>
</div>
<div id="nav-search">
<form action="/s" method="GET">
<input type="text" id="twotabsearchtextbox"
placeholder="Amazonで検索">
<button type="submit">検索</button>
</form>
</div>
...
</header>
<main id="main-content">
...商品一覧、プロモーションバナー等...
</main>
<footer>...</footer>
</div>
</body>
</html>
↓ HTMLパーサー処理 ↓
DOMツリー:
Document
└─ html [lang="ja-JP"]
├─ head
│ ├─ meta [charset="UTF-8"]
│ ├─ title
│ │ └─ "Amazon | 本, ファッション..."
│ ├─ link [rel="stylesheet", href="/css/main.css"]
│ └─ script [defer, src="/js/app.bundle.js"]
└─ body
└─ div#a-page
├─ header#navbar
│ ├─ div#nav-logo
│ │ └─ a [href="/"]
│ │ └─ img [src="...", alt="Amazon"]
│ └─ div#nav-search
│ └─ form [action="/s"]
│ ├─ input#twotabsearchtextbox
│ └─ button
│ └─ "検索"
├─ main#main-content
│ └─ ...
└─ footer
└─ ...
9.3 パーサーブロッキングとプリロードスキャナー
HTMLパース中のリソース発見と読み込み:
パーサー プリロードスキャナー ネットワーク
│ │ │
│─ <link css>を発見 │
│ │── CSSを先読み ──→ │── /css/main.css
│─ <script>を発見 │
│ │── JSを先読み ──→ │── /js/app.bundle.js
│─ <img>を発見 │
│ │── 画像を先読み ──→ │── /images/logo.png
│ │
│ ※ defer属性付きscriptはDOMパースを │
│ ブロックしない │
│ ※ asyncスクリプトは到着次第実行 │
│ ※ CSSはレンダリングをブロック │
│ (CSOMが完成するまでレンダー不可) │
▼ │
<link rel="preload"> による明示的先読み:
<link rel="preload" href="/fonts/amazon-ember.woff2" as="font"
type="font/woff2" crossorigin>
→ 高優先度でフォントを事前にフェッチ
<link rel="preconnect"> による事前接続:
<link rel="preconnect" href="https://images-na.ssl-images-amazon.com">
→ DNS解決 + TCP接続 + TLSハンドシェイクを事前に実行
9.4 CSSOMの構築とスタイル計算
CSS (簡略化):
/* main.css */
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Amazon Ember', Arial, sans-serif; }
#navbar {
background: #131921;
height: 60px;
display: flex;
align-items: center;
}
#nav-search input {
width: 100%;
padding: 8px 12px;
border-radius: 4px;
}
↓ CSSパーサー処理 ↓
CSSOMツリー:
StyleSheet
├─ Rule: * { margin: 0; padding: 0; box-sizing: border-box }
├─ Rule: body { font-family: 'Amazon Ember', Arial, sans-serif }
├─ Rule: #navbar { background: #131921; height: 60px; ... }
└─ Rule: #nav-search input { width: 100%; ... }
↓ スタイル計算 (Computed Styles) ↓
各DOMノードに計算済みスタイルが適用される:
body → font-family: 'Amazon Ember'; font-size: 16px; color: #0F1111; ...
#navbar → display: flex; background-color: rgb(19, 25, 33);
height: 60px; width: 1920px; ...
※ カスケード(優先順位):
インライン > ID > クラス > 要素 > ユーザーエージェントスタイルシート
※ 継承: font-family, colorなどは親から子に継承
※ 初期値: 継承されないプロパティにはデフォルト値が適用
9.5 レイアウト(Layout / Reflow)
Render Tree のレイアウト計算:
ビューポート: 1920 × 1080 px
│
▼
body (1920 × auto)
└─ div#a-page (1920 × auto)
├─ header#navbar
│ x: 0, y: 0
│ width: 1920px, height: 60px
│ ├─ div#nav-logo
│ │ x: 15, y: 10
│ │ width: 113px, height: 40px
│ └─ div#nav-search
│ x: 300, y: 10
│ width: 780px, height: 40px
├─ main#main-content
│ x: 0, y: 60
│ width: 1920px, height: (コンテンツ依存)
│ ├─ プロモーションカルーセル
│ │ x: 0, y: 60, w: 1920, h: 600
│ ├─ 商品グリッド
│ │ x: 232, y: 660, w: 1456, h: auto
│ │ └─ (Flexbox/Grid レイアウト計算)
│ ...
└─ footer
x: 0, y: (上記要素の合計高さ)
width: 1920px, height: 200px
レイアウト計算の特徴:
- ボックスモデル (content + padding + border + margin)
- Flexboxレイアウト (ナビバー、商品カード)
- CSS Gridレイアウト (商品グリッド)
- フロート、ポジショニング (absolute/relative/fixed)
- テキストのライン・ブレーキングとフォントメトリクス
9.6 ペイント(Paint)とコンポジティング(Compositing)
ペイント処理:
各レンダーオブジェクトの描画命令リストを生成:
1. 背景色の塗りつぶし
2. 背景画像の描画
3. ボーダーの描画
4. 子要素の描画
5. アウトラインの描画
コンポジティング:
┌─────────────────────────────────────────────────────┐
│ レイヤー分割 (Layer Tree) │
│ │
│ Layer 0: ルートレイヤー (背景 + 静的コンテンツ) │
│ Layer 1: ナビバー (position: fixed) │
│ Layer 2: カルーセル (transform / will-change) │
│ Layer 3: 商品画像 (opacity アニメーション) │
│ Layer 4: ドロップダウンメニュー (z-index) │
│ │
│ 各レイヤーをタイル分割 → ラスタライズ (CPU or GPU) │
│ │
│ GPU コンポジター: │
│ 各レイヤーをテクスチャとしてGPUメモリに転送 │
│ OpenGL/Vulkan/Metal の描画コマンドで合成 │
│ VSync (垂直同期) に合わせてスワップバッファ │
│ │
│ → 画面に表示 │
└─────────────────────────────────────────────────────┘
9.7 JavaScript実行とDOMの動的操作
JavaScriptエンジン (V8) の処理:
app.bundle.js の実行
│
├─ パース → AST (抽象構文木)
├─ Ignition (インタプリタ) → バイトコード実行
├─ TurboFan (JITコンパイラ) → 最適化されたネイティブコード
│
├─ DOMの動的操作:
│ ├─ パーソナライズされたコンテンツの挿入
│ │ (おすすめ商品、閲覧履歴)
│ ├─ カルーセルのアニメーション初期化
│ ├─ 遅延ロード (Lazy Loading) の設定
│ │ (IntersectionObserver で画面内に入った画像をロード)
│ └─ イベントリスナーの登録
│ (クリック、スクロール、入力)
│
├─ 追加のHTTPリクエスト (XHR / Fetch API):
│ ├─ GET /api/recommendations → 推薦商品データ (JSON)
│ ├─ GET /api/deals → タイムセール情報
│ └─ POST /api/analytics → 行動分析データ送信
│
└─ Service Worker登録 (オフラインサポート)
9.8 Critical Rendering Path の最適化
amazon.com のパフォーマンス最適化手法:
1. Critical CSS インライン化:
<style>
/* ファーストビューに必要なCSSをHTMLに埋め込み */
#navbar { ... }
.hero-banner { ... }
</style>
2. JavaScript の遅延実行:
<script defer src="/js/app.bundle.js"></script>
<script async src="/js/analytics.js"></script>
3. リソースヒント:
<link rel="dns-prefetch" href="//images-na.ssl-images-amazon.com">
<link rel="preconnect" href="//fls-na.amazon.com">
<link rel="preload" href="/css/critical.css" as="style">
4. 画像最適化:
<img loading="lazy" <!-- 遅延ロード -->
srcset="img-300.webp 300w, <!-- レスポンシブ画像 -->
img-600.webp 600w,
img-1200.webp 1200w"
sizes="(max-width: 768px) 100vw, 300px"
src="img-300.jpg" <!-- フォールバック -->
alt="商品画像">
5. HTTP/2 Server Push (廃止傾向) / 103 Early Hints:
HTTP/1.1 103 Early Hints
Link: </css/main.css>; rel=preload; as=style
Link: </js/app.js>; rel=preload; as=script
9.9 Web Vitals パフォーマンス指標
主要なパフォーマンス指標:
LCP (Largest Contentful Paint): ≤ 2.5s
→ 最大のコンテンツ要素が表示されるまでの時間
→ amazon.comの場合: メインバナー画像
FID (First Input Delay) / INP (Interaction to Next Paint): ≤ 200ms
→ ユーザーの最初の操作に対する応答時間
CLS (Cumulative Layout Shift): ≤ 0.1
→ レイアウトの予期しない移動量
TTFB (Time to First Byte): ≤ 800ms
→ リクエスト送信からレスポンスの最初のバイトまで
FCP (First Contentful Paint): ≤ 1.8s
→ 最初のコンテンツ描画まで
典型的な amazon.com のタイムライン:
0ms : ナビゲーション開始
~50ms : DNS解決完了
~100ms : TCP接続確立
~150ms : TLSハンドシェイク完了
~200ms : HTTPリクエスト送信
~350ms : TTFB (最初のバイト受信)
~600ms : FCP (ナビバーの描画)
~1200ms : LCP (メインバナーの描画)
~2000ms : TTI (Time to Interactive - インタラクション可能)
Phase 10: 接続の終了とリソースの解放
10.1 HTTP/2 ストリームの終了
個々のHTTP/2ストリームの終了:
Stream 1 (HTML):
サーバー → クライアント:
DATA Frame [flags=END_STREAM]
→ Stream 1 は half-closed (remote)
クライアント: すべてのデータ受信完了
→ Stream 1 は closed
TCP接続自体はKeep-Aliveされ、追加リクエストに再利用される。
HTTP/2では1つのTCP接続で複数のリクエストを処理するため、
個々のストリーム終了 ≠ TCP接続終了。
10.2 TCP接続の終了(4ウェイハンドシェイク)
ブラウザのタブを閉じる、またはアイドルタイムアウトが発生すると、TCP接続が終了する。
クライアント サーバー
│ │
│ ① FIN │
│ Seq=N, Ack=M │
│ ─────────────────────────────────────→ │
│ │
│ ② ACK │
│ Seq=M, Ack=N+1 │
│ ←───────────────────────────────────── │
│ │
│ ③ FIN │
│ Seq=M, Ack=N+1 │
│ ←───────────────────────────────────── │
│ │
│ ④ ACK │
│ Seq=N+1, Ack=M+1 │
│ ─────────────────────────────────────→ │
│ │
│ クライアント: TIME_WAIT (2×MSL) │
│ → 一定時間後にソケット解放 │
│ │
状態遷移:
クライアント: ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED
サーバー: ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED
# TCP接続状態の確認
$ ss -tn state time-wait | head -5
Recv-Q Send-Q Local Address:Port Peer Address:Port
0 0 192.168.1.100:54321 99.84.191.123:443
# TIME_WAIT の確認
$ ss -s
Total: 234
TCP: 45 (estab 12, closed 8, orphaned 0, timewait 15)
10.3 TLSセッションの終了
TLS close_notify:
クライアント → サーバー:
Alert Protocol:
Level: Warning (1)
Description: close_notify (0)
サーバー → クライアント:
Alert Protocol:
Level: Warning (1)
Description: close_notify (0)
※ TLS 1.3ではclose_notifyはオプショナルだが推奨。
close_notifyなしでTCP FINが来た場合、
truncation attack の可能性を検知可能。
10.4 リソースの解放
接続終了後のリソース解放:
カーネル空間:
├─ ソケットバッファ (sk_buff) の解放
├─ TCBアドレス (Transmission Control Block) の解放
│ (TIME_WAIT 期間後)
├─ ファイルディスクリプタの解放
└─ conntrack テーブルエントリの削除 (NAT)
ユーザー空間 (Chrome):
├─ TLSセッション情報のキャッシュ
│ (次回接続のためのセッションチケット保持)
├─ HTTP/2接続プール からのエントリ削除
├─ DNSキャッシュの更新 (TTLに基づく)
└─ Renderer Process のメモリ管理
├─ DOM ツリー
├─ CSSOM
├─ JavaScript ヒープ (V8 GC)
└─ 画像デコードバッファ
まとめ: 全体の通信フローとレイヤー対応
全フェーズのタイムライン概要
時間軸 (概算)
────────────────────────────────────────────────────────────────────
0s 電源ボタン押下
0~3s PSU起動、POST、UEFI初期化
3~15s ブートローダー → カーネル起動 → systemd
15~30s ネットワーク初期化、DHCP取得
30~60s デスクトップ環境ロード完了 ← ログイン画面表示
... ユーザーがブラウザを起動
T+0ms URL入力、Enter押下
T+5ms HSTSチェック → https:// 確定
T+10ms ブラウザDNSキャッシュ確認 → ミス
T+15ms OS DNSキャッシュ確認 → ミス
T+20ms DNSクエリ送信 (UDP/53)
T+50ms DNS応答受信 (99.84.191.123)
T+55ms TCP SYN 送信
T+85ms TCP SYN-ACK 受信
T+90ms TCP ACK 送信 (接続確立)
T+95ms TLS ClientHello 送信
T+130ms TLS ServerHello + 証明書 受信
T+135ms TLS Finished 送信 (ハンドシェイク完了)
T+140ms HTTP/2 リクエスト送信 (GET /)
T+200ms HTTP/2 レスポンスヘッダ受信 (200 OK)
T+250ms HTML受信完了 → DOMパース開始
T+300ms 追加リソースリクエスト開始 (CSS, JS, images)
T+500ms Critical CSS適用 → FCP (First Contentful Paint)
T+1000ms メインコンテンツ表示 → LCP (Largest Contentful Paint)
T+1500ms JavaScript実行完了 → TTI (Time to Interactive)
T+2000ms 全リソースロード完了 → Load Event
────────────────────────────────────────────────────────────────────
各フェーズとOSI/TCP/IPレイヤーの対応表
| フェーズ | 主要プロトコル/技術 | OSI層 | TCP/IP層 |
|---|---|---|---|
| ハードウェア初期化 | 電気信号、PCIe、UEFI | - | - |
| OS起動 | カーネル、ドライバ | - | - |
| NIC初期化 | イーサネット、802.11 | L1, L2 | ネットワークIF |
| DHCP | DHCP (UDP/67-68) | L7 (L3経由) | アプリケーション |
| ARP | ARP | L2/L3境界 | ネットワークIF |
| DNS | DNS (UDP/53, DoH/443) | L7 | アプリケーション |
| TCP接続 | TCP (3ウェイハンドシェイク) | L4 | トランスポート |
| TLS | TLS 1.3 | L5/L6 | (TCP上) |
| HTTPリクエスト | HTTP/2 | L7 | アプリケーション |
| レスポンス処理 | HTML, CSS, JS | L7 | アプリケーション |
| 接続終了 | TCP (4ウェイハンドシェイク), TLS close_notify | L4, L5 | トランスポート |
パケットカプセル化の全体像
アプリケーションデータ(HTTPリクエスト)が送信される際のカプセル化:
┌─────────────────────────────────────────────────────────────────┐
│ イーサネットフレーム │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Ethernet Header (14B) │ │
│ │ dst MAC | src MAC | EtherType(0x0800) │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ IPv4 Packet │ │ │
│ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ IP Header (20B) │ │ │ │
│ │ │ │ src: 192.168.1.100 dst: 99.84.191.123 │ │ │ │
│ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ TCP Segment │ │ │ │ │
│ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │
│ │ │ │ │ │ TCP Header (20-60B) │ │ │ │ │ │
│ │ │ │ │ │ src: 54321 dst: 443 │ │ │ │ │ │
│ │ │ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ │ │ │
│ │ │ │ │ │ │ TLS Record │ │ │ │ │ │ │
│ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ TLS Header (5B) │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ Content Type: Application Data │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ ┌─────────────────────────────────┐ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ 暗号化されたHTTP/2フレーム │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ (AES-128-GCM で暗号化) │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ ┌───────────────────────────┐ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ HTTP/2 HEADERS Frame │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ :method GET │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ :path / │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ :authority www.amazon.com │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ └───────────────────────────┘ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ └─────────────────────────────────┘ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │
│ │ │ │ │ │ └─────────────────────────────────────────┘ │ │ │ │ │ │
│ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ │
│ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │
│ │ │ └─────────────────────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ Ethernet FCS (4B) │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
サイズの内訳 (典型的なHTTPSリクエスト):
Ethernet Header: 14 bytes
IP Header: 20 bytes
TCP Header: 32 bytes (オプション含む)
TLS Record: 5 bytes (ヘッダ) + 暗号化データ + 16 bytes (GCM tag)
HTTP/2 Frame: 9 bytes (フレームヘッダ) + HPACK圧縮ヘッダ
────────────────────────────
合計: ~300-500 bytes (典型的なGETリクエスト)
参考文献
- UEFI仕様: UEFI Forum, "Unified Extensible Firmware Interface Specification", Version 2.10
- RFC 2131: Dynamic Host Configuration Protocol (DHCP)
- RFC 1035: Domain Names - Implementation and Specification
- RFC 9293: Transmission Control Protocol (TCP) - Updated specification
- RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
- RFC 9113: HTTP/2
- RFC 8484: DNS Queries over HTTPS (DoH)
- RFC 826: An Ethernet Address Resolution Protocol (ARP)
- RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
- Linux Kernel Documentation: https://www.kernel.org/doc/html/latest/
- Chromium Design Documents: Multi-process Architecture, Network Stack
- Web Performance: Google Web Vitals, https://web.dev/vitals/
- Amazon CloudFront Developer Guide: AWS Documentation
- Intel® 64 and IA-32 Architectures Software Developer's Manual
- HPACK: Header Compression for HTTP/2 (RFC 7541)