魔術師見習いのノート

プロフィール

魔術師見習い
Author魔術師見習い-_-.
Twitter魔術師見習い

コンピュータ関係のメモを主に書きます.

MENU

コンピュータ・ネットワーク(1)

投稿日:
タグ:

目次

本稿はコンピュータネットワークの基礎についてメモである。現代でネットワークといった場合、暗黙的にコンピュータネットワークを指すことが多い。ネットワークとはいくつかのノード(例えばマシン)間が接続されてできる通信網のことである。

あるマシン間で行う通信は次のような階層モデルで表される。

アプリケーション層
トランスポート層
ネットワーク層
データリンク層
物理層
このモデルを5階層TCP/IPモデルという。このモデルがネットワークの階層を表す上で最適なモデルであるかはいろいろ議論はあるだろうが、本稿では基本的にこのモデルを基に説明する。

通信形態

通信には次の4つの形態がある。

ユニキャスト
1対1の通信のこと。
マルチキャスト
1対多の通信のこと。
エニーキャスト
ある集合に属する1つのものとの通信のこと。
ブロードキャスト
同じネットワーク上の全てのものとの通信のこと(1対不特定多数)。
本稿で扱う通信もまたこれらのいずれかに属する。

ネットワーク階層モデル

ネットワークを表すための階層モデルには、次のようなモデルがある。

アプリケーション層アプリケーション層アプリケーション層
プレゼンテーション層
セッション層
トランスポート層トランスポート層トランスポート層
ネットワーク層ネットワーク層ネットワーク層
物理層データリンク層データリンク層
物理層物理層
4階層TCP/IPモデル5階層TCP/IPモデルOSI参照モデル
どの階層が最適なモデルであるかは、定かではない。例えば、OSI参照モデルのアプリケーション層とプレゼンテーション層、セッション層は、5階層TCP/IPモデルのアプリケーション層に相当するが、それを分けるぐらいならば物理層やデータリンク層を細分化すべきという主張もある。本稿では、基本的に5階層TCP/IPモデルを使用し、階層についてこれ以上言及しない。

5階層TCP/IPモデル

5階層TCP/IPモデルの最上位のアプリケーション層は、それぞれユーザに対して、メールやWEBページの配信などさまざまな機能を提供する。そして、それから下位に行くほどユーザが認知しないベーシックな通信を扱う。

最上位のアプリケーション層を除く各層は、基本的にそれぞれ次の3つの要素からなる。

サービス
上のレイヤのエンティティ(通信するもの)に提供する機能。
インタフェース
サービスを受けるためのアクセス方法。
プロトコル
通信規約のこと。送信側と受信側が同じプロトコルを使用することで通信が成り立つ。例えばアプリケーション層でWEBページの配信を行う場合、送信者と受信者が共にHTTPに従う。

各層の要素についての説明は次の通りである。

レイヤ名サービスインタフェース代表的なプロトコルや技術
データ単位アドレス
アプリケーション層 HTTP, SMTP, POP3
トランスポート層 プロセスがサービスを行ったりそれを受けたりするための通信を可能にする。そしてそのためにフロー制御や輻輳制御、誤り訂正などを行う。 ソケット ポート番号 TCP, UDP
ネットワーク層 物理的なネットワークを跨いで全てのノード間の通信を可能にする。 パケット 論理アドレス IP, ICMP
データリンク層
  • 物理的に接続されたいくつかのノードの中(物理的なネットワーク)で、ユニキャストを可能にする。
  • 通信品質を向上のために、伝送エラーの検出やフロー制御などを行う。
フレーム 物理アドレス ARP, PPP, IEEE802.11
物理層 有線や無線、衛生などを使って物理的に通信を可能にする。 ビット なし(ブロードキャスト) 光ケーブル, ツイストペアケーブル, 10Base-T
基本的にアプリケーション層を除く4つのレイヤは、更に2つずつに分けられ、それぞれ異なるネットワークを構築する。物理層とデータリンク層は物理的なネットワーク、ネットワーク層とトランスポート層は論理的なネットワークを形成する。そして、次の表のようにそれぞれの組みの低い方のレイヤはノードの接続を、高い方のレイヤはその制御を司っている。
物理ネットワーク(MAC)仮想ネットワーク(IP)
接続物理層ネットワーク層
制御データリンク層トランスポート層

標準化

ネットワークを構成する技術や仕様は、いくつかの団体によって標準化が勧められている。

IETF(Internet Engineering Task Force)
インターネット技術の国際標準化をすすめる団体。インターネットで利用される多くのプロトコルはRFC(Request For Comments)というもので技術仕様が公開されている。
例)
RFC 959アプリケーション層のFTPの仕様
RFC 2616アプリケーション層のHTTP/1.1の仕様
IEEE(the Institute of Electrical and Electionics Engineers, inc)
アメリカに本部を持つ電気・電子技術学会。読み方はアイトリプルイー。通信工学・電子工学・情報工学などの分野を対象とし、標準化の活動を行なっている。
例)
IEEE 754浮動小数点の表記や演算に関する標準規格。
IEEE 802.3有線LANに関する標準規格。
IEEE 802.11無線LANに関する標準規格
ICANN(Internet Corporation for Assigned Names and Numbers)
IANA(Internet Assigned Number Authority)
インターネット上で利用されるアドレス資源の標準化や割り当てを行う団体。ICANNはIANAの後継にあたる。アドレス資源には、ポート番号やIPアドレス、ドメイン名などがある。

コンピュータ・ネットワーク(2) -物理層-

投稿日:
タグ:

目次

物理層は5階層TCP/IPモデルの下から1番下の層である.

アプリケーション層
トランスポート層
ネットワーク層
データリンク層
物理層

--編集中--

  • 線路
  • 無線
  • 衛生

双方向通信

全二重(full duplex)
半二重(half duplex)

ネットワーク・トポロジー

ネットワークとはいくつかのノード間が接続されてできる通信網のことである.ネットワークにはさまざまな幾何学的な形(トポロジー)がある.以下にいくつかの例を紹介する.以下の図では,○がノード,線が接続,□が接続を繋ぐ集線装置(例:ハブ)を表す.

デイジーチェイン型
ノードを数珠繋ぎで繋いだトポロジー.最もコストが低いが,冗長性も低く耐障害性が最も低い.いずれか1つのノードか経路が機能しなくなると,通信できなくなる可能性がある.
バス型
バスと呼ばれる伝送路を通じていくつものノードが接続されたトポロジー.他のノードによる通信の影響はないが,いずれか1つの経路が機能しなくなると,通信できなくなる可能性がある.ただし,バスのトポロジーによっては耐障害性も向上する.ただし,その分コストも上がる.
リング型
あるノードから別のノードへの経路が必ず2つあるトポロジー.いずれか1つの経路やそれに関わるノードが機能しなくても,通信可能である.
スター型
いずれかのノードや集線装置までの経路で問題が発生しても,通信可能である.ただし集線装置が停止した場合,全ての通信が不能になる.
ツリー型
巡回路(ループ)のないトポロジーのこと.デイジーチェイン型もまたツリー型の一種である.
フルコネクト型
耐障害性が最も高く,全てのノードに対して最短な経路があるトポロジー.あるノードから別のノードへの経路がいくつもあるので,いくつかのノードや経路が使えなくなっても通信が可能である.ただし費用も最も高い.

ネットワーク・トポロジーには次の2種類のトポロジーがある.

  • 物理的トポロジー
  • 論理的トポロジー
物理的トポロジーと論理的トポロジーのトポロジーが同じであるとは限らない.例えば,IEEE802.3の10BASE-Tの物理的トポロジーはスター型だが,論理的トポロジーはバス型になっている.

コンピュータ・ネットワーク(3) -データリンク層-

投稿日:
タグ:

目次

データリンク層は5階層TCP/IPモデルの下から2番目の層である.

アプリケーション層
トランスポート層
ネットワーク層
データリンク層
物理層

以下にデータリンク層が持つ3つの要素を表で示す.

サービス
  • 物理的に接続されたいくつかのノードの中(物理的なネットワーク)で、あるノードから指定したノードへの通信を可能にする。
  • 通信品質を向上のためにさまざまな処理を行う
インタフェース転送単位フレーム
アドレス物理(ハードウェア)アドレス(MACアドレス)
代表的なプロトコル
  • ARP
  • PPP
  • MAC(IEEE802やイーサネットなど)
多くのユーザはこのレイヤを意識することはないだろうが、スイッチングハブと呼ばれるハードウェアは,この物理層からデータリンク層までを扱うものである.

副層

データリンク層は更にいくつかの副層に分けて考える場合がある。例えば、物理的な制御と論理的な制御に分けることができる。

LLCLogical Link Control論理リンク制御副層 高品質な通信を可能にする。
  • 伝送エラーの検出
  • フロー制御
  • 送信の際の多重化と受信の際の非多重化
MACMedia Access Controlメディアアクセス制御副層 物理的に接続されたいくつかのノードの中(物理的なネットワーク)で、ユニキャストを可能にする。
  • MACアドレス
  • 競合制御(衝突対策)
物理層が1対1接続で、かつ全二重通信の場合、メディアアクセス制御副層は必要ない。

通信

物理層では、いくつかのノードを接続し、ネットワークを構築する。物理層の通信形態は、接続するノード数に関係なくブロードキャストである。データリンク層では、そのネットワーク上のあるノードに、宛先物理(ハードウェア)アドレスが自分のものであるフレームが届いた場合、それを受け取ることで、ユニキャストを実現する。

ARP

TCP/IPの通信では,各マシンはIPアドレスという論理的なアドレスを使って通信を行うが,最終的にはMACアドレスによってマシンを特定する.IPアドレスからMACアドレスを取得するには,ARP(Address Resolution Protocol)を利用する.ARPでは,物理的なネットワークでブロードキャストによって調べたいIPアドレスを伝える.受信したノードは,そのIPアドレスが自身のものである時,MACアドレスをその送信元ノードに返す.

フレーム

フレームとはデータリンク層で扱う転送単位で,ビット群のことである.ビット群は,さらにいくつかのフィールドに分類され,フィールドはそれぞれ必要な情報を保持する.フレームの構成にはいくつかの規定があり,以下にいくつか紹介する.なお,ここのフィールドの1セルは,ヘッダとデータを除いて1バイトを表しているで使用される.

DIX
プリアンブル MACヘッダ データ FCS
46〜1500bytes
世界中のLAN(Local Area Network)で最も使用されるイーサネットという規格では,DIXが主流に使用される.DIX規格はDecとIntel,Xeroxが共同開発した規格である.DIX規格の場合,MACヘッダのタイプ・長さのフィールドはタイプを表す.
IEEE802.3
プリアンブル SFD MACヘッダ データ FCS
46〜1500bytes
以下に各フィールドの用途を示す.
プリアンブル
SFD(Start Frame Delimiter)
同期を取り,フレームの開始を合図するためのフィールド.DIXでは8バイト(64ビット)で101010…と繰り返し,最後の2ビットを11,IEEE802.3では7バイトで101010…と繰り返し,最後の1バイト(8ビット)が10101011となる.
FCS(Frame Check Sequence)
エラー検出のためのフィールド.このフィールドにより,MACヘッダとデータが正しいかを判定する.エラー検出にはパリティや加算による方法など様々ある.イーサネットの場合,エラー検出の方法には巡回冗長検査(CRC:Cyclic Redundancy Check)方式を使用する.
MACヘッダ
宛先MACアドレス 送信元MACアドレス タイプ・長さ
宛先MACアドレス
送信元MACアドレス
MAC(Media Access Control)アドレスとは必ず一意に定まる48ビットの値のこと.物理ネットワークではこの値によってノードを識別する.UNIX系のifconfigやWindowsのipconfigでは,1バイト(8ビット)毎に区切って,"00:03:47:11:22:33"というように16進数で表記される.各ハードウェアベンダーは,利用可能なMACアドレスの番号の範囲を持つ.
タイプ
長さ
このフィールドが46から1500であればIEEE802.3規格の長さを表しており,1501以上であればDIX規格のタイプを表している.

衝突(コリジョン)

通信で使用される経路が送信でも受信でも使用される場合,いくつかのノードが同時に通信しようとして送信するデータが破損することがある.これを衝突(コリジョン)と呼ぶ.そして、いくつかのノードが同時に送信して衝突が発生する範囲のことをコリジョンドメインという。データリンク層では,これに備えるためのいくつかのプロトコルがある.

CSMA/CD(Carrier Sense Multiple Access/Collision Detection)プロトコル
CSMA/CD方式で衝突が発生した場合,ノードはランダムな間を置いて再度通信を行う.IE802.3ではCSMA/CDが採用されている.
CSMA/CA(Carrier Sense Multiple Access/Collision Avoidance)プロトコル
通信を開始する前に受信を試みることで、他に通信を行なっているノードがあるかを調べる。いずれかのノードが通信している場合、通信が終了してからランダムな間を置いて通信を行う。無線LAN規格のIEEE802.11aやIEEE802.11b、IEEE802.11gで利用されている。
FDDI(Fiber Distributed Data Interface)プロトコル
トークンリングプロトコルを拡張したプロトコル.トークンリングプロトコルとは衝突を回避するためのプロトコルで,ノードはトークンと呼ばれるものを保有する時のみ通信が許可される.トークンは1つの物理ネットワーク内のノードに1つだけ存在し,それをローテーションで渡していく.トークンリングプロトコルでは,衝突の発生を完全に防ぐことができるが,経路で問題が発生した場合,トークンが移動しなくなって全てのノードの通信ができなくなるという問題がある.FDDIプロトコルでは,トークンの受け渡しの経路を二重化することでこの問題を防ぐことができる.

リピータハブを用いたような物理層での接続の場合、それらの範囲はコリジョンドメインである。しかし、データリンク層で接続するスイッチングハブや、ネットワーク層で接続するルータを使用した場合、コリジョンドメインを分割できる。リピータハブはただ接続範囲を拡大するためのものだが、スイッチングハブはどこのポートに何のノード(MACアドレス)が接続されているか記憶することで,コリジョンドメインを分割する。これにより、衝突の頻度を減らすことができる。

データリンク層で接続された範囲のことをブロードキャストドメインという。ブロードキャストドメインは、フレームのブロードキャストが届く範囲のことである。本稿で述べる物理ネットワークとはこの範囲のことを指す。


関連コマンド

arp
システムが使用するARPのキャッシュを制御する.例えば次のようにして使用することで,キャッシュされたARPの情報を見ることができる.
user% arp 192.168.1.1
もし調べたいIPアドレスがあれば,pingのようなコマンドでそのアドレスへアクセスを行なってから,arpコマンドを使えば良い.以下にいくつかのオプションを紹介する.
-s
エントリの追加(IPアドレスとMACアドレスを対応付ける). IPアドレス"172.168.1.1"にMACアドレス"01:23:45:67:89:ab"を対応付けるには以下のように行う。
user% arp -s 172.168.1.1 01:23:45:67:89:ab -i wlan0
-d
エントリの削除
user% arp -d 172.168.1.1 -i wlan0
-a
ARPテーブルを出力.
-n
ホストやポート,ユーザーの名前を解決せずに生のまま出力.
-i
インタフェースを指定.
-v
詳細な情報を出力.
tcpdump
パケットスキャニングツール.-eオプションを指定することで,フレームのヘッダ情報を表示できる.
user% tcpdump -e -i eth0


補足

CRC(Cyclic Redundancy Check)

イーサネットの通信やZIP,PNGなどで利用されるエラー検査のアルゴリズムである.CRC方式では以下の方法で計算された値を比較することで,エラーを演出する.

  1. 入力と除数のビット列の左端を合わせる.
  2. 除数の左端のビットに対応する入力のビットを見て,1ならば,XOR演算を行う(除数の足りない桁は全て0とする).
  3. 解を入力とする.
  4. 除数の桁を右に1つずらす.
  5. 除数の右端の桁が入力の右端の桁より右にいかない間,1から4を繰り返す.
以下に例を示す.
10010010  入力
1011      除数
00100010
  1011
00001110
    1011
    0101  最終解

コンピュータ・ネットワーク(4) -ネットワーク層-

投稿日:
編集日:
タグ:

目次

ネットワーク層は5階層TCP/IPモデルの下から3番目の層である。

アプリケーション層
トランスポート層
ネットワーク層
データリンク層
物理層
ネットワーク層は、データリンク層で物理的に接続されたネットワークを跨いだノード間の通信を可能にする。

サービス
    物理的なネットワークを跨いで全てのノード間の通信を可能にする。
  • 誤り検出
インタフェースデータ単位パケット
アドレス論理アドレス
代表的なプロトコル
  • IPv4
  • IPv6
  • ICMP

IPパケット

IPでは、IPパケットというデータ単位で通信を行う。IPパケットは次のようなデータ構造である。ここで、各セルは基本的に1ビットを表す。

012345678910111213141516171819202122232425262728293031
Version IHL TOS Total Length
identification VCF Fragment Offset
TTL Protocol Header Checksum
Source Address
Destination Address
Options
Data
Version
IPのバージョン。IPv4ならば4。
IHL: Internet Header Length
IPヘッダの長さ。
Type Of Service
パケットが転送される際に重視するサービスを指定するフィールド。
01234567
優先度 遅延度 転送量 信頼性 予備
予備のフィールドは、RFC3168ではECN(輻輳通知機能)のために定義される。
67
ECTCE
各ビットはそれぞれ次のような名前である。
  • ECT(Explicit Capable Transport)
  • CE(Congestion Experience)
そしてそれらの値は次のような意味を持つ。
00ECNを未サポート。
01送信ホストはECNをサポート。
10
11輻輳はルータにより経験。
Total Length
パケットの全長。1バイトが8ビットとした時のバイト数。
identification
断片化した時にその断片がどのパケットのものかを表す。
VCF: Various Control Flags
断片化の制御に用いるフィールド。
012
予備禁止継続
Fragment Offset
パケットを断片化した時に、パケット全体のどこの位置にあたるのかを示すフィールド。
TTL: Time To Live
ルーティング可能な回数。パケットを転送する度に1減らし、これが0になったらそのパケットを破棄する。
Protocol
トランスポート層やネットワーク層の他のプロトコルなどでIPパケットを使用する場合にその種類を示すフィールド。
プロトコル番号プロトコル名
1ICMP
2IGMP
4IP
6TCP
7CBT
8EGP
9IGP
17UDP
41IPv6
43IPv6-Route
44IPv6-Flag
45IDRP
46RSVP
47GRE
50ESP
51AH
55MOBILE
58IPv6-ICMP
59IPV6-NoNxt
60IPv6-Opts
88EIGRP
89OSPF
94IPIP
103PIM
112VRRP
113PGM
115L2TP
Header Checksum
IPヘッダの誤り検査のためのフィールド。ルーティングの度にTTLの値が変化するため、この値も変化する。なおIPではデータ内容のチェックは行われない。
Source Address
送信元IPアドレス。
Destination Address
宛先IPアドレス。
Options
セキュリティやルーティングなどの拡張情報。可変長のフィールドで、ないこと、すなわち5であることが多い。


IPアドレス

IPアドレスとは32ビットの論理アドレスのことである。データリンク層で使用されるMACアドレスが各ネットワークデバイスにそれぞれ割り当てられているのに対し、IPアドレスはソフトウェアによってMACアドレスに対応づけられる(厳密には1対1関係とはいえないがそれについては後述する)。それゆえノードに割り当てられるIPアドレスは、常に同じであるとは限らない。

MACアドレスが隣接するノード間の通信に使われるのに、IPアドレスは接続されたノード間の通信のために使用される。例えば、送信元IPアドレス"192.168.1.2"から宛先IPアドレス"64.4.11.37"への通信を行う場合、経路中のパケットやフレームで使用される各アドレス情報は、それぞれ図のようになる(実際にはプライベートアドレスと呼ばれる"192.168.1.2"からグローバルアドレス"64.4.11.37"には直接通信できない)。

このように送信元・宛先IPアドレスが常にエンドのものであるのに対し、送信元・宛先MACアドレスはフレームを送受信するノードのものが使用される。

ネットワークインタフェース

IPアドレスはMACアドレスに対応付けられると述べたが、厳密にはこれは正しくない。前述の通り、MACアドレスはネットワークデバイス毎に割り当てられている。しかしソフトウェアレベルでは、ネットワークデバイスを抽象化したネットワークインタフェースという単位で扱われ、IPアドレスはネットワークインタフェースに割り当てられる。そして、ネットワークインタフェースにはMACアドレスがないがIPアドレスを持つものや、1つのネットワークインタフェースで複数のIPアドレスを持つもの、いくつかのネットワークインタフェースで同じMACアドレスが使用されるようなものなど様々なタイプがある。例えばUNIX系OSでは、ローカルループバックと呼ばれる自分自身と通信するためのIPアドレスが割り当てられたネットワークインタフェースがある。これは実際のネットワークデバイスの有無に関係なく存在し、かつMACアドレスがない。

ネットワーククラス -RFC791-

RFC791では、IPアドレスは3つの要素から構成される。各フィールドは、クラスとネットワークアドレス、ホストアドレスに分けられる。

クラス
ネットワークの規模。
ネットワークアドレス
ネットワークの識別番号。
ホストアドレス
あるネットワーク内のノードの識別番号。
クラス 0123456789 10111213141516171819 20212223242526272829 3031
A 0
B 1 0
C 1 1 0
1 1 1 拡張アドレスモード
IPアドレスは1バイト(8ビット)毎に区切って表示される(例:172.16.1.1)。IPアドレスにはいくつかの特別な番号のものがある。

サブネット -RFC950-

RFC950では、RFC791で出てきたネットワークを更に小さいネットワーク(サブネット)に分割できる。サブネットを指定するには、ネットワークマスクと呼ばれる32ビットの値を使用する。例えばクラスBのネットワークは次のようにしてサブネットを指定する。

0123456789 10111213141516171819 20212223242526272829 3031
B 1 0 ネットワーク ホスト
1 0 ネットワーク サブネット ホスト
1111111111 1111111111 000000000000
ネットワークマスクは255.255.0.0のように記述したり、IPアドレスと一緒に172.16.1.1/16のようにして表す。

プライベートアドレス -RFC1918-

インターネットで使用されるIPアドレスをグローバルアドレスと呼ぶ。そして、これとは別に局所的なネットワークで使用されるアドレスがある。これをプライベートアドレスという。RFC1918ではプライベートアドレスの範囲を次のように定めた。

10.0.0.0〜10.255.255.25510.0.0.0/8
172.16.0.0〜172.31.255.255172.16.0.0/12
192.168.0.0〜192.168.255.255192.168.0.0/16
プライベートアドレスとグローバルアドレスは、直接通信することができない。そのため、プライベートアドレスのマシンからグローバルアドレスのマシンにアクセスする場合、グローバルなネットワークに接続するルータによってアドレス変換が行われる。これをNAT(Network Address Translation)という。

このようなRFCで定められたグローバルアドレス以外の特別なアドレスのことを予約アドレスという。

予約アドレス

2014/02時点の予約アドレスは次の通りである。

アドレスネットワーク名RFC
0.0.0.0/8現在のネットワークRFC1122
10.0.0.0/8PRIVATE-ADDRESS-ABLK-RFC1918-IANA-RESERVEDRFC1918
127.0.0.0/8SPECIAL-IPV4-LOOPBACK-IANA-RESERVEDRFC6598
169.254.0.0/16SHARED-ADDRESS-SPACE-RFCTBD-IANA-RESERVEDRFC3927
172.16.0.0/12PRIVATE-ADDRESS-ABLK-RFC1918-IANA-RESERVEDRFC1918
192.0.0.0/24SPECIAL-IPV4-REGISTRY-IANA-RESERVEDRFC5736
192.0.2.0/24IANA Special UseRFC5737
192.88.99.0/246TO4-RELAY-ANYCAST-IANA-RESERVEDRFC1198
192.168.0.0/16PRIVATE-ADDRESS-ABLK-RFC1918-IANA-RESERVEDRFC1918
198.18.0.0/15SPECIAL-IPV4-BENCHMARK-TESTING-IANA-RESERVEDRFC2544
198.51.100.0/24TEST-NET-1RFC5737
203.0.113.0/24TEST-NET-3RFC5737
224.0.0.0/4マルチキャスト(クラスD)RFC3171
240.0.0.0/4クラスERFC1112
255.255.255.255ブロードキャストRFC919,RFC922
RFCは廃止される場合がある。すなわち予約アドレスが常に同じとは限らないし、それを規定するRFCも同じであるとは限らない。例えばプライベートアドレスは初めRFC1597で規定されたが、今は廃止され、現在はRFC1918で規定されている。

UNIX系OSでは、いくつかの例外を除いてIPアドレスの情報をwhoisコマンドで調べることができる。例えば127.0.0.1のIPアドレスについて調べたい時、次のようにすれば良い。

user% whois 127.0.0.1

ドメイン

人間がIPアドレスを指定する際、多くの場合はIPアドレスを指定する代わりにドメイン名といわれるコンピュータ名を指定する。ドメイン名はICANN(Internet Corporation for AssignedNames andNumbers)と呼ばれる団体によって管理される。ドメイン名の情報は、アプリケーション層のWHOISプロトコルを使用して取得できる。UNIX系では、そのためのクライアントアプリとしてwhoisがある。

user% whois google.co.jp

ドメインは、アプリケーション層のDNSという仕組みによって成り立つ。ドメイン名はDNSサーバによって管理され、DNSクライアントでアクセスすることで、ドメイン名からIPアドレスへ変換することができる。

user% nslookup google.co.jp


ルーティング

ルーティングとは、パケットの経路制御のことである。ルーティングはルーティングテーブルに基づいてルート(経路)を探索する。ルーティングは次の2種類に分類できる。

静的ルーティング
手動でルーティングテーブルの中身を設定する方法。
動的ルーティング
アルゴリズムに基づいて自動でルーティングテーブルの中身を設定する方法。経路決定アルゴリズムには次の2種類がある。
  • 距離ベクトルアルゴリズム(DVA:Distance Vector Algorithm)
  • リンク状態アルゴリズム(LSA:Link State Algorithm)

ここでルーティングの仕組みを紹介する。次のような3つのネットワークインタフェースを持つノードがあるとする。

lo
127.0.0.1
eth0
192.168.1.2/24
eth1
173.194.117.183/16
この時、ルーティングテーブルは次のような情報を持つ。
ネットワーク/ノードゲートウェイインタフェース
デフォルト192.168.1.1eth0
192.168.1.0/24*eth0
173.194.0.0/16*eth1
127.0.0.1/8*lo
ゲートウェイとは、あるパケットを別のネットワークに転送してくれるためのノードのことである。ここで、*はゲートウェイが設定されていないこと、すなわちそのネットワークに属するノードであることを示す。同じネットワーク内のノードであれば、データリンク層で接続されているため、直接通信可能である。また、全てのルーティングテーブルには、デフォルトルートと呼ばれるものがある。もしルーティングテーブルに宛先のネットワークが載っていない場合、デフォルトルートを使用する。

次のようなネットワークで前述のノードが通信を行うとする。

この時、送信元IPアドレスから宛先IPアドレス(64.4.11.37)までの経路は次のようになる。
  1. 宛先のネットワークが不明のため、デフォルトルートを使用。eth0のネットワークインタフェースを使用し、192.168.1.1に送信。
  2. 203.216.243.243に送信。
  3. 64.4.11.37に送信。
送信元ノードは、経路途中にあるノードのルーティングテーブルの情報が分からなくても問題ない。また、各ネットワーク内のノード間はデータリンク層で接続されており、識別にはMACアドレスが使用されている。データリンク層の通信については本稿では詳しく言及しない。IPアドレスはARPによってMACアドレスに変換することができる。

ネットワークインタフェースの情報は、UNIX系OSではifconfig、Windowsではipconfigコマンドで、ルーティングテーブルの情報は、UNIX系OSもWindowsも、routeコマンドや、netstatコマンドの-rオプションで表示したり設定したりできる。また、パケットが辿った経路については、tracerouteコマンドで確認することができる。


関連コマンド

以下にネットワーク層に関するコマンドをいくつか紹介する。なおここで紹介するコマンドは、主にUNIX系OSを想定している。

whois
IPアドレスやドメインの情報をRFC3912のデータベースより検索するコマンド。ドメインとはIPアドレスに対応づけた名前のことで、"google.co.jp"や"yahoo.co.jp"などがそれに該当する。whoisの使い方は次の通りである。
user% whois 173.194.117.166
これによりネットワークの大きさや名前、それを管理する団体の情報などを取得できる。また、ドメインを指定することでそのドメインの管理者や有効期限などの情報を取得できる。
user% whois google.co.jp
nslookup
dig
ドメインとIPアドレスを変換するにはnslookupやdigコマンドがある。nslookupコマンドはWindowsにもあり、基本的な使い方は同じである。nslookupコマンドの使い方は、コマンドの引数を指定する方法と対話する方法の2種類がある。
user% nslookup google.co.jp
user% nslookup
> google.co.jp
traceroute
パケットの経路を調査し、出力するコマンド。
user% traceroute google.co.jp
tracerouteのオプションをいくつか紹介する。
-p port
ポート番号を指定。
-i device
デバイスを指定。
ping
ICMP Echo Requestパケットを送信するコマンド。pingはUNIX系OSだけでなくWindowsでも使用可能である。以下にUNIX系OSのpingのオプションをいくつか紹介する。
-v
詳細な情報を出力。
-b
ブロードキャストで行う。
-R
経路を表示。
-i wait
個々の送信間隔をwait秒分間を置く。標準では1秒。
pingは次のようにして使用する。
user% ping google.co.jp
netstat
ネットワークに関する情報や状態を表示・設定するコマンド。以下にいくつか例を示す。UNIX系OSにもWindowsにもあるコマンドだが、使い方(オプション)は異なる。
ルーティングテーブル
user% netstat -r
UNIX系OS、Windows共に-rは同じである。
user% netstat --route
user% route
ネットワークインタフェース
user% netstat -i
user% netstat --interfaces
使用中のソケット情報を確認(つまりポートの状態も確認できる)
user% netstat -a
user% netstat --all
プロトコル毎のログの統計
user% netstat -s
user% netstat --statistics
なおオプション-nを指定することで、アドレスやポート番号をそのまま数字で表示する。
route
ルーティングテーブルの表示・設定を行うコマンド。routeは基本的に処理とそれに対する引数を指定する。処理を指定しなければ現在のルーティングテーブルを表示する。
add
ルーティングテーブルへの追加処理。
  • user% route add -net 192.168.1.0 netmask 255.255.255.0 dev eth0
  • user% route add -host 192.168.1.2 gw 192.168.1.1 dev eth0
  • user% route add -net default gw 192.168.1.1 dev eth0
del
ルーティングテーブルからの削除処理。
  • user% route del -net 192.168.1.0 netmask 255.255.255.0 dev eth0
  • user% route del -host 192.168.1.2 gw 192.168.1.1 dev eth0
  • user% route del -net default
ifconfig
ipconfig
ネットワークインタフェースの情報を表示・設定するコマンド。UNIX系OSはifconfig、Windowsはipconfigであり、使い方も異なる。
user% ifconfig -a
user% ipconfig /all
設定にはルート権限が必要である。 例えばIPアドレスとネットワークマスクは次のようにして設定する。
user% ifconfig eth0 192.168.1.100 netmask 255.255.255.128 
これ以外にもさまざまな設定がある。例えば通常ネットワークデバイスは自分のIPアドレス以外のパケットは破棄する(データリンク層でユニキャストを実現する)が、プロミスキャスモードというモードを有効にすれば、それを受信できる。
user% ifconfig eth0 promisc
DHCP
5階層TCP/IPモデルのアプリケーション層のDHCPによってIPアドレスを設定する場合、IPアドレスはサーバによって割り当てられる。そして多くのルータはDHCPサーバの機能を持つ。それゆえ多くのルータが使用される環境では、個々のノードが自身のIPアドレスを決めることはないだろう。UNIX系OSでは、DHCPクライアントにdhclientコマンドがある。以下に簡単な使い方を紹介する。
user% dhclient eth0
iwconfig
iwspy
無線のネットワークインタフェースのためのコマンド。
tcpdump
パケットスキャニングツール。5階層TCP/IPモデルのより上位の層のためにも活用できるコマンドで、指定したネットワークインタフェースが扱ったパケット情報を出力する。tcpdumpについてはアプリケーション層のところで詳述する。
user% tcpdump -i eth0
-i interface
ネットワークインタフェースを指定。
-e
イーサネットフレームのヘッダを表示。
-x
-X
パケットの中身を16進数で表示。-Xの場合、それに加えてASCII文字に変換したものも表示。
-n
アドレス(IPアドレスやポート番号)を名前に変換しない。
-N
ホストを名前に変換しない。
expression
パケットフィルタ機能。いかにいくつかの機能を紹介する。
proto
プロトコルを指定。
src host
送信元アドレスを指定。
src port port
送信元のポート番号を指定。
dst host
宛先アドレスを指定。
dst port port
宛先のポート番号を指定。
and
or
not
いくつかの条件を組み合わせる
iptables
PF
パケットフィルタツール。iptablesはLinux用の、pfは主にBSD系で使用されるパケットフィルタである。iptablesの詳細はここを参照されたい。

パケットプログラミング

IPパケットの送信

ネットワーク層のサービスを利用してデータを送信する例を紹介する。IPパケットを生成して送信するプログラムのソースコードは、次のように記述できる。なおこのコードはエラー処理のコードを記述していない。

#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(int argc, char *argv[])
{
  const int ON=1;
  const char* DST_ADDR = "192.168.1.1";
  const unsigned char IP_PACKET[] = {
    0x45, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x40, 0x00,
    0xFF, 0x04, 0x00, 0x00,
    0xad, 0xc2, 0x7e, 0x0d, // src 173.194.126.13
    0xc0, 0xa8, 0x01, 0x01, // dst 192.168.1.1
    0x00, 0x01, 0x02, 0x03, 
    0x04, 0x05, 0x06, 0x07
  };
  int sock;
  struct sockaddr_in sin;
  
  memset(&sin, 0, sizeof(struct sockaddr_in));
  sin.sin_family = PF_INET;
  sin.sin_addr.s_addr = inet_addr(DST_ADDR);
  sin.sin_port = 0;
  
  sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);  
  setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &ON, sizeof(int));
  sendto(sock, IP_PACKET, sizeof(IP_PACKET), 0, (struct sockaddr*)&sin, sizeof(sin));
  
  return 0;
}
このコードは、IPパケットを送信するプログラムである。このプログラムを正常に実行するにはルート権限が必要である。

タイプがSOCK_RAWについては、マニュアル第7章のrawを参照されたい。

user% man 7 raw
マニュアルによると、IPヘッダの大きさやヘッダ・チェックサムは関数によって自動的に計算される。また、ソースアドレスとパケットIDは0の場合に変更される。 このプログラムを実行し、そのパケットをtcpdumpで見た結果を以下に示す。
15:43:32.732162 IP 173.194.126.13 > 192.168.1.1: IP0 [|ip]
     (ipip-proto-4)
     0x0000:  4500 001c 0000 4000 ff04 8e64 adc2 7e0d
     0x0010:  c0a8 0101 0001 0203 0405 0607

IPパケットの受信

ICMPパケットを受信するようなプログラムのコードは次のように記述される。このコードも同様にエラー処理を省略している。

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
  int i;
  int sock;
  unsigned char packet[0x54];
  
  sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
  while (1){
    recv(sock, packet, sizeof(packet), 0);
    for (i=0;i<0x54;i++){
      if (i%4==0) putchar('\n');
      printf("0x%.2x ", packet[i]);
    }
    putchar('\n');
  }
  close(sock);
  return 0;
}
このプログラムもまた正常に実行するにはルート権限が必要である。

このプログラムを起動中に、127.0.0.1宛にpingをすると、次のように画面に出力されるだろう。

0x45 0x00 0x00 0x54 
0x80 0x72 0x00 0x00 
0x40 0x01 0xfc 0x34 
0x7f 0x00 0x00 0x01 
0x7f 0x00 0x00 0x01 
0x00 0x00 0x19 0xed 
0x18 0xaa 0x00 0x01 
0xa9 0x65 0x07 0x53 
0x2c 0xac 0x05 0x00 
0x08 0x09 0x0a 0x0b 
0x0c 0x0d 0x0e 0x0f 
0x10 0x11 0x12 0x13 
0x14 0x15 0x16 0x17 
0x18 0x19 0x1a 0x1b 
0x1c 0x1d 0x1e 0x1f 
0x20 0x21 0x22 0x23 
0x24 0x25 0x26 0x27 
0x28 0x29 0x2a 0x2b 
0x2c 0x2d 0x2e 0x2f 
0x30 0x31 0x32 0x33 
0x34 0x35 0x36 0x37 

コンピュータ・ネットワーク(5) -トランスポート層-

投稿日:
修正日:
タグ:

目次

トランスポート層は5階層TCP/IPモデルの下から4番目であり、上位の層にサービスを行う最後の層である。

アプリケーション層
トランスポート層
ネットワーク層
データリンク層
物理層

トランスポート層は、アプリケーション層の各サービスに対し、通信を提供する。

サービス
    サービスを行ったり受けたりするために、そのプロセスに通信を提供。
  • フロー制御
  • 輻輳制御
  • 誤り検出
インタフェースデータ単位ソケット
アドレスポート番号
代表的なプロトコル
  • TCP
  • UDP
※UDPはフロー制御や輻輳制御などは行わず、アプリケーション層に任せているため、TCPだけといえなくもない
トランスポート層の代表的なプロトコルには、コネクション型のTCPと、コネクションレス型のUDPがある。TCPは電話のように互いにコンタクトを取りながらデータ通信を行うことで、品質の高い通信を提供する。UDPは手紙のように送信者が一方的に受信側にデータを送るようなものである。UDPの場合、送りつけられたデータが届いたかどうか、それが完全なものであるかの確認や、受信側やネットワークへの負荷管理などはアプリケーション層で確認しなければならない。
TCP(Transmission Control Protocol)
フロー制御や輻輳制御、誤り検出などを行うことで、高品質な通信をアプリケーション層に提供。
UDP(User Datagram Protocol)
TCPのような高品質な通信を行うための機能をアプリケーション層に任せることで、トランスポート層での高速通信を可能にする。
TCPの通信は、次の2種類の通信から成る。
  • データの送受信のための通信
  • 通信制御のための通信
本稿ではTCPを中心に説明する。

TCPの通信では、あるノードAがノードBに対してデータを送る場合、ノードAを送信側、ノードBを受信側と呼ぶ。ノードBからノードAに対して通信制御のための情報を送信することもあるが、多くの場合、その呼び方は変わらない。


3ウェイ・ハンドシェイク

TCPではコネクション型の通信を行う。そのために3ウェイ・ハンドシェイクと呼ばれる接続の確立を行う。接続の確立には、データ通信を開始するのを含め次の5つの工程が必要である。

  1. 送信者がSYNパケットを送る。
  2. 受信者がACKパケットを送る。
  3. 受信者がSYNパケットを送る。
  4. 送信者がACKパケットを送る。
  5. データを送信する。
SYNパケットは同期開始の合図であり、ACKパケットは確認の合図である。

TCPでは、これらの工程の次のように3つの工程にまとめている。

  1. 送信側がSYNパケットを送信する。
  2. 受信側がSYNパケットとACKパケットを送信する。
  3. ACKパケットと、データを送信する。

3ウェイ・ハンドシェイクで接続が確立されなければ、アプリケーション層はアクセスがあったかどうかも認識できない。それゆえ、SYNパケットを送り、SYN+ACKパケットが返ってくるかを待ち、返ってきても最後のACKを送信しないことで、相手に悟られることなくそのポートでTCPを使った通信を行なっているかを確認することができる。このような処理をポートスキャンという。これを防ぐには、1階層下のネットワーク層で、通信を監視する必要がある。このような機能や、それによって通信を防ぐ機能をファイアウォールという。

フロー制御

TCPのフロー制御では、受信相手の状況に応じて送信量を制御することで、受信側の負荷を小さくしようとする。そのために、受信側は受信可能な通信量、つまり受信者のバッファの空きサイズを送信側に知らせる。この通信量を制御する仕組みをスライディングウィンドウと、受信可能なサイズのことをウィンドウ・サイズという。受信側は,受信可能なウィンドウサイズを,ソケットのウィンドウ・サイズフィールドによって通知する。

輻輳制御

2つのノードが通信する場合,それが同一のネットワークであるとは限らない。そのような場合,パケットはノード間の転送速度は間にあるいくつかのネットワークやルータによって処理速度が変化する。それゆえ,それぞれのノードが好き放題な送信を行い,ルータがそれを処理しきれずにパケットをロスすれば結果として遅くなる。また,ネットワーク全体としての性能(スループット)も低下する。TCPにはこのような問題を防ぎ、ネットワークの利用効率を良くするための仕組み(輻輳制御の機能)がある。その仕組みがスロースタートアルゴリズムである。

送信側は、はじめに送出するサイズを小さく設定し、それから指数オーダ的に大きくしていく。もし輻輳が発生した場合,受信側はそれを送信側に知らせ,送出するサイズを小さくさせる。TCPでは送信側と受信側がそれぞれパケットを送りあうことでコネクションを確立するが,もし輻輳が発生した場合,受信側は送信側に送るパケットサイズを小さくすることで,それを知らせる。これはTCPには元々輻輳制御が備わっておらず,後に追加されたためにこのような通知手段をとっている。送出するサイズもまたウィンドウサイズという単位で扱われるが,輻輳制御の場合ウィンドウサイズはOSによって管理される。輻輳が発生してウィンドウサイズを減らした後,送信側は今度は線形的にウィンドウサイズを増やしていくことで,送出するサイズを理想的な状態に近づける。

ルータがパケットをロスするような場合,ルータはICMPパケットを使ってそれを送信側に知らせる。通信経路を特定するためのコマンドtracerouteは,この特性を利用して徐々にTTL(Time To Live)を増やしていく事で実装される。


ソケット

TCP通信で使用するソケットは次のような構造である。ここで各セルはビット単位を表す。

01234567 89101112131415 1617181920212223 2425262728293031
送信元ポート番号宛先ポート番号
シーケンス番号
ACK番号
データオフセット 予約領域 NS CWR ECE URG ACK PSH RST SYN FIN ウィンドウ・サイズ
チェックサム 緊急ポインタ
オプション(32ビット単位で可変長)
データ部分(可変長)
送信元ポート番号
サービスを行うトランスポート層のアドレス。
宛先ポート番号
サービスを受けるトランスポート層のアドレス。
シーケンス番号
データを分割して送信する場合、その順番を表す値。送信するデータには、1バイト毎に順にシーケンス番号が割り当てられている。シーケンス番号の値は、データの先頭が0とは限らず、最大値まで使用すると0から順に割り当てられる。シーケンス番号はTCPデータの送信側で管理される。例えば30バイトのデータを10バイトずつ送信する場合、ソケットのシーケンス番号は1つ目はn、2つ目はn+10、3つ目はn+20となる。
ACK(Acknowledge)番号
受信側がデータをどのシーケンス番号まで受信したか示す値。ACK番号は受信したデータのシーケンス番号+1である。例えば10バイトのデータを受信した場合、初期値+10の値になる。
データオフセット
ヘッダ長
TCPソケットのデータが始まる位置、またはTCPソケットのサイズを示す値。
予約領域
将来的に使用されるために予約されているフィールド。現在は未使用で値は常に0である。
フラグ
パケット(ソケット)の種類を表すフィールド群。各フィールドは1の時にオン、0の時にオフを表す。標準では全て0である。RFC793ではフラグが6つであったが、後に追加されていき、RFC3540までに3つ追加されて9ビットとなり、その分予約領域が縮小された。
URG
URGentフラグ。緊急データが含まれていることを表す。
ACK
ACKnowledgeフラグ。ACK番号が含まれていることを表す。
PSH
PuSHフラグ。受信したデータをすぐに上位レイヤに提供することを表す。
RST
ReSeTフラグ。TCP接続を中断、拒否することを表す。ある接続要求に対してACKならば接続許可、RSTならば接続拒否を表す。
SYN
SYNchronizeフラグ。接続要求を表し、ACK番号を同期する。
FIN
FINishフラグ。接続終了を表す。
後に追加されたフラグ
ECE
RFC3168で追加されたフラグで、輻輳が起こっていることや輻輳情報を通知するための機能が備わっていることを示す。ECN-Echoフラグ。具体的には、3ウェイハンドシェイク(SYNフラグがオン)の際、ECN(輻輳情報通知機能)対応であること、すなわちIPパケットのTOSの予備フィールドをECNのために使用できる(10か01、11の値かもしれない)ことを示す。それ以外(SYNフラグがオフ)の時、IPパケットのCEフラグが1だったことを示す。
CWR
RFC3168で追加されたフラグで、輻輳ウィンドウ・サイズを小さくしたことを示す。すなわち受信側がENEフラグがオンであるソケットを受信した場合、これをオンにしたソケットを送信することで、輻輳制御機構で対応したことを通知する。Congestion Window Reducedフラグ。
NS
RFC3540で追加されたENC Nonce Sumフラグ。
ウィンドウ・サイズ
受信側が受信可能なソケットのサイズ。
チェックサム
ヘッダやデータの誤りを検査するための値。
緊急ポインタ
URGフラグがオンの時に使用されるフィールド。 緊急データが シーケンス番号からのオフセットを示す。
オプション
拡張情報のためのフィールド。32ビット単位で可変長で、最小サイズは0バイトである。MSS(最大セグメントサイズ)やウィンドウ・スケーリングなどを設定するのに使用され、情報が32ビット単位にならない場合はその分0を詰められる(これをパディングと呼ぶ)。


関連コマンド

telnet
TELNETプロトコルのインタフェース。標準では23番が使われるが、ポート番号を指定することで他のポートにアクセスしてTCP通信が可能である。
user% telnet pied-piper.net 80
GET /note/note.cgi HTTP/1.1
Accept: image/gif, image/jpeg, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (Compatible; MSIE 6.0; Windows NT 5.1;)
Host: pied-piper.net
Connection: Keep-Alive

nc
netcat
TCPかUDPで通信を行うためのユーティリティ。telnetと異なりtcpだけでなく、UDPも扱え、ポートスキャンやソケットの受け取り側としても起動可能。
-u
UDPモードで起動。
-l
リッスンモードで起動。
-p port
リッスンモードの際に開くポート番号を指定。
-s port
ソースポートを指定。
-z
スキャンのみでデータを送らない。
-v
詳細な情報を出力。
接続
user% nc pied-piper.net 80
GET /note/note.cgi HTTP/1.1
Accept: image/gif, image/jpeg, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (Compatible; MSIE 6.0; Windows NT 5.1;)
Host: pied-piper.net
Connection: Keep-Alive

user% nc -u -z localhost 5555
リッスンモード
user% nc -p 5555 -l localhost
user% nc -p 5555 -u -l localhost
ポートスキャン
user% nc -z -v localhost 0-65535
user% nc -z -u -v localhost 0-65535
nmap
高性能ポートスキャニングツール。
user% nmap localhost -p1-1024 -sT
user% nmap localhost -p1-1024 -sT -sU
user% nmap 192.168.1.1,2 -p1-100,500-1024 -sT -sU
-p
ポート番号やポート番号の範囲を指定。
-T0
-T1
-T2
-T3
-T4
-T5
スキャンのタイミングを設定。数字が大きいほどスキャン速度は速い。
-r
検査するポートの順番は標準では無作為だが、順番に行うように設定。
-sT
TCP接続でスキャン。
-sU
UDPでスキャン
-sS
TCP SYNパケットでスキャン。
-sA
TCP ACKパケットでスキャン。
-sF
TCP FINパケットでスキャン。
-s0
IPパケットでスキャン。
-PE
ICMP Echoパケットでスキャン。
-PP
ICMP Timestampパケットでスキャン。
-PM
ICMP Address Maskパケットでスキャン。
-O
アクセス先マシンのOSを推測。ルート権限でのみ使用可能
--traceroute
tracerouteを行う。
tcpdump
パケットスキャニングツール.さまざまな機能を持ち、5階層TCP/IPモデルのいくつかの層で利用可能であり、プロトコルや宛先ポート番号、送信元ポート番号でフィルタリングすることができる。
user% tcpdump -X src port 80 -i eth0
proto
プロトコルを指定.
src port port
送信元のポート番号を指定.
dst port port
宛先のポート番号を指定.
and
or
not
いくつかの条件を組み合わせる


ソケットプログラミング

UDPやTCPソケット通信を利用したプログラム、すなわちアプリケーション層のプログラムは次のように書くことができる。

TCP

サーバ・プログラム

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>


int main(int argc, char *argv[])
{
  const char* SERVER_ADDR = "192.168.1.14";
  const int SERVER_PORT = 50000;
  int server_fd, client_fd;
  FILE *fp;
  struct sockaddr_in sin, pin;
  char buf[20];
  size_t size = sizeof(struct sockaddr_in);
  
  memset(&sin, 0, sizeof(struct sockaddr_in));
  sin.sin_family = PF_INET;
  sin.sin_addr.s_addr = inet_addr(SERVER_ADDR);
  sin.sin_port = htons(SERVER_PORT);
  
  server_fd = socket(PF_INET, SOCK_STREAM, 0);
  bind(server_fd, (struct sockaddr*)&sin, sizeof(struct sockaddr_in));
  listen(server_fd, 50);
  
  client_fd = accept(server_fd, (struct sockaddr*)&pin, &size);
  fp = fdopen(client_fd, "w+");
  
  fprintf(fp, "Hello, Client\n");
  
  fgets(buf, 20, fp);
  printf("client ip:%s\n", inet_ntoa(pin.sin_addr));
  printf("Message: %s\n", buf);
  
  fclose(fp);
  return 0;
}

クライアント・プログラム

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>


int main(int argc, char *argv[])
{
  const char* SERVER_ADDR = "192.168.1.14";
  const int SERVER_PORT = 50000;
  int server_fd;
  FILE *fp;
  struct sockaddr_in sin;
  char buf[20];
  
  memset(&sin, 0, sizeof(struct sockaddr_in));
  sin.sin_family = PF_INET;
  sin.sin_addr.s_addr = inet_addr(SERVER_ADDR);
  sin.sin_port = htons(SERVER_PORT);
  
  server_fd = socket(PF_INET, SOCK_STREAM, 0);
  connect(server_fd, (struct sockaddr*)&sin, sizeof(struct sockaddr_in));
  fp = fdopen(server_fd, "w+");
    
  fgets(buf, 20, fp);
  
  fprintf(fp, "Hello, Server\n");
  printf("Server ip:%s\n", inet_ntoa(sin.sin_addr));
  printf("Message: %s\n", buf);
  
  fclose(fp);
  return 0;
}


UDP

送信側プログラム

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>


int main(int argc, char *argv[])
{
  const char* SERVER_ADDR = "192.168.1.14";
  const int SERVER_PORT = 50000;
  const char HELLO[] = "Hello, Server";
  int sock;
  struct sockaddr_in sin;
  char buf[20];
  
  memset(&sin, 0, sizeof(struct sockaddr_in));
  sin.sin_family = PF_INET;
  sin.sin_port = htons(SERVER_PORT);
  sin.sin_addr.s_addr = inet_addr(SERVER_ADDR);
  
  sock = socket(PF_INET, SOCK_DGRAM, 0);
  
  sendto(sock, HELLO, strlen(HELLO), 0, (struct sockaddr*)&sin, sizeof(struct sockaddr_in));
  
  close(sock);
  return 0;
}

受信側プログラム

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>


int main(int argc, char *argv[])
{
  const char* SERVER_ADDR = "192.168.1.14";
  const int SERVER_PORT = 50000;
  const char HELLO[] = "Hello, Client";
  size_t len = sizeof(struct sockaddr_in);
  int sock;
  struct sockaddr_in sin, pin;
  char buf[20];
  
  memset(&sin, 0, sizeof(struct sockaddr_in));
  sin.sin_family = PF_INET;
  sin.sin_port = htons(SERVER_PORT);
  sin.sin_addr.s_addr = inet_addr(SERVER_ADDR);
  
  sock = socket(PF_INET, SOCK_DGRAM, 0);
  bind(sock, (struct sockaddr*)&sin, len);
  
  recvfrom(sock, (void*)buf, 13, 0, (struct sockaddr*)&pin, &len);
  buf[13] = '\0';
  printf("Message: %s\n", buf);
  
  close(sock);
  return 0;
}

コンピュータ・ネットワーク(6) -アプリケーション層-

投稿日:
修正日:
タグ:

目次

アプリケーション層は、OSI参照モデルや5階層TCP/IPモデル、4階層TCP/IPモデルなどで最も上位の層である。

アプリケーション層
トランスポート層
ネットワーク層
データリンク層
物理層
本稿では、アプリケーション層のいくつかのプロトコルによって実装されるWebや電子メールについて紹介する。

ポート番号

5階層TCP/IPモデルでは、アプリケーション層の各プロトコルはトランスポート層で提供されるポートを利用する。そして、いくつかの有名なプロトコルでは、サーバで利用するポート番号がICANNによって標準化されている。また、それ以外の多くのプロトコルも使用するポート番号が明示されている。

ウェルノウンポート番号(well-known ports)0-1023ICANNで登録されているポート番号の範囲のうち有名なもの
登録済みポート番号1024-49151ICANNで登録されているポート番号の範囲
プライベート(ダイナミック)ポート番号49152-65535 ユーザやアプリケーションが自由に利用できるポート番号の範囲。多くの場合、クライアントアプリが必要に応じて動的に使用する。

ウェルノウンポート番号(0-1023)

TCP/UDPポート番号プロトコル名機能サーバ例クライアント例
TCP,UDP7ECHO 基本的にテスト用途で使用される。送られたデータをそのまま返す
TCP20FTPFile Transfer Protocolファイル送受信のためのプロトコル。データ転送用
  • Webブラウザ
  • ftp
TCP21ファイル送受信のためのプロトコル。制御用
TCP22SSHSecure SHell暗号や認証技術を用いた安全な通信やリモートログインのためのプロトコル。
  • OpenSSH Server
  • OpenSSH Client
TCP,UDP25SMTPSimple Mail Transfer Protocol電子メールの送受信に使用するプロトコル。
  • qmail
  • sendmail
  • thunderbird
  • Microsoft Outlook
TCP,UDP42WINSWindows Internet Naming Service Microsoft Windowsネットワーク上のコンピュータ名をIPアドレスに変換するためのプロトコル。宛先不明のため、クライアントはブロードキャストで問い合わせを行う。
TCP43WHOISドメイン名やIPアドレスなどの所有者情報を取得するためのプロトコル。
  • whois
TCP,UDP53DNSDomain Name System IPアドレスとドメイン名の対応情報を取得するためのプロトコル。
  • BIND
  • Djbdns
  • nslookup
  • dig
TCP,UDP80HTTPHyperText Transfer Protocol HTMLや画像、テキストなどの送受信のためのプロトコル。 Webサーバ
  • apache
  • IIS
Webブラウザ
  • Internet Explorer
  • Google Chrome
UDP123NTPNetwork Time Protocolマシンの時間を同期するためのプロトコル。
  • ntpdate
TCP443HTTP over SSLSSL通信を用いたSMTP
TCP465SMTP over SSLSSL通信を用いたSMTP

登録済みポート番号(1024-49151)

TCP/UDPポート番号プロトコル名機能サーバ例クライアント例
TCP,UDP1194OpenVPNオープンソースのVirtual Private Networkソフトウェアのためのプロトコル。
TCP,UDP1293IPSecInternet Protocol SecurityIPパケット単位でのデータ改ざん防止や秘匿機能を提供するためのプロトコル。
TCP,UDP3389RDPRemote Desktop ProtocolMicrosoftが開発しているリモートデスクトップサービスのためのプロトコル。
  • リモートデスクトップ接続
TCP,UDP5900VNCVirtual Network Computingリモートデスクトップ方式のためのプロトコル。
TCP6000X11ネットワーク経由でXを利用するためのプロトコル。
UDP6001
TCP8080HTTPの代替HTTPのプロキシサーバやキャッシュサーバなどに使用される。

プライベート(ダイナミック)ポート番号(49152-65535)

多くのプロトコルでは、クライアントアプリケーションが使用するポート番号は、プライベートポート番号の中で使われていないもの無作為に動的に使用する。例えば、WebブラウザでHTTP(80番ポート)のサイトにアクセスする際のパケット解析した結果の一部を示す。

user% tcpdump -n -X dst port 443 -i wlan0
06:29:52.791584 IP 192.168.1.14.60063 > 183.77.202.242.80: Flags
[S], seq 1904628341, win 14600, options [mss 1460,sackOK,TS val
104657554 ecr 0,nop,wscale 4], length 0
この解析後すぐにサーバとクライアントのTCPポートを確認すると、それぞれ次のような結果となる。
サーバ
uesr% telnet 183.77.202.242 80
Trying 183.77.202.242...
Connected to 183.77.202.242.
Escape character is '^]'.
クライアント
uesr% telnet localhost 60063
Trying ::1...
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
このようにクライアントのポートは、動的に使用される。

また、同じクライアントアプリを起動し直して再度同じページにアクセスしてもクライアントが使用するポート番号が同じであるとは限らない。

user% tcpdump -n -X dst port 443 -i wlan0
06:34:15.218947 IP 192.168.1.14.60082 > 183.77.202.242.80: Flags
[F.], seq 2386135769, ack 94445475, win 2641, options [nop,nop,TS val
104723161 ecr 2033111718], length 0
前の例では、クライアントアプリは60063番ポートを使用したが、今回は60082番ポートを使用している。このように、クライアントアプリは、49152番から65535番のポート番号を動的に使用する。

TCP

トランスポート層のTCPは、高品質なデータ通信を可能にする。アプリケーション層では、これを利用したものがいくつもある。それらはユーザに対して、さまざまなものを提供する。

  • テキスト
  • メッセージ
  • 音声
  • 動画

telnet

telnetコマンドを使用すると、ユーザは簡単にTCPのサービスを受けることができる。telnetは指定したIPアドレスのポート番号に対し、ユーザが入力した文字列を送信する。本稿では、これを利用してHTTPやSMTP、POP3などのプロトコルを説明する。


Web(HTTP)

WWW(World Wide Web)上でテキストや画像などのデータを通信するのに使用されている代表的なプロトコルが、HTTP(Hyper Text Transfer Protocol)である。HTTPサーバは基本的にTCPポートの80番を使用し、クライアントが要求したテキストや画像などを送信する。HTTPクライアントとして最も有名なアプリケーションがWebブラウザである。Webブラウザにはさまざまな種類がある。

  • Internet Explorer
  • Firefox
  • Google Chrome
  • Safari

ユーザの中にはWebブラウザが表示したWebページを、Web(HTTP)サーバが提供している画面だと認識しているかもしれない。しかしHTTPクライアントが取得するデータは、基本的にHTML(Hyper Text Markup Language)という形式のテキストである。HTTPのバージョン1.0では、クライアントは次のようにGETメソッドを使用してHTMLテキストを取得できる。

user% telnet pied-piper.net 80
Trying ::1...
Connected to pied-piper.net.
Escape character is '^]'.
GET /index.html HTTP/1.0

HTTP/1.1 200 OK
Date: Mon, 14 Apr 2014 15:34:24 GMT
Server: Apache/2.2.22 (Debian)
Last-Modified: Sat, 21 Sep 2013 17:22:33 GMT
ETag: "6a2c55-b1-4e6e8084eb7e3"
Accept-Ranges: bytes
Content-Length: 177
Vary: Accept-Encoding
Connection: close
Content-Type: text/html; charset=UTF-8

<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added,
      yet.</p>
</body></html>
Connection closed by foreign host.
HTTPの仕様についてはRFCを参照されたし。
バージョンRFC
HTTP/1.0RFC 1945
HTTP/1.1RFC 2616

HTML(Hyper Text Markup Language)

HTTPは基本的にHTMLという形式のテキストを転送する。HTMLはマークアップ言語とよばれるコンピュータ言語の一種である。マークアップ言語はタグという文字列を使って、各文章を意味付けできる。例えば<h1>ハロー</h1>は"ハロー"という文字列が文中の最大レベルの見出しであることを示す。タグは基本的にマークしたい文字列を囲うことで意味付けする。以下にサンプルコードを示す。

<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added,
      yet.</p>
</body></html>
<html>-</html>
HTMLの文
<body>-</body>
本文
<h1>-</h1>
見出し レベル1-6(1が最大)
<p>-</p>
段落

HTMLレンダリングエンジン

WebブラウザはHTMLを受け取るとそれを読み込み、解釈してユーザに分かりやすい形で表現する。前述で紹介したWebブラウザの場合、HTMLを視覚的に見やすい形で表現する。前述のサンプルを表現した例が次の通りである。

HTML Rendering Engine
ただし必ずしも視覚的な表現だけとは限らず、視覚障害者用の音声ブラウザのように音声で表現するものもある。このHTMLを取得し、それを解釈してユーザに分かりやすいよう表現するプログラム、または機能をHTMLレンダリングエンジンという。最近のHTMLレンダリングエンジンの多くはHTMLだけでなく、CSS(Cascading Style Sheets)JavaScriptなどを読み込む機能を持つ。
CSS(Cascading Style Sheets)
HTMLの視覚的情報を指定する情報。例えば文字の色や大きさなどがある。
JavaScript
動的なWebサイトを構築するためのプログラミング言語。HTTPのクライアントであるWebブラウザによって読み込まれ、処理される。
HTMLレンダリングエンジンには、次のようなものがある。
HTMLレンダリングエンジンWebブラウザ
Trident
  • Internet Explorer
  • Sleipnir
  • Craving Explorer
Gecko
  • Firefox
  • Epiphany(後にWebKitに移行)
WebKit
  • Google Chrome
  • Safari
HTMLには基本的に視覚的情報がない。また、HTMLレンダリングエンジンによって独自のCSSのプロパティがある。それゆえ、HTMLレンダリングエンジン毎に表示される画面が同じであるとは限らない。

WebKitライブラリ

オープンソースのHTMLレンダリングエンジンであるWebKitを使用したプログラミングのサンプルを以下に示す。

#!/usr/bin/python2.7

import gtk
import webkit

win = gtk.Window()
web = webkit.WebView()
web.open("http://www.google.co.jp")
win.add(web)
win.show_all()
Debian7.10では"python-webkit-dev"というパッケージをインストールすることで、環境を整えることができる。


電子メール(SMTP, POP3)

電子メールとは、コンピュータネットワークを使って、メッセージやファイルなどのデータの送受信を行う手段のこと。電子メールはメールやEメールなどと略される。本稿ではメールと記述する。

メールの機能は、メールサーバメールクライアントによって実装される。

メールクライアント
ユーザはメールクライアントによってメールサービスを受けることができる。メールクライアントの機能は、メールサーバに保存されているメールを受け取ったり、メールサーバに頼んでメールを送ってもらったりする。
メールサーバ
メールの転送は各メールサーバが行う。

メールの送信から受信までの流れ

メールの実装にはアプリケーション層のいくつかのプロトコルが使用される。

プロトコル機能ポート
POP3(Post Office Protocol version3)メールサーバからメールを受け取る(POPとIMAPそれぞれに利点と欠点がある)。tcp/110
IMAP(Internet Message Access Protocol)tcp/143, tcp/220
SMTP(Simple Mail Transfer Protocol)メールを転送する。tcp/25
あるユーザがメールを送信し、別のユーザがメールを確認するまでの流れは次の通りである。
メールサーバは、それぞれドメイン(例:pied-piper.net)を持つ。
  1. メールクライアントはSMTPクライアントとして、自身のドメインのメールサーバのSMTPサーバ機能に対して、送信要求を行う。
  2. SMTPサーバはメールの宛先が自身のドメインであれば、設定されたメールボックスにそれを追加する。それ以外の場合、その宛先ドメインのメールサーバのSMTPサーバ機能に対し、SMTPクライアントとして送信要求を行う。
  3. 受信するユーザは、POP3やIMAPクライアントでメールサーバにアクセスすることで、自身宛に届いたメールを受け取ることができる。

電子メールの仕組み

メールは5つのプログラム(機能)によって構成される。以下にそれらのプログラムとメールの流れを紹介する。

MUA(Mail User Agent)
いわゆるメールクライアントのこと。他にもメーラ、メールリーダなどと呼ばれる。
MTA(Mail Transfer Agent)
メールを別のメールサーバに送信したりMDAに渡したりするもの。
MDA(Mail Delivery Agent)
MTAから受け取ったメールをメールボックスに保存するもの。
MRA(Mail Retrieval Agent)
メールを受信するもの。
MSA(Mail Submission Agent)
MUAとMTAの間で認証などを行うもの。メールの仕組みができたばかりのころはなかったが、現在はセキュリティのためにMSAを間に置くのが主流。

メールクライアント

前述のHTTPのサンプルと同様に、telnetを使ってSMTPとPOP3のサーバにアクセスした例を以下に示す。

SMTP
user% telnet 192.168.1.101 25
Trying 192.168.1.101...
Connected to versus.
Escape character is '^]'.
220 pied-piper.net ESMTP
HELO pied-piper.net
250 pied-piper.net
MAIL FROM: me@pied-piper.net
250 ok
RCPT TO: user@pied-piper.net
250 ok
DATA
354 go ahead
From: me@pied-piper.net
Subject: test

Hello, User
.
250 ok 1397490184 qp 6800
QUIT
221 pied-piper.net
Connection closed by foreign host.
ちなみにSMTPの通信には,DATA以前に入力した情報を使用し,それ以降はメールヘッダのために使用する。 それゆえヘッダ部分は,偽装することも可能であるが,いくつかのSMTPサーバは,そのような怪しいメールの受け取りを拒否する。
POP3
user% telnet 192.168.1.101 110
Trying 192.168.1.101...
Connected to versus.
Escape character is '^]'.
+OK <6798.1397490101@pied-piper.net>
USER user
+OK
PASS hogehoge
+OK
STAT
+OK 125 3714019
LIST
+OK 
1 754
2 1846
3 782
RETR 1
+OK 
Return-Path: <user@pied-piper.net>
Delivered-To: user@pied-piper.net
Received: (qmail 6615 invoked by uid 0); 15 Apr 2014 00:22:33 +0900
Received: from unknown (HELO pied-piper.net) (192.168.1.111)
  by 192.168.1.101 with SMTP; 15 Apr 2014 00:22:33 +0900
From: me@pied-piper.net
Subject: test
Hello, User

.

QUIT
+OK 
Connection closed by foreign host.

SMTP,POP3プログラミング

SMTPやPOP3ライブラリを使用したサンプルコードを以下に示す。

SMTP
#!/usr/bin/python2.7

import smtplib,email.utils
from email.mime.text import MIMEText

FROM = "i@pied-piper.net"
TO = "you@example.pied-piper.net"

msg = MIMEText('This is the body of the message.')
msg['To'] = email.utils.formataddr(('You', TO))
msg['From'] = email.utils.formataddr(('O_Messiaen', FROM))
msg['Subject'] = 'Hello'

server = smtplib.SMTP('192.168.1.101', 25)
server.set_debuglevel(True) # show communication with the server
try:
    server.sendmail(FROM, [TO], msg.as_string())
finally:
    server.quit()
POP3
#!/usr/bin/python2.7

import poplib

pop3 = poplib.POP3("192.168.1.201", 110)
pop3.user("user")
pop3.pass_("hogehoge")
retr = pop3.retr(len(pop3.list()[1]))
"\n".join(retr[1])


セッション層

OSI参照モデル(7階層モデル)では,アプリケーション層とトランスポート層の間に,プレゼンテーション層とセッション層がある。セッション層では,通信の開始時や終了時などに送受信するデータの形式などを規定する。セッション層には例えばSSL(Secure Socket Layer)がある。SSLの詳細は省略するが,それは階層の上位のレイヤに対して暗号化や認証,完全性を提供する。昨今,httpやsmtp,pop3などのアプリケーション層のプロトコルを安全に利用するために,SSLを利用することは珍しくない。

以下にSMTP-SSLの利用例を示す。ここではopensslコマンドを使用する。opensslの機能はさまざまあり,引数としてコマンドを指定する。 以下の例では,s_clientを使用する。telnetやnc(netcat)がTCP(トランスポート層)での通信を提供するソフトウェアと考えるなら,opensslのs_clientコマンドはSSL(セッション層)での通信を提供するソフトウェアと考えれば良い。オプションの詳細については"man s_client"で閲覧できる。

user% openssl s_client -connect smtp.gmail.com:465 -crlf -ign_eof
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEdjCCA16gAwIBAgIIGcMF7jeVMoAwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
   ー中略ー
    Verify return code: 20 (unable to get local issuer certificate)
---
220 mx.google.com ESMTP n7sm9349346pdl.90 - gsmtp
EHLO localhost
250-mx.google.com at your service, [153.198.XXX.XXX]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
認証方法を入力する。
AUTH LOGIN
334 VXNlcm5hbWU6
AUTH LOGINで認証を行う場合,ユーザ名とパスワードをそれぞれbase64でエンコードしたものを使用する。ここでXXXXXXXXXXはユーザ名をエンコードしたもの,YYYYYYYYYYはパスワードをエンコードしたものである。
XXXXXXXXXX
334 UGFzc3dvcmQ6
YYYYYYYYYY
235 2.7.0 Accepted
エンコードは,次のようにbase64コマンドやopensslのencコマンドで行うことができる。また,opensslのencコマンドのマニュアルはs_clientと同様"man enc"で閲覧できる。
  • user% echo "me@gmail.com" | base64 
    bWVAZ21haWwuY29tCg=
  • user% echo "me@gmail.com" | openssl enc -e -base64
    bWVAZ21haWwuY29tCg=
パスワードのエンコードも同様である。XXXXXXXXXXやYYYYYYYYYYの部分にはこの結果を貼り付ければ良い。 これ以降は通常のSMTPと同じように行えば良いが,ここではあえてHTMLメールを送信する例を紹介する。
MAIL From: <me@gmail.com>
250 2.1.0 OK n7sm9349346pdl.90 - gsmtp
RCPT To: <you@gmail.com>
250 2.1.5 OK n7sm9349346pdl.90 - gsmtp
DATA
354  Go ahead n7sm9349346pdl.90 - gsmtp
Subject: html-mail
Mime-Version: 1.0;
Content-Type: text/html; charset="ISO-8859-1";
Content-Transfer-Encoding: 7bit;

<!DOCTYPE HTML>
<html lang="ja-JP">
<body>
<h1>こんにちわ</h1>
</body>
<html>
.
250 2.0.0 OK 1413388691 n7sm9349346pdl.90 - gsmtp
QUIT
221 2.0.0 closing connection n7sm9349346pdl.90 - gsmtp
read:errno=0

一覧