TCP/IP

提供:UnixClassWiki
2014年1月9日 (木) 16:35時点におけるHironobu (トーク | 投稿記録)による版 (→‎Internet Protocol Suite)
ナビゲーションに移動 検索に移動

まずはじめに

本章でのTCP/IPの取り上げるスタンスについて説明します。 本章では、UNIXとTCP/IPの関係性を取り上げ、GNU/Linuxの中でどう扱われているかの議論を試みます。TCP/IP自体の説明、また、インターネット自体の説明は本章の趣旨ではないので本章では扱いません。またTCP/IPに関する基本知識(例えば 3 way handshakeなど)は既に学習しているものとして話を進めます。

GNU/LinuxはTCP/IPだけではなく、Appletalk、DECNETなど多数のプロトコルをサポートしていますが、本章では主要な論点であるTCP/IPのみ取り上げます。


UNIXとTCP/IP

TCP/IPとは1970年代初頭にDRAPAの研究成果として既に出来上がったネットワーク通信用プロトコルで、元々はUNIXにはなかった機能です。DARPAからの研究資金を得て、4.1bBSD(1982年8月)に対してBBN Technologiesで実装されていたTCP/IPコードをベースとして組入れるという作業が始まり4.2BSDで正式にTCP/IPを含んでリリース(1983年8月)となりました。ここでは「BBNの実装ベースで」とあっさり書いていますが、実際にはもうちょっと複雑な話になっています。 [1]


TCP/IPというとインターネット用プロトコルというイメージがありますが、当時のBSDの実装はイーサーネット接続されたLANやキャンパスネットワークで高速に情報を伝達するのに適したものになっています。一方でオリジナルのBBNの実装は広域なネットワークであるインターネットで使うことを前提としているもので、そのため80年代当時の低速なネットワーク向けに作られています。このようにターゲットとなるネットワークの前提が違うため、BBNの実装をそのままBSDに組み込んだような単純な話ではありません。


この期間でのエポックとしては1983年1月1日にARPANETの公式プロトコルはTCP/IPに切り替わっています。 [2] 当時TCP/IPの実装を持っていたオペレーティング・システムはそんなに多くはなく、BSDの他の名の知れたシステムはDEC社のTOPS-20 system [3] ぐらいです。当時、DARPAの資金で開発した、他に参考となる実装が多くなく、ソースコードが公開されているなどのいくつかの要因により実質BSDがコンピュータにおけるTCP/IPのリファレンス実装となっていました。


リファレンス実装であったというおもしろい傍証は1997-8年頃に問題となった Ping of Death のケースが良いかも知れません。これは規定外サイズのICMPパケットを脆弱性を持つシステムに送るとオペレーティングシステムごとハングアップしてしまうというものです。そもそもの原因はBSDのコードがパケットの分割を考えていなかった実装だったからです。分割されるケースを設計時点で考慮に入れなかったある意味、単純なバグで、そんなに深い意味はありません。もし、IPパケットとICMPパケットの仕様[4]だけで作っていたら設計時に考慮し、この脆弱性はたぶん現れないでしょう。しかし実際にはGNU/LinuxだけではなくMacintoshやWindowsにも同じ脆弱性が現れました。このことから仕様ドキュメントから設計をしたわけではなく、商用のオペレーティングシステムもオープンなコードであるBSDのTCP/IPコードをリファレンスとしていたのではないかといわれています。


Xerox PARCで開発されたイーサーネット、TCP/IP、そしてBSDの組み合わせによって構築されたLANがARPANET経由でエンド・ツー・エンドで接続し広域ネットワークを構築してしまうという当時は技術的にかなり画期的な仕組みであり、これこそ今日私たちがインターネットと呼んでいるものそのものです。ですからUNIXの存在はインターネットの大きな礎としての存在であった決して過言ではありません。


Internet Protocol Suite

BSD由来のTCP/IPの特徴は、クライアントだけでなく、サーバだけでもなく、ルーターだけでもない、TCP/IPの機能一式をもったInternet Protocol Suiteの実装であるということです。つまり、UNIXはサーバとしても使え、クライアントとしても使え、そしてまたルーターとしても使えるということです。もちろんその上で動作するアプリケーションは、TCP/IPの機能をフルに使うことができます。


GNU/Linuxベースのサーバーやクライアントはインターネットにおける日常の風景的な部分ではありますが、形をかえて組み込み系でも市販のルータの中身がGNU/Linuxベースであったりするものよく見かけます。もちろんGNU/Linuxは、Internet Protocol Suiteで一式揃えているので、サーバとクライアントとルータやブリッジを同時に兼ねることも当然可能です。


典型的なのがGNU/Linux上で動作するバーチャルマシン・モニタXenのネットワーク構成です。Xenのドメイン0 (他の仮想マシンを動かすためのベースとなる環境)では、内部的にブリッジの機能を作り、ドメインU(個々の仮想マシン)からはそこに仮想的に接続する形を取りネットワークを形成します。このために特別なプロトコルスタックを用意するわけではありません。既にGNU/Linuxには必要なネットワークの能力が用意されているのです。


一般にTCP/IPのようなプロトコルが重ねられている構造のことをプロトコルスタック ( Protocol Stack ) と呼びます。 そして各々のプロトコルのメカニズムあるいは実装のことを、その層のスタック、たとえばTCPであればTCPスタック、IPであればIPスタックと呼びます。意味は、TCPの層だけではなく、その下層も含めたメカニズムあるいは実装をさしています。

GNU/Linux での TCP/IP

まずEthernetを前提に基本的な部分を説明したいと思います。 GNU/LinuxではEthernetのデバイスは基本的にeth0から順番に割り当てられます。 むかしはNIC (Network Interface Card)に対応するデバイスファイル /dev/eth0 というのがあったのですが、今ではそれが存在せず内部的にeth0、eth1という仮想的なネットワークデバイスになっています。 慣用的にloはローカルホスト、eth0はEternet、wlan0は無線LANの仮想ネットワークデバイスとして命名されていますが、これは任意な名前であり、たとえば、新たにPPP (シリアル経由でpoint-to-point接続するプロトコル)で接続を作る時はppp0や、 easytether (AndroidをUSBで接続しテザリングをするツールを利用)など仮想ネットワークデバイスは自由度の高い名前をつけることができます。同種類のデバイスが増えるたびに番数が増えます(eth0, eth1, ... )。

  • lo ローカルホストのための仮想ネットワークデバイス
  • eth0 Ethernetのための仮想ネットワークデバイス
  • wlan0 無線LANのための仮想ネットワークデバイス

その仮想ネットワークデバイスにIPアドレスを設定しTCP/IPで利用する形にします。

ifconfig

仮想ネットワークデバイスにTCP/IPに必要なパラメータを設定するのはifconfigコマンドです。これはバークレー大学でBSDに組み込んだTCP/IPの実装が作られた時に、IPアドレスやネットマスクなどのパラメータを設定する、あるいは参照するのに作られたコマンドですが、そのまま今もスタイルを変えず使われています。グラフィカルインタフェース〜といっても項目をリストアップする程度のものですが〜を使って設定するツールは存在しますが、システムがブートする段階でIPの制御を行うのがifconfigです。

低いレベルでコントロールする方法を理解したい、あるいはツールを作成したいと思った時は netdevice のオンラインマニュアルにヒントがあります。

/sbin/ifconfigをオプションなしに実行すると、現在のeth0やloが表示されます。

 $ ifconfig
 eth0      Link encap:Ethernet  HWaddr 00:15:c5:41:95:a0  
         inet addr:192.168.100.18  Bcast:192.168.100.255  Mask:255.255.255.0
         inet6 addr: fe80::215:c5ff:fe41:95a0/64 Scope:Link
         UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
         RX packets:350974 errors:0 dropped:0 overruns:0 frame:0
         TX packets:291913 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:1000 
         RX bytes:329347998 (329.3 MB)  TX bytes:36362966 (36.3 MB)
         Interrupt:18 
 lo        Link encap:Local Loopback  
         inet addr:127.0.0.1  Mask:255.0.0.0
         inet6 addr: ::1/128 Scope:Host
         UP LOOPBACK RUNNING  MTU:16436  Metric:1
         RX packets:6 errors:0 dropped:0 overruns:0 frame:0
         TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:0 
         RX bytes:340 (340.0 B)  TX bytes:340 (340.0 B)

仮想ネットワークデバイスeth0はEthernetに接続され、IPアドレス192.168.100.18が設定されています。

loはローカルホストです。これは127.0.0.1が割り当てられます。127.0.0.1は特殊なアドレスでこれは自分自身のマシンを指します。 ホスト名はlocalhostとなっています。


ブート時にはIPアドレスの設定などifconfigコマンドを使っています。デスクトップやノートパソコン、特にモバイルのように色々なネットワーク上で動作させるようなコンピュータはDHCP [5] を使ってそのネットワーク上で自動割り当てされるのが一般的ですが、ここではまず固定IPの話から進めましょう。

# ifconfig eth0 up

これはeth0のインタフェースを利用可能にします。

# ifconfig eth0 192.168.201.3/24

こう実行することによってeth0にはIPアドレス192.168.1.3、ブロードキャスト:192.168.1.255、マスク:255.255.255.0が設定されます。

ここではeth0に設定していますが物理的に1つのNICに複数のIPアドレスを付与できます。 むかしならNIC(network interface card)に1つのIPアドレスしか付加できませんでしたが、 複数のIPアドレスが設定する場合、eth0:1、eth0:2といった形でMACアドレスが同じである eth0のインタフェースが作られます。

 $ sudo ifconfig eth0:1 192.168.100.99/24
 $ ifconfig eth0:1
ifconfig eth0:1
eth0:1    Link encap:イーサネット  ハードウェアアドレス 14:da:e9:71:cd:35  
         inetアドレス:192.168.100.99  ブロードキャスト:192.168.100.255  マスク:255.255.255.0
         UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
         割り込み:47 ベースアドレス:0xc000

脚注

  1. 詳しくは Open Sources: Voices from the Open Source Revolution に納められているMarshall Kirk McKusickが書いたTwenty Years of Berkeley Unix From AT&T-Owned to Freely Redistributable を読むことをお勧めします。
  2. 核戦争にも耐えうる軍事ネットワークを作るためにインターネットを作ったという俗説がまことしやかに流れていますが、そのような事実はありません。Internet Society のサイトにある Brief History of the Internet に目を通して正しいインターネットの歴史の全体像を知っておきましょう。
  3. http://panda.com/tops-20/ by Mark Crispin
  4. RFC791
  5. ISC DHCP https://www.isc.org/downloads/dhcp/ ここにDHCPのリファレンス実装があります。

目次