ネットワーク(主にLinux・TCP/IP)メモ


ネットワークに関してLinux(ubuntu18.04)で勉強した際に、わからなかった箇所を備忘録としてここに残しておきます。


# 理論・ワード解説

## サブネット

- 一つのネットワーク内にさらに小さなネットワークを構築する
  - 例えばクラスCのネットワーク内に、ネットワーク部が26bitのネットワーク(例えば192.168.1.65/26)を構築する

# TCP/IPのプロトコル階層モデルの階層ごとのメモ

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

### arp

- IPアドレスからMACアドレスを取得するためのプロトコル
- 最終的に通信を行うにはIPアドレスだけでなくMACアドレスも必要となるため、必ずarp requestという指定したIPアドレスと対応したMACアドレスを取得するためのリクエストを送る必要がある  
  - arpリクエストはブロードキャスト通信で行われる
  - arpリクエストを受信したコンピュータは、指定されたIPアドレスが自分のものの場合はarp replyを返し、そうでない場合は無視する  

- arpで得られたIPアドレスとそれと対応するMACアドレスのペアは、ネットワークインターフェースがもっている対応表に追加される。この対応表における保存期間は数分〜10分程度となる
  - 保存された対応表は「arp -a」コマンドで閲覧可能

## ネットワーク層(インターネット層)

### IP

- 主にIPアドレスによる通信とルーティングを行う。また、送ろうとするパケットのMTUを確認し、必要であればパケットの分割もIPで行う。

### ルーティングテーブル

- 通信を行う機器が、IPパケットをどこへ送出すべきかを記述したリスト。「どのネットワーク/ホスト宛てなら、どのインターフェイス(NIC)を介して、どのルータに送る」かが書かれている

#### デフォルトゲートウェイ

- あるデータを送出する際に、ルーティングテーブルに送信先のIPアドレスがない場合に、送信先として設定されるIPアドレス
  - 主にルータやWLANのアクセスポイントのIPアドレスがこれに当たることが多い。この宛先とのルートのことをデフォルトルートと呼ぶ

### IPフラグメンテーション

- 通信を行うネットワークハードウェアが指定したMTU(1度の転送における最大転送サイズ)よりも大きいサイズのパケットを送る場合に、パケットを分割して送るしくみ

- IPフラグメンテーションが起こっているかどうかは、通信されるパケットのヘッダ情報に書かれている

### ICMP

- IPパケットにヘッダ情報(タイプ・コード・チェックサム)を加えて送られる。主に通信・通知のテストに使われる(例:pingコマンド)

## トランスポート層

## ポート

- ポートとは、マンションにおける部屋のようなもの。16bitの数値になる
  - ポートの値はアプリケーションで決まっている
    - 0~1023 : システムポート
    - 1024~49151 : ユーザポート、or レジスタポート
    - 49152~65535 : ダイナミックポート or プライベートポート

### UDP

- 送受信、データ化けチェック、再送などの処理を行わない転送方法。また、データを受信した際の確認応答も行わない

#### linuxでのUDPサーバの作成方法

- 下記のコマンドでサーバとして起動。 

```
nc -ulnv ip (address) (port番号)
```

- その他オプション
  -  「-u:UDP通信」
  -  「-l:サーバとして動作」
  -  「-n:ipアドレスをDNSで名前解決させないようにする」
  -  「-v:コマンドの表示を詳細にするため」

- 下記でクライアントとして起動
```
nc -u ip (address) (port番号)
```
  
### TCP

- 送信するデータを所定のサイズに小分けし、その小分けされたデータを一つの単位として、送受信、データ化けチェック、再送などの処理を行う。また、データを受信した際に確認応答を必ず返す

- データの順番を明確にするため、シーケンス番号をつける
  - シーケンス番号は「(前のパケットのシーケンス番号)+(MSS)」で計算される

- 文字列を送る際はコントロールビットのフラグにPが含まれる


#### 接続処理

- 接続時は、SYNフラグがオンされたパケットを送ることにより、接続処理を開始する。そのパケットを受信したコンピュータがSYNフラグ、ACKフラグをオンにしたパケットを返す。さらに接続処理を開始したコンピュータがACKフラグをオンにしたパケットを送ることで接続処理が完了する(3WAYハンドシェイク)
    - SYNがたったパケットを送り合うことでお互いにシーケンス番号を同期する(データの順番を管理する)
    - ACK : 該当のbitが立っていることでACKとして認識する
 
- 接続処理時に、データ部分の最大サイズ(MSS)を決める 

#### 切断処理

- 切断時は切断するコンピュータがFINフラグを立てたパケットを送る。FINを送られたコンピュータも、確認応答を送ったのち、FINフラグを立てたパケットを送る

#### ウインドウサイズ

- 受信側が、確認応答を受け取らずに送って良いデータサイズのこと。受信側が決めて、送信側が通知する

#### チェックサム

- チェックサムの計算時は、TCP擬似ヘッダ(IPヘッダに特定のデータがあると仮定し、作成した擬似的なIPヘッダ)を使って計算する
  - このとき、TCP擬似ヘッダのチェックサムのオフセットの場所は0であると仮定する
  - UDPも同様にチェックサムを計算する

## アプリケーション層

### HTTP

- クライアントからリクエストを送り、サーバがレスポンスを返すことによって成り立っている
  - 必ず、１リクエストにつき、１レスポンス

- 基本的にテキストデータでやり取りを行う

- リクエストの際に、ログインIDとパスワードがいる際、最初の通信以降は、webクライアントアプリがログインIDとパスワードを覚えておき、それを付与してリクエストを送る

#### 認証

- あるURLに対してリクエストを送った際に、HTTPの仕組みにより、特定のIDとパスワードの組み合わせ出会った場合のみ、リクエストが実行される仕組み。

- Basic認証とDigest認証がある

##### Basic認証

- IDとパスワードを平文で送る

- 一度認証情報を入れずに、リクエストを送り、401のエラーレスポンスが返ってきた場合に、IDとパスワードを求める
  - レスポンスにサーバが求める認証方法を示すヘッダ(WWW-Authenticateヘッダ)を確認して、それと対応するヘッダ情報とIDとパスワードを入れてリクエストを送り直す

- basic認証のみでHTTPリクエストを送るのはセキュリティに問題があるが、HTTPSで送られる場合は問題なし

##### Digest認証

- ハッシュ関数により生成したダイジェストを利用してIDとパスワードを送る

#### Cookie

- 小容量のクライアント情報を保存しておく仕組み。情報はクライアントアプリケーションが持つ
  - サービスの最終利用日時、閲覧履歴、利用者名など

- 保存するのにはHTTPヘッダの「Set-Cookie」を用いる

- HTTPリクエストを送る際に、クライアントはリクエストにヘッダ「Cookie」と保存している情報を追加しリクエストを送る

#### linuxでのhttpリクエストの使用方法

- 使用するポートナンバーはTCPの80。下記のような形でhttpリクエストを発行できる
```
echo -en "GET / HTTP/1.0¥r¥n¥r¥n" | nc 127.0.0.1 80
curl -X GET -D - http://127.0.0.1
```

- また、サーバもpython3があれば下記のようにしてサーバを起動できる
```
sudo python3 -m http.server -b 127.0.0.1 80  
```
このとき、アクセス時に表示されるページはカレントディレクトリ上のindex.htmlとなる

### DNS

- DNSサーバーは外部のものを使うことがよくある。例えばgoogleの(8.8.8.8)。どのDNSを用いるかは、PC上のリゾルバが決定する

- ローカル上では、linuxの場合「/etc/hosts」ファイル内でDNS解決用のリストが記載してある

- 使用するポートはUDPの53番ポート

#### 名前解決の手順

1. スタブリゾルバにリクエストを送る
2. スタブリゾルバが、キャッシュサーバにリクエストを送る
3. キャッシュサーバはルートDNSサーバに問い合わせを行う(キャッシュに情報がなければ)
4. キャッシュサーバはルートDNSサーバからの返答で指定されたDNSサーバへ問い合わせる
5. キャッシュサーバは指定されたDNSサーバから、別のDNSサーバを指定された場合は、そのDNSサーバへ問い合わせる
6. リクエストのURLに対応するIPアドレスが取得できるまで、4〜5を繰り返す

### DHCP

- 役割としては
  - ip アドレスの割り振り
  - ルーティングテーブルの作成
  - 名前解決に利用するネームサーバの指定
    を行う

- 通信方式はサーバ・クライアント方式。主にDHCPサーバの機能をルータが担うことが多い

- 使用するポートはUDPの67番ポート

### NAT(NAPT)

- ローカルアドレスとグローバルアドレスの変換を行う

- iptablesコマンドを用いてlinuxでは使用

## 暗号化

- 何らかの方法で、ある元の文字列(平文)を読解不能な文字列(暗号文)に書き換えること

### 暗号鍵

- 暗号化を行う際に使用される、平文と一緒に暗号化されるデータのこと
  - 同じ平文と同じ変換ルール(暗号アルゴリズム)であっても、鍵が違うことにより暗号文が異なるように作られ、復号時も同じ鍵がないと復号できない仕組みになっていることにより、盗聴などを防ぐ

### 共通鍵暗号方式

- 復号と暗号化に同じ鍵を使うもの。計算量も小さく、多くの場面で用いられる

- 鍵をどうやって共有するかが問題となる
  - 鍵の引き渡しには公開鍵暗号を使う

### 公開鍵暗号方式

- 復号する人が復号用の鍵(秘密鍵)を用意し、それと暗号化に使用する対になる鍵(公開鍵)を用いる
  - 鍵のやり取りを行う必要がなくなる。ただし、公開鍵が正しいものであることを確認する必要がある

- 計算量が非常に多く、処理が重くなる恐れが高い
  - 公開鍵暗号方式で共通鍵暗号方式の鍵を送り、実際の通信では共通鍵を使った共通鍵暗号方式を用いる(この考え方はSSL/TLSでも用いられている)

#### PKI

- 公開鍵が正しいものであるか確認するための仕組み
  - 信頼できる第三者(認証局(CA))が電子署名によって、所有者と改竄されていないことを担保する

- 社会的に信頼のあり、認証を最終的に行う決め手になる認証局(ルート認証局)があり、そのルート認証局が認証した認証局(中間認証局)による電子署名があれば問題ないと考える方式
  - ルート認証局が絶対的に信頼できるものであり、そのルート認証局が信頼している中間認証局が発行した電子署名があれば問題ないと考える

#### SSL/TLSでの暗号化

- webサーバ側で、クライアントから送られてきた電子署名を確認し、問題がなければ電子署名と共に送られてきた公開鍵を用いて、暗号化通信を行う

### ハッシュ関数

- ある情報を与えると、その情報を基にした、一定の長さの文字列(要約値)に変換する関数
  - 与えられる情報が少しでも違うと変換後の要約値が変わるため、改竄検出に用いられる

- ハッシュ関数にはMD5, SHA-1, SHA-2, SHA-256,SHA-512などがある

#### ハッシュ関数による電子署名

- 送信者が秘密鍵を使用して暗号化し、受信者が公開鍵を使用して復号化する公開鍵暗号方式を用いることで改竄を検出する

- 以下のような手順で電子署名の改竄検出を行う

1. 送信する文書をハッシュ関数により要約値を算出する
2. 要約値を送信者の秘密鍵で暗号化する
3. 文書と、暗号化した要約値を合わせて送信する
4. 受信者は公開鍵により、要約値を復号化する
5. 受信した文書をハッシュ関数に要約値に変化し、受信した要約値と同じかを確かめる

# その他

- 127.0.0.1   :   ループバックIPアドレス。自身とネットワークの通信を行いたいときに用いる

- tcpdump   :   コンピュータ上を流れるtcp/ipのデータをキャプチャ(sniffing)するためコマンド

- ルーティングテーブルがないと、外部への通信はできない
  - ルーティングテーブルを見るには、「ip route show」
  - 外部への通信を行うには、デフォルトルートが必要
    - デフォルトルートとは、他の宛先と一致しない場合に使われるルーティングエントリ