12. インターネットはどのような仕組みで動いているのか

インターネットがどのような仕組みで動いているのか理解しやすくするために、 ここでは、典型的なインターネットの操作、すなわち、Linux Documentation Project のウェブページ上にあるこの文書の最初のページをブラウザ上で クリックした場合に、どのようなことが起こっているのかを概観しましょう。 例えば、この文書は次の場所にあります。

http://www.linuxdoc.org/HOWTO/Unix-and-Internet-Fundamentals-HOWTO/index.html

上記は、LDP/HOWTO/Unix-and-Internet-Fundamentals-HOWTO/index.html というファイルが www.linuxdoc.org というホストの World Wide Web についての公開ディレクトリ 上に置かれているということを意味します。

12.1. 名前と場所

ブラウザがまず初めにしなければならないことは、その文書が置かれた マシンとの間にネットワークコネクションを確立することです。それをするには、 第一に、そのホスト (host) である www.linuxdoc.org の あるネットワーク上の場所を探す必要があります(ここで「ホスト」とは、 「ホストマシン」、もしくは「ネットワークホスト」の略です。 www.linuxdoc.org という名前は、ごく一般的な ホスト名 (hostname) です)。通信の際の場所の指定は、実際には、 IP アドレス (IP address) と呼ばれる番号が使用されます(IP アドレスという用語の IP の部分 については、後ほど説明します)。

IP アドレスを知るには、ブラウザは ネームサーバ (name server) と呼ばれるプログラムに問い合わせをします。ネームサーバは自分のマシン上に あってもよいのですが、たいていの場合は専用のマシン上で動いているので、 それに問い合わせを送ることになっています。ISP と契約したとき、 そのセットアップ手順のなかで、ISP のネットワーク上にある ネームサーバの IP アドレスを、手持ちのインターネットソフトウェアに指示する という手順がきっと含まれていたはずです。

異なるマシン上で動くネームサーバは、お互いに通信をし、ホスト名解決 (すなわち、ホスト名を IP アドレスに変換する処理) に必要なすべての情報を交換しあい、つねに最新の状態に保っています。 ネームサーバは、www.linuxdoc.org というホスト名解決の過程で三度か 四度ネットワークごしに存在する他のサイトに問い合わせをしますが、 これは通常非常に高速に行われます(一秒以下です)。ネームサーバの 詳細については、次章で概観します。

ネームサーバはブラウザに対して、www.linuxdoc.org の IP アドレスが 152.19.254.81 であることを教えます。これを知ることによって、 読者のマシンは、www.linuxdoc.org との間で直接情報交換ができる ようになります。

12.2. ドメインネームシステム (domain name system)

プログラムとデータベースを連携させてホスト名を IP アドレスに変換する 仕組み全体は、DNS (Domain Name System) と呼ばれています。"DNS サーバ" と呼ぶ場合、これは単に「ネームサーバ」と呼ぶのと同じ意味で使われます。 ここでは、そのシステム全体の仕組みについて説明します。

インターネットのホスト名は、ドットで区切られたいくつかの部分から 構成されています。ドメイン (domain) とは、ホスト名の末尾部分が同一 であるマシンの集合のことです。ドメインは、他のドメインの内部にも 存在することができます。たとえば、www.linuxdoc.org というマシンは、 .org というドメインの中の .linuxdoc.org というサブドメインに 存在しています。

個々のドメインは、そのドメイン内の全てのマシンの IP アドレスを記憶して いる 権威あるネームサーバ (authoritative name server) によって規律されています。権威ある(もしくは「プライマリ」) ネームサーバは、故障に備えてバックアップされていることもあります。 セカンダリネームサーバ (secondary name server) (もしくは、セカンダリ DNS) という記述がある場合、 それはそうしたバックアップホストのことを言っているわけです。 こうしたセカンダリサーバ群は、通常、プライマリサーバから数時間ごとに 情報を受け取って更新しているので、プライマリサーバ上でホスト名 と IP との対応関係に変更が加えられた場合は、自動的にそれが セカンダリ側にも伝えられるようになっています。

次の事柄は非常に重要です。すなわち、あるドメインのネームサーバは、 他のドメイン(および、それら自身のサブドメイン)にあるすべてのマシンの位置を 知る必要はないということです。ネームサーバが知らなければならないのは、 他のネームサーバの位置だけです。先ほどの例では、.org ドメインの権威ある ネームサーバは、.linuxdoc.org の権威あるネームサーバの IP アドレスを 知っていますが、linuxdoc.org 内にあるそれ以外のマシンのアドレスについて は知りません。

DNS システム内のドメインは、巨木を逆さまにしたような階層構造を持つよう 配列されています。頂点にあるのは、ルートサーバです。すべてのネームサーバ は、ルートサーバの IP アドレスを知っています。ルートサーバの IP アドレス は、DNS ソフトウェアに組み込まれているからです。これらのルートサーバは、 .com や .org といったトップレベルドメインに関するネームサーバの IP アドレスを知っていますが、それらの内部にあるマシンのアドレスは知りません。 個々のトップレベルドメインのサーバは、その直下のドメインのネームサーバ の場所を知っていて、以下そうした関係が続きます。

DNS は、非常に注意深く設計されていて、各マシンがこの木構造に関する必要最小限の 情報をやり取りするだけですむように、そして、局所的なサブツリーの変更は、一箇所 だけの権威あるネームサーバの名前と IP アドレスとのマッピングを変更するだけで 実施できるようになっています。

www.linuxdoc.org の IP アドレスを問い合わせた場合、実際には次のような ことが起こります。第一に、その問い合わせを受けたネームサーバ(x)が、 ルートサーバに対して、.org に関するネームサーバがどこにあるのか 教えるよう問い合わせをします。それが分かると、次に(x は)、.org の サーバ に対して、.linuxdoc.org のネームサーバがどこにあるのか教えてくれる よう、問い合わせをします。その答えが返ってきたら、今度は(x は)、 .linuxdoc.org のネームサーバに対して、www.linuxdoc.org というホスト の IP アドレスを教えるよう問い合わせます。

たいていの場合、ネームサーバは実際に上記のような面倒な仕事をする必要は ありません。ネームサーバは大量の情報をキャッシュしているからです。 名前の解決ができたとき、ネームサーバは入手した IP アドレスとの 対応関係をしばらくの間メモリ内に保持します。初めてのウェブサイトを サーフする際、「ホストを探しています」というブラウザからのメッセージ が表示されるのは一番最初のページを開いた場合だけであるのは、上記 のような仕組みになっているからです。最終的には、名前とアドレスとの マッピングは時間切れとなり、DNS はその名前を再度問い合わせなければ ならなくなります。この機能が重要なのは、あるホスト名とアドレスとの 結びつきが変更されたときに、無効になった情報がいつまでも邪魔を するようなことがないということです。あるサイトに関するキャッシュされ た IP アドレスは、そのホストに到達できなくなった場合にも、破棄されます。

12.3. パケットとルータ

ブラウザが実行しようとしているのは、www.linuxdoc.org 上のウェブサーバ に対して次のようなコマンドを送信することです。

GET /LDP/HOWTO/Fundamentals.html HTTP/1.0

以下で、その際に何が起こるのかについて説明します。上記コマンドは、 パケット(packet) というビットの塊に分割され、電報の場合のように、 次のような三つの重要事項を付け加えた上でラップされます。その 重要事項とは、送信元アドレス (source address) (読者のマシンの IP アドレス)、あて先アドレス (destination address) (これは、152.19.254.81)、およびそれがウェブに関するリクエストであることを示す サービス番号 (service number) もしくは ポート番号 (port number) (この場合では、80 番)です。

次に、読者のマシンはそのパケットを回線(ISP や ローカルネットワークとの コネクション) 上に送信すると、そのパケットは ルータ(router) と呼ばれる特別なマシンに届きます。ルータは、インターネットの 地図をメモリ内に記憶しています。これは必ずしも完全な地図ではありませんが、 そのネットワークの周辺地域については完全に記述しているので、 インターネット上の他の周辺ルータに至るべき方法は理解しています。

送信したパケットは、いくつかのルータを通過しながら、あて先へと到達します。 ルータは非常に上手く出来ています。ルータは、パケットを受信した旨の 送達確認を他のルータから受け取るまでの経過時間を監視しています。また、 その経過時間に関する情報を使って、空いているリンク上にパケットを流す ようトラフィックを調整しています。また、ルータはその情報を使用して、 他のルータやケーブルが原因でネットワークに支障が生じた際に、 別のルータを探すことで可能な限り埋め合わせをしようとします。

インターネットは核戦争に耐えられるように設計されたという噂が都会で暮らす 人々の間でささやかれていま。これは真実ではないのですが、しかし、インター ネットの設計というのは、この不確かなことが多い世界において、頼りにならない ハードウェアからでも信頼に足るパフォーマンスを引き出してくれるだけの 極めて優れた設計思想のもとに構築されています。 このことは、まさに次の事実によっています。 すなわち、(電話回線網のように)少数の巨大で脆弱な交換機に処理を集中 させるのではなく、無数のルータにそうした処理の役割を分散したという ことです。つまり、障害はあくまで局地的なものに留まるようになっていて、 ネットワークはそうした障害を避けてルーティングすることができるのです。

パケットが一旦あて先のマシンまで到達したなら、そのマシンはサービス番号を 使って、そのパケットをウェブサーバに渡します。ウェブサーバは、そのコマンド パケットの送信元 IP アドレスを見ることで、どこに返答を返せばよいのかを 知ることができます。上記の例で、そのウェブサーバがこの文書を送信する際は、 文書はいくつかのパケットへと分割されます。パケットのサイズは、ネットワーク 上の伝送方法やサービスの種類によって異なります。

12.4. TCP と IP

こうした分割されたパケットを使う通信方法の処理のしかたを理解するには、 インターネットは実際にはふたつのプロトコルを使用していて、一方が他方の 上に積み重ねられているという通信の仕組みを知る必要があります。

下位層である IP (Internet Protocol) は、送信元アドレスからあて先アドレスに個別のパケットを到達させるための 方法は知っています(これらが IP アドレスと呼ばれるのはそのためです)。 しかしながら、IP は信頼性に欠けています。パケットが途中で行方不明に なったり消失したりしても、送信元とあて先のマシンは決してそれに 気づかないでしょう。ネットワーク用語では、IP は コネクションレス (connection less) なプロトコルです。 送信者はパケットを 受信者に対して送るだけであり、受信側からの確認応答は期待できません。

しかし、IP は、高速かつ安価です。高速かつ安価であれば、信頼性がなくとも 問題ないという場合もあります。Doom や Quake をネットワーク上でプレイする ときは、弾丸のひとつひとつも IP パケットで送られています。弾丸の2,3 発 消失してしまったとしても、特に問題はないはずです。

上位層の TCP (Transmission Control Protocol) は、信頼性のためのプロトコルです。 二台のマシンが相互に交渉して TCP コネクションを張り (これは、IP を使って 行われます)、受信側が受信したパケットについての到達確認を送信側に 送るようになっています。送信側が一定時間内にあるパケットの送達確認を 受け取らない場合は、そのパケットを再送します。さらに、送信側は、個々の TCP パケットに通し番号を振っているので、受信側ではそれを使って、パケットの 到着順序が狂った場合でもそうしたパケットを並べ直すことができるように なっています。(これは、ネットワーク上の経路が、コネクションの最中に 変動した場合には、よく起こる現象です。)

TCP/IP パケットにはチェックサム (checksum) という情報も含まれていて、 経路上に障害が生じてデータが壊れてしまったりしていないかを検出できる ようになっています。 (チェックサムは、まずチェックサム自体を除いたパケットの残りの情報から算出 されます。そうしておくと、パケットの残りの部分かチェックサム自体が(経路上で) 壊れてしまっていた場合は、(到達先で)そのパケットから再度チェックサムを算出 して、もとのチェックサムと比較することで、エラーの有無を高い確率で検出する ことができるわけです)。それゆえ、 TCP/IP とネームサーバというのは、使う側の視点からみると、ホスト名とサービス 番号で区別された二台のホスト間でバイトストリームを伝達しあう方法としては、 信頼に足るものと言ってもいいでしょう。また、ネットワークプロトコルを書く人から すると、このネットワーク階層以下で起こっているパケット分割やパケットの再構成、 エラーチェック、チェックサムの計算、再送といった事柄をほとんど考慮しなくても よくなります。

12.5. HTTP : アプリケーションプロトコルの一例

ここで、先ほどの例題に戻りましょう。ウェブブラウザとサーバとは、 アプリケーションプロトコル (application protocol) を使って 会話をしています。これは、TCP/IP 階層の上位で実行されるプロトコルであり、 TCP/IP をバイト列のやりとりの手段として利用しているものです。上記の例での プロトコルは、 HTTP (Hyper-Text Transfer Protocol) と呼ばれるもので、そこで使われるコマンドの一例が GET で始まる文字列である ことは既にご覧になった通りです。

上記の GET コマンドが www.linuxdoc.org のウェブサーバにサービス番号 80 番で 到達すると、ウェブサーバはこれを、80 番ポートで待機している サーバデーモン (server daemon) へと渡します。大部分のインターネットサービスは、 サーバデーモンとして実装されていて、これらは、送られてくるはずのコマンドを 監視し、実行するために、特定のポートでただひたすら待ち受け状態を続けています。

インターネットの設計に関する一大原則があるとするなら、それはすべての部分が できる限りシンプルで人間が見て分かるような形にするということです。HTTP と その親戚 (Simple Mail Transfer Protocol, SMTP という、ホスト間で電子メールをやりとりするために使われるプロトコルなど) は、キャリッジ・リターン(復帰)とライン・フィード(改行)で終了する、人間が 読んでも意味の分かるシンプルなテキストコマンドを使うという傾向があります。

こうした方法は、かなり非効率です。環境によっては、がちがちに固められた バイナリプロトコルを使ってスピードアップを図ることもできるはずです。 しかし、経験が示すところによると、人間にとって説明や理解のしやすいコマンド を使うことのメリットは、トリッキーで分かりにくいものをわざわざ作ること で得られる僅かな効率の上昇をはるかに上回るものなのです。

したがって、サーバデーモンが TCP/IP 経由で送り返す返答もテキスト形式 です。返答の最初の部分は、次のようなものとなります(ヘッダの一部は省略 しています)。

HTTP/1.1 200 OK
Date: Sat, 10 Oct 1998 18:43:35 GMT
Server: Apache/1.2.6 Red Hat
Last-Modified: Thu, 27 Aug 1998 17:55:15 GMT
Content-Length: 2982
Content-Type: text/html

上記のようなヘッダの後に空行がひとつ入り、その後にウェブページのテキスト が続きます(それらの送信が終わった時点で、コネクションが切断されます)。 ブラウザは、それらを表示するだけです。ヘッダは、ブラウザに対してその 表示方法を指示するものです (特に、Content-Type というヘッダでは、 返信データが実際に HTML であるということをブラウザに伝えています)。