ブラウザのURLバーにURLを入力して決定キーを押した時になにが起こるか

https://www.shonenjump.com/j/weeklyshonenjump/ を入力して決定キーを押した時になにが起こるか」 を調べた時のメモです。 自分用のメモなので読みづらいかもですがご了承ください。

※ 注意:以下の内容は誤りを含む場合があります。

目次

  1. ブラウザでの処理
  2. DNSによる名前解決
  3. TCP
  4. イーサネット/IPルーティング
  5. TLS
  6. HTTPレスポンスを受け取ったブラウザ

ブラウザでの処理

  1. 入力された文字列がURLかを判定 → URLでないならWeb検索
  2. 入力文字列がURLなら、文字列の解析
    • スキームの解析:about:、file:、http:、https:
    • キャッシュが存在するかの判定
      • if キャッシュが存在 && キャッシュが有効 then
        • キャッシュから読み出してブラウザに返却
      • else then
        • オリジンサーバに問い合わせ
  3. HTTPリクエストメッセージの作成

    • Chrome Devtools のNetworkタブからRequest Headers を確認すると、以下のようなHTTPリクエストメッセージが作成されていることがわかる
      リクエストヘッダー
    • :authority、:method、:path、:scheme などの疑似ヘッダーがあるので、HTTP/2が使われているぽい
      • DevtoolsのNetwork panelをご活用いただいてるとおもうのですが、表の見出し行を右クリックいただくと "Protocol"列を追加できます
  4. 作成したHTTPリクエストメッセージを送信する

    1. その前に、WebサーバのIPアドレスがわかっていないので、まずは取得する → 次章へ

DNSによる名前解決

DNSサーバにドメイン名を問い合わせ、サーバの「IPアドレス」を取得したい

  • dig コマンドを使えば確認できる

      dig +noedns www.shonenjump.com
    
      ; <<>> DiG 9.10.6 <<>> +noedns www.shonenjump.com
      ;; global options: +cmd
      ;; Got answer:
      ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 331
      ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
    
      ;; QUESTION SECTION:
      ;www.shonenjump.com.        IN  A
    
      ;; ANSWER SECTION:
      www.shonenjump.com. 300 IN  A   202.218.223.232
    
      ;; Query time: 118 msec
      ;; SERVER: 172.23.0.1#53(172.23.0.1)
      ;; WHEN: Wed Jul 03 23:29:16 JST 2024
      ;; MSG SIZE  rcvd: 52
    
    • IPアドレス202.218.223.232 らしい
    • DNSクエリは ;www.shonenjump.com. IN A っぽい
  • ローカルマシンのDNSキャッシュを確認してみる
    • Windowsだとコマンド一発で確認できた
      ipconfig/displayDNSの実行結果
    • ❓TODO: Mac環境での確認方法も知りたいな
    • ローカルマシンのDNSキャッシュに www.shonenjump.com がない場合、DNSゾルバに問い合わせる
  • DNSゾルバの動作
    DNSゾルバの動作
    • キャッシュ:毎回上位のDNSサーバに問い合わせていては時間がかかるので、ドメイン名-IPの対応づけをキャッシュしている
    • 💬 再帰問い合わせという設計にしている理由は、世界中の全てのWebサーバのドメイン-IPアドレスの対応付けを、1つのDNSでしてしまうと大変。なので、ドメインごとに階層化すればよいという考え方
  • dig +noedns で確認したDNSクエリは www.shonenjump.com. IN A だったが、shonenjump.comの権威DNSサーバが受け取るクエリも↑と同じ?

TCP

サーバに接続し、アプリケーションから依頼されたメッセージを小さな断片に分割してサーバに送信したい

この時、エラーでパッケットが消えてしまうことを想定し、分割した断片がサーバーに届いたかを確認、届かなかったら再送する

  • 参考:RFC 9293 - Transmission Control Protocol (TCP) 日本語訳
  • アプリケーションから見たソケット通信の流れ

      // 名前解決
      <メモリ領域> = gethostbyname("www.shonenjump.com");
    
      // 準備
      <ディスクリプタ> = socket(<IPv4を使用>, <ストリーム型>, ...);
    
      // 接続
      connect(<ディスクリプタ>, <サーバのIPアドレスとポート番号>, ...);
    
      // 送信
      write(<ディスクリプタ>, <送信データ>, <送信データ長>);
    
      // 受信
      <受信データ長> = read(<ディスクリプタ>, <受信バッファ>, ...);
    
      // 切断
      close(<ディスクリプタ>);
    
  • connectは、3 Way Handshaking 方式で確立される

    TCP 3-way handshaking

  • 接続 終了時

    TCP 接続終了

  • TCPヘッダのフォーマット

    各フィールド ビット数 各フィールドの説明
    送信元ポート番号 16 bit 送信元のポート番号の値。
    宛先ポート番号 16 bit 宛先のポート番号の値。
    シーケンス番号 32 bit 送信したデータの順序を示す値。「相手から受信した確認応答番号」の値。
    確認応答番号 32 bit 確認応答番号の値。「相手から受信したシーケンス番号」+「データサイズ」。
    データオフセット 4 bit TCPヘッダの長さを示す値。
    予約 3 bit 全ビット「0」が入る。将来の拡張のために用意されている。
    コントロールフラグ 9 bit NS、CWR、ECE、URG、ACK、PSH、RST、SYN、FINの9ビットで構成。これらのビットは「1」の値が入る(フラグを立てる)場合に意味をなす。
    ウィンドウサイズ 16 bit 受信側が一度に受信することができるデータ量を送信側に通知するために使用される。送信側は、この値のデータ量を超えて送信することはできない。
    チェックサム 16 bit TCPヘッダとデータ部分のエラーチェックを行うために使用される値が入る。
    緊急ポインタ 16 bit コントロールフラグのURGの値が「1」である場合にのみ使用されるフィールド。緊急データの開始位置を示す情報が入る。
    オプション 可変長 TCPの通信において、性能を向上させるために利用する。例えばTCPコネクションの際に、MSSを決定するために使用される。
    パディング 可変長 TCPヘッダの長さを32ビットの整数にするために詰め物(Padding)として空データの「0」の値を入れることにより調整する。
  • コントロールフラグの詳細

    ビット 値が「1」である(フラグが立っている)時の意味
    NS ECN-nonce 輻輳保護を示す。
    CWR 輻輳制御ウィンドウ縮小(Congestion Window Reduced)を示す。
    ECE ECN-Echo を示す。SYNフラグがセットされている場合、ECNが利用可能であることを意味する。
    URG 緊急に処理すべきデータが含まれていることを示す。
    ACK 確認応答番号のフィールドが有効であることを示す。コネクション確立時以外は値が「1」。
    PSH 受信したデータをバッファリングせずに、即座にアプリケーション(上位)に渡すことを示す。
    RST コネクションが強制的に切断されることを示す。何らかの異常を検出した場合に送信される。
    SYN コネクションの確立を要求することを示す。
    FIN コネクションの正常な終了を要求することを示す。
    • 💬 TCPフラグ値のLSB3bit → RST、SYN、FIN
  • TCPチェックサムの計算範囲(ピンク部分)

