curlコマンドからネットワークを理解する 第二章: curlを追え! パケットキャプチャとシステムコールからcurlを見る

# index

つながっているか微妙ですが、一章は[こちら](https://qiita.com/Kohei909Otsuka/items/39a03b44e370f848a07a)

下記の順番で説明します。

- 0節: 物理アドレスと論理アドレス
- 1節: 一番シンプルなLAN(L2 スイッチ: スイッチングハブ)
- 2節: LAN同士をつなぐ(L3 スイッチ: ルーター)
- 3節: curlコマンドを追え: パケットキャプチャ編
- 4節: curlコマンドを追え: システムコール編

0節では、前提知識としてネットワークの世界における2つのアドレス`MACアドレス`と`IPアドレス`を説明します。

1節では、シンプルなLANを通じて、
インターネットの構成単位である`LAN`とはどんなものかを説明するパートです。
複雑なものは、小さい単位でみていくことで理解しやすくなります。

2節では、1節で出てきたLAN同士をつなぎ合わせネットワークを作ります。
このLAN同士をつなぐ役割がL3 スイッチです。
これによって、多数のLANの集合がインターネットになっていることが理解できます。

3節では、パケットキャプチャを通じてcurlコマンドの挙動を追っていきます。

4節では、システムコールを通じてcurlコマンドの挙動を追っていきます。

ネットワークの基本を一通り学んでみて、感じていることが2つあります。

一つ目は、1つ1つの事が色んな観点から觀れることです。
二つ目は、一個学ぶと新たなが疑問がでてくることです。

たとえば、IPプロトコルというものを理解しようとしたときに、それは色んな観点から観れます。
この多面性があるためにネットワークについての記事や本を1つ読んだくらいでは、いまいち腹落ちできません。

また、`ポートってなんだ?`や`ソケットってなんだ?`などと、以前からなんとなく使ってきた言葉が、
本当の意味で理解できていないことに気づいて深みにハマっていきます。

![explain_in_many_ways.jpg](https://qiita-image-store.s3.amazonaws.com/0/106693/5338d92d-27ee-67d8-25a1-69f90d3e2daa.jpeg)

# 0節: 物理アドレスと論理アドレス

郵便とおなじく、誰かとコミュニティケーションを取ろうとしたら、その場所を表すアドレスが必要になります。
ネットワークの世界でアドレスといったら、MACアドレスとIPアドレスしかありません。

|名前|論理/物理|用途/意味|例|
|---|---|---|---|
|MACアドレス|物理|あるパケットが次にどこにいくのかを表す|34:36:3b:77:6f:82|
|IPアドレス|論理|あるパケットが最終的にどこにいくのかを表す|192.0.2.0/24|

パケットがローカルを出て、目的地に到着するまでに、通常いくつかのネットワーク機器(L2 スイッチやL3 スイッチなど)を経由して運ばれます。
下記のスクショは`traceroute`コマンドで自宅からFaceBookまでの経路を表示した例です。

![traceroute-2.png](https://qiita-image-store.s3.amazonaws.com/0/106693/a191aa61-ce9c-9a6e-f5e2-64707c232d60.png)

スタート地点S--中継地点A--中継地点B--中継地点C...--ゴール地点G、とパケットをバケツリレーするときに、
各々の`--`の間の行き先を決めるのがMACアドレスです。
スタート地点Sから、ゴール地点Gの行き先を決めるのがIPアドレスです。
次のアドレスを表現するMACアドレスはバケツリレーの間、変わり続けます。一方で、最終地点を表現するIPアドレスは不変です。

MACアドレスはハードウェアに直接刻印されていて、そのハードが製造されたときにはすでに一意の値がその機器にふられています。なので、同じ機器を使っているかぎり不変です。これが物理アドレス。

IPアドレスはソフトウェア(OS)が管理しており、ネットワーク管理者によって静的に割当られるときもあれば、[DHCP](http://www.infraexpert.com/study/tcpip13.html)で動的に割当られるときもあります。なので、自分のPCのIPアドレスが今日と明日で同じということは保証できません。これが論理アドレス。

参考までに下記のような写真も載せておきます。

自宅のルーター(ONUにルーター機能も内蔵)にはMACアドレスが刻印されている。
![route_mac_address.jpg](https://qiita-image-store.s3.amazonaws.com/0/106693/7759dd07-b31a-b28b-0a03-3ca2c325e9a3.jpeg)

自分のPCのwifiのネットワークインターフェースにはMACアドレスが刻印されている。
![local_mac_address.png](https://qiita-image-store.s3.amazonaws.com/0/106693/b9f51ab3-2025-7ffc-7c80-0b1afd8c9e8e.png)

自分のPCには、DHCPによって動的にIPが割り振らている。
![local_ip_address.png](https://qiita-image-store.s3.amazonaws.com/0/106693/97c20d14-f1b8-8a07-8908-272ddcbee66a.png)

# 1節: 一番シンプルなLAN(L2 スイッチ: スイッチングハブ)

1節と2節では、下の図の部分をはなします。

![two_main_layer.png](https://qiita-image-store.s3.amazonaws.com/0/106693/276ff972-bd05-8dea-948f-8fbf8b8341a5.png)

OSI参照モデルでいう、Layer 2と Layer 3を理解することで、どうやってコミュニティケーションを実現しているのかはわかります。
その土台が分かってから、それより上のレイヤーであるTCPや、UDP, HTTPなどを土台に乗せる感じで理解したほうが分かりやすいです。
余談ですが、Layer 1はLANケーブルのコネクタの形状とか、そういうハード面を定義しているので、Layer 2からでいいと思います。

1章の繰り返しになりますが、大切なのは`上のレイヤーは下のレイヤーに依存している`ということです。
`下のレイヤーは上のレイヤーについて知らない`、と言い換えることもできます。

大切なところだと思うので例をあげて説明します。

たとえばHTTPでhtmlを取得するときに、htmlのサイズが大きい場合、パケットは分割して送信されます(実際にTCPが分割している単位はパケットではなくセグメントと呼ばれる)。
このパケットの分割/順番などを管理しているのがTCPプロトコルです。
つまり上位のTCPーの視点から観れば、パケットの`順番`というのは確かに存在しますし、それはとても大切な情報です。

しかし下位のIPの観点からみれば、`順番`なんてものはまったく知りません。どうでもいいことです。
パケットを分割しているのはTCPであって、IPはそのパケットを最終目的地に到達させることだけを考えます。
TCPにとっては連番がついて関係のあるように見えるパケット1とパケット2は、IPからみれば意味としてはまったく同じものに見えます。

この関係性はそのまま各レイヤーが、何のヘッダーを読み込み/書き込みするのか、ということに現れています。

前置が長くなりました、本題のL2 スイッチに進みましょう。

L2 スイッチ(Layer 2 Switch)とは、こんな感じのやつです。
![layer2switch.jpeg](https://qiita-image-store.s3.amazonaws.com/0/106693/1fcdd374-7fe1-ea32-5b7b-2a4b5b5d73b8.jpeg)


自分の部屋にある3台のコンピュータでコミュニティケーションしたい、という一番シンプルな場合を考えたときの図です。

![L2_switch.jpg](https://qiita-image-store.s3.amazonaws.com/0/106693/9d70b8b4-91fc-88f6-7baf-ec399129cc45.jpeg)

上の例だと、PC AはPC BのMACアドレスを最初から分かっているように見えますが、それは間違えです。
インターネット層からIPパケットをネットワークインターフェース層が受け取ったときには`宛先IPアドレス`しかありません。なのでこの宛先IPアドレスをもつノードのMACアドレスを知る必要があります。このとき使われるプロトコルがARP([Address Resolution Protocol](http://www.infraexpert.com/study/tcpip2.html))です。

ローカルにキャッシュされたARPテーブルの例
![arp-2.png](https://qiita-image-store.s3.amazonaws.com/0/106693/f0e5dcb7-b991-68fb-19ab-48b37c53bb1e.png)


# 2節: LAN同士をつなぐ(L3 スイッチ: ルーター)

前節でMACアドレスをもとに、同一のネットワーク上でのフレームのやりとりをL2 スイッチを使って実現できました。
ですが、このままでは、他のネットワークへアクセスすることができません。

ネットワークとネットワークをつなぎ、IPアドレスをもとにパケットを転送する装置をL3 スイッチといいます。

無線ルーターの例
![wifi-router-007b.jpg](https://qiita-image-store.s3.amazonaws.com/0/106693/9a54412b-71df-85dd-bf6d-5a841148f1a6.jpeg)


自分の部屋の3台がつながったネットワークと、隣の部屋で3台つながったネットワークをつなぐ。

![L3_switch.jpg](https://qiita-image-store.s3.amazonaws.com/0/106693/c9b3a4f8-ed58-9310-c551-cdce93018e2e.jpeg)

もちろん、ルーティングテーブルをそもそもどう作るのかとか、ルーティングテーブルからどう経路を選ぶのかとか、
細かい話はいっぱいあるのですが、だいたい上の図ようなことを抑えておけばいいかなと。

# 3節: curlコマンドを追え: パケットキャプチャ編

この実験をするためにわざわざサーバレンタルして、ドメインまでとりました(笑)
次の記事でSSLの仕組みを書こうと思っていたので、まぁいいでしょう!

下記の図のような構成です。
![architect.jpg](https://qiita-image-store.s3.amazonaws.com/0/106693/81f23899-3c3f-78a5-7b68-02cb99f495d5.jpeg)

wiresharkでキャプチャするとこんな感じになりました。

`curl http://kohei-experimental.site`のとき

![curl_tcp-2.png](https://qiita-image-store.s3.amazonaws.com/0/106693/55c1e92b-74ba-3c0f-96ec-3418c33388e9.png)

DNSをみせたいがために`nslookup kohei-experimental.site`を打つ

![curl_dns.png](https://qiita-image-store.s3.amazonaws.com/0/106693/b60db11e-3acc-773e-e524-a8ffbec33a1d.png)

ARPもやり取りされてます。
![curl_arp.png](https://qiita-image-store.s3.amazonaws.com/0/106693/58eab1bb-b3e3-758f-bd1a-2ad5daecccc1.png)



# 4節: curlコマンドを追え: システムコール編

## クライアント側でシステムコールをみてみる

[こちらの記事](https://qiita.com/dhomma/items/28e900978b3824cfe9af)で詳細に説明されています。

結果はこんな感じ。

`strace -e trace=network curl -s -o /dev/null http://kohei-experimental.site`

![client_strace_org.png](https://qiita-image-store.s3.amazonaws.com/0/106693/7ce9224c-736f-3865-b1c9-dd591578f436.png)

ソケットソケットってなんやねん!となるのですが、ソケットってなんですか?という質問は、
プロセスってなんですか?という質問と似ています。
両方ともOS上の概念なので、理解するのが若干難しいです。

こちらの説明がわかりやすい。
> 昔々、カリフォルニア大学バークレイ校というところで、AT&Tのベル研が開発 したオペレーティングシステムであるUNIXを拡張しようという研究が行われ、 BSD UNIXという名称で、便利で高機能のUNIXが開発されておりました。その研 究の一つにUNIXから通信ネットワーク、特にTCP/IPを利用した通信プログラム を容易にする工夫として開発されたのがソケットです。
UNIXでは、キーボード、画面などのデータを読んだり、書き込む対象は何でも ファイルとして扱ってしまおうという哲学があります。そこで、コンピュータ 間通信もファイルへの読み書きとしてプログラミングができないかということ を目標にして開発されました。このため、ファイルの入出力プログラムの流れ である、ファイルのオープン・データの書き出し／読み出し・ファイルクロー ズに乗っ取り、UNIXにおける初期のTCP/IPの利用では /dev/tcp というファイ ルへのオープン・読み／書き・クローズがそのまま通信になるようにデザイン されていました。しかし、BSD UNIXを開発しているグループは、TCP/IPの多様 な通信形態を扱うには、オープン・読み／書き・クローズの流れだけでは困難 であると考え、代わりに生み出されたのがソケットです。ソケットは、ファイ ルオープンに相当する操作が通常のファイルより複雑ですが、より高度が通信 が可能であり、さらにオープン後はファイルへの読み書きと同じスタイルで通 信が可能になります。
ソケットはその取り扱いの容易さから、その後、UNIXの本流であるAT&TのUNIX にも採り入れらましたし、他のオペレーティングシステムにも徐々に利用でき るようになりました。特に、初期のインターネットでは接続されているコンピュー タの多くがUNIXオペレーティングシステムを利用していたため、インターネッ ト用のソフトウェアの殆どはソケットを利用して開発されました。この結果、 他のオペレーティングシステムが、これらのインターネット用のソフトウェア を利用するには、そのオペレーティングシステムでもソケット機能を提供して PCいる必要が生じ、大型計算機（メインフレーム）から、WindowsやMacOSなどの 用のオペレーティングシステムまでもがソケット機能を提供しています。 このため、ソケットの使い方さえ知っていれば、インターネットに代表される TCP/IPを基礎とした通信ネットワーク用のプログラミングができるようになり ますし、ソケットを利用したプログラムが書けないと、インターネット用のプ ログラムは書けないといっても過言ではありません。（コラム終わり）

`Everything is a file`というUNIXの設計思想を理解すると、なんとなくわかった気になれます。
[この動画](https://www.youtube.com/watch?v=dDwXnB6XeiA)とか分かりやすいです。

## サーバー側でシステムコールをみてみる

nginxのwoker processを指定して`strace`を実行しています。

![server_strace_org.png](https://qiita-image-store.s3.amazonaws.com/0/106693/fe365ca5-7ab3-cbb1-85d4-fd4b6f377044.png)

C言語まったく読めませんが、MAN page頼りになんとなく、読んでみると


`accept4`でソケットへの接続を受ける。 =>
  この接続でつかうソケットを表すファイルディスクリプタの`3`が返る

`recvfrom`でソケットからメッセージの読み込み =>
  GETリクエストがバッファに保存され、読み込んだメッセージの長さ87が返る

`open`でindex.htmlを開く => ファイルディスクリプタの`11`が返る

`writev`で`3`で示されるソケットにHTTP headerを書き込む

`sendfile`で`11`で示されるindex.htmlの内容を`3`で示されるソケットへコピーしHTTP bodyを書き込む

`write`で、これは多分ログの書き込み

`close(11)`でindex.htmlを閉じる

`close(3)`でソケットを閉じる

# まとめ

まだLV 1感がすごいですが、全体像をイメージできたのと、ネットワーク関連の広さと深さを認識できて、よかったです。
普段当たり前につかってるネットですが、その動作原理をみると、すげー!!!!って感動しました。

自宅から電波になってONUに入って、プロバイダのルーティング回されて、海底ケーブルの光回線通って、でまたどこかの国のプロバイダのルーティング回されて、そして同じように帰ってくる。
物理的には電気や電波や光など色んなものに姿を変えながら、たくさんのパケットが、とんでもなく広い範囲で、なんども経由されながら交通している様をイメージすると、やっぱり感動しました。すごいなって(笑)

# 参考文献

[インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門](https://www.amazon.co.jp/gp/product/4797373512/ref=oh_aui_detailpage_o08_s00?ie=UTF8&psc=1)
[ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識](https://www.amazon.co.jp/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AF%E3%81%AA%E3%81%9C%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8B%E3%81%AE%E3%81%8B-%E7%AC%AC2%E7%89%88-%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84TCP-IP%E3%80%81LAN%E3%80%81%E5%85%89%E3%83%95%E3%82%A1%E3%82%A4%E3%83%90%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E6%88%B8%E6%A0%B9/dp/4822283119/ref=sr_1_1?ie=UTF8&qid=1524129584&sr=8-1&keywords=%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AF)
[マスタリングTCP/IP 入門編　第5版](https://www.amazon.co.jp/gp/product/B00MLUGZKG/ref=oh_aui_d_detailpage_o08_?ie=UTF8&psc=1)
[Eli The Computer Guy, Understanding Switches](https://www.youtube.com/watch?v=9yYqNqTNnqI&t=1186s)
[ネットワークエンジニアとして](http://www.infraexpert.com/)
[Linuxカーネルの基本機能](http://tech.nikkeibp.co.jp/it/article/COLUMN/20080501/300463/)