TCPチェックサムの計算範囲(ピンク部分)

  • ✍️ tcpdumpTCP通信をキャプチャして出力できる

イーサネット/IPルーティング

  • IPルーティングの仕組み
    • まず端末からL2 segment内のルータに投げる
      • 宛先がL2 segment内なら直接送信できる
      • 各ルータは自分が直接接続しているネットワークなら送れるが、それ以外は知らない
        • 今回のケースはLAN内ではない
        • その場合、とりあえずえデフォルトゲートウェイ(今回は gw.cysec.ritsumei.ac.jp)に送っている
    • デフォルトゲートウェイに送る際、送り元IPアドレス 192.168.100.18 はプライベートIPアドレスなので、グローバルIPに変換する必要がある
      • それをするのがNAT君
      • もし、プライベート↔︎グローバルIPの相互変換をしないままISPルータに送ると破棄されてしまう
    • デフォルトゲートウェイを経由してISPルータまで届けられたとして、どうやってさらにその先のネットワークに送り届けられるか?
      • IPルーティング:ルータ間でどこにどんなネットワークがあるのかを情報交換する仕組み
      • ルーティングテーブル:宛先IPアドレス→送り先ゲートウェイIPアドレスへの変換表
        • 実際にはネットワーク部分だけ見る
        • すべてのIPアドレスを経路表に登録して完全一致するかどうか調べてたら大変
        • ルーター同士のルーティングテーブルの交換は、BGPなどのプロトコルがある
    • ✍️ netstat -rn でマシンのルーティングテーブルを表示できる
  • :端末は、192.0.2.10というIPアドレスを宛先とするIPv4パケットを、ルータに送信します。しかしルータのIPアドレス192.168.0.1です。どうやってルータに送信するんでしょう。

  • 192.168.0.100発、192.0.2.10宛のIPv4パケットを受け取ったルータは、上流のISP(インターネットサービスプロバイダ)にパケットを転送します。しかしそのまま転送すると、ISPルータはこのパケットを破棄してしまうと思います、それはなぜでしょう。ルータは、転送する前に端末から受け取ったIPパケットに対してどういう加工を行いますか。

  • ISPルータは、家庭ルータから受け取ったパケットを、別のルータに向けて転送します。この際、ルータはパケットの加工をおこないますか?おこないませんか?(パケットのヘッダは、ルータが受け取ったパケットとルータが次ルータに送出するパケットで同じでしょうか?)理由とともに述べてください
    • TTLは変更しないとネットワーク内での無限ループが発生してしまう。TTLの変更に伴いIPヘッダチェックサムも再計算しないといけない。送信元IPアドレスや宛先IPアドレスに関しては変更しなくてもよい
  • ISPルータは、192.0.2.10サーバに直接繋がっておりません。複数のルータを経由して、最終的に192.0.2.10へパケットが到達します。また、ISPルータは、複数のルータと相互接続していると思います。どのルータにパケットを転送するか、どう決めているんでしょう。
    • ISPルータは、宛先IPアドレスに基づいてルーティングテーブルを参照し、最適な次ホップアドレスを決める
    • ルーティングテーブルの作成にはBGPを利用し、他のルータと経路情報を交換することで作成する

TLS

  • https://www.shonenjump.com/j/weeklyshonenjump/ では https とある通り、TLSプロトコルによりセキュアな接続が行われている
    • 通信の暗号化
    • 改ざん検知
    • 通信相手の認証
      1. クラウアント:デジタル証明書を要求
      2. サーバ:デジタル証明書を送付
      3. クライアント:デジタル証明書の情報から Webサーバの身元と安全性を確認
        • Chromeでは証明書ビューアから閲覧できる
          デジタル証明書ビューア

HTTPレスポンスを受け取ったブラウザ

参考

https://bookplus.nikkei.com/atcl/catalog/07/P83110/

https://www.slideshare.net/slideshow/url-120966707/120966707

https://browserbook.shift-js.info/