クライアントからサーバーに対してネットワークが繋がらない場合の確認方法メモ

クライアントからサーバーに対してネットワークが繋がらないという場合の各レイヤでの確認方法メモ。

# 参考

+ [パケットキャプチャ入門 第3版～LANアナライザWireshark活用術～ [Kindle版]](http://www.amazon.co.jp/%E3%83%91%E3%82%B1%E3%83%83%E3%83%88%E3%82%AD%E3%83%A3%E3%83%97%E3%83%81%E3%83%A3%E5%85%A5%E9%96%80-%E7%AC%AC3%E7%89%88%EF%BD%9ELAN%E3%82%A2%E3%83%8A%E3%83%A9%E3%82%A4%E3%82%B6Wireshark%E6%B4%BB%E7%94%A8%E8%A1%93%EF%BD%9E-%E7%AB%B9%E4%B8%8B%E6%81%B5-ebook/dp/B011HPWTNC/ref=sr_1_1?s=digital-text&ie=UTF8&qid=1460554919&sr=1-1&keywords=wireshark)
+ [マスタリングTCP/IP 入門編 第5版](https://estore.ohmsha.co.jp/titles/978427406876P)

# 確認OS

+ Amazon Linux AMI 2016.03.0

# そもそもネットワークでのレイヤとは

OSI参照モデルやTCP/IPモデルなどあるかと思います。

[TCP/IP](http://www.infraexpert.com/study/tcpip.html)

以下にTCP/IPモデルを書きます。

| TCP/IPレイヤ| プロトコル例 |指定するもの|機能|
|:-----------|:------------|:------------|:------------|
|アプリケーション層|HTTP|URI、メソッドなど|アプリケーション間による通信|
|トランスポート層|TCP,UDP|ポート番号|プロセス間での通信。確実な通信の確立(エラーチェックや再送)|
|インターネット層|IP,ICMP|IPアドレス|ルーターを経由し、対象のIPアドレスまでのルーティング|
| ネットワークインターフェース層|EthernetⅡ|MACアドレス|LANケーブルで接続した対象との通信|

アプリケーション層が上位のレイヤでネットワークインターフェース層が下位のレイヤとなります。
パケット送信者は上位レイヤから下位レイヤにかけてヘッダとデータを追加し、受信者は下位レイヤから上位レイヤに向けてヘッダとデータの情報を確認します。

以下に別ネットワークのサーバーに対してパケットを送信する場合の実施内容について記載します。

1.送信元(自分のPCなど)

+ アプリケーション層のヘッダ、データを付与
+ トランスポート層のヘッダ、データを付与
+ インターネット層のヘッダ、データを付与
+ ネットワークインターフェース層のヘッダ、データを付与

2.別のネットワークへの通信の場合にはルーティング(インターネット層によって)N個のルータを経由します。

3.最終的に指定されたIPアドレスへ辿り着いた場合には対象PCでは下から順番に解析

+ ネットワークインターフェース層のヘッダ、データを確認
+ インターネット層のデータとヘッダ、データを確認
+ トランスポート層のヘッダ、データを確認
+ アプリケーション層のデータとヘッダ、データを確認

上記流れを意識すると解析の際にどこで問題になっているかの参考になるかと思います。

では以下より各階層での確認方法について記載します。

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

この層では物理的な線(LANケーブルなど)を使い、LANカードのMACアドレスによる指定で通信を行います。

物理的な部分については以下の問題がある可能性があるかと思います。

+ LANケーブルの断線
+ LANケーブルの未接続

上記問題がある場合、電気信号のビット列が送信先に送信できず、通信が出来ません。

上記に対してチェックがどのようにできるか考えてみました。

+ 通信が可能なPCで使っているLANケーブルを借りて利用する(LANケーブルによる問題か否かの判定)
+ LANケーブルテスターを使って断線の確認

LANケーブルテスターなるものは初めて知ったのですが、ネットワーク屋さんだと有名なのかもしれません。。

また、例えば接続機器を交換した場合にARPキャッシュテーブルの内容が古く、送信先MACアドレスが変わってしまうことで通信ができない場合もあると思います。

別ネットワークへの通信を想定し、確認してみます。

```bash
# デフォルトゲートウェイを確認
$ip route show all
default via 172.31.16.1 dev eth0
169.254.169.254 dev eth0
172.31.16.0/20 dev eth0  proto kernel  scope link  src 172.31.23.12

# ARPリクエストによって172.31.16.1のMACアドレスを取得してみる
$sudo arping 172.31.16.1
ARPING 172.31.16.1 from 172.31.23.12 eth0
Unicast reply from 172.31.16.1 [06:8F:4C:8A:08:F1]  0.851ms
Unicast reply from 172.31.16.1 [06:8F:4C:8A:08:F1]  0.765ms
Unicast reply from 172.31.16.1 [06:8F:4C:8A:08:F1]  0.778ms
Unicast reply from 172.31.16.1 [06:8F:4C:8A:08:F1]  0.772ms
^CSent 4 probes (1 broadcast(s))
Received 4 response(s)

# ARPキャッシュテーブルの確認.MACアドレスが同じなので問題無い
$ip neigh show
172.31.16.1 dev eth0 lladdr 06:8f:4c:8a:08:f1 REACHABLE
```

`ip route`コマンドによるルーティングテーブルを見ると別ネットワークへの通信時にはデフォルトゲートウェイに設定されたIPアドレス172.31.16.1へ通信する事が分かります。
つまり、別ネットワークへの通信時には172.31.16.1の機器のMACアドレスに対して通信を行います。

既に自身のARPキャッシュテーブルにIPアドレス、MACアドレスの対応表があればそのMACアドレスを利用します。
ARPキャッシュテーブルにないもしくは期限が切れた場合には「ARPブロードキャストパケット」によって同一LAN内にパケットをブロードキャストします。パケットを受信したPCで自分が対象のIPアドレスだった場合には自身のMACアドレスを送信元に「ARP応答ユニキャストパケット」として送信します。
上記では`arping`というコマンドを使ってARPブロードキャストパケットを送信し、IPアドレスからMACアドレスを引いてアドレス解決を行っています。

例えばデフォルトゲートウェイに設定された機器が故障などして交換した場合、IPアドレスは同じでもMACアドレスが変わる場合があります。その場合にはARPキャッシュテーブルの内容と実際との齟齬が出てしまい、通信できないという可能性もあるかと思います。
その場合、`ip neighbor`コマンドによってデフォルトゲートウェイのARPキャッシュテーブルを削除して内容の更新ができれば問題なく通信できるようになるかと思います。

# インターネット層

ネットワーク層はIPアドレスの指定によって宛先を指定しています。

ネットワーク層での問題点としては以下などが考えられるでしょうか。

+ そもそも指定したIPアドレスが間違っている
+ 途中のルーターでの故障やルーティングの誤りで対象サーバーまでパケットが届かない
+ 受信先ネットワークでのファイアウォールや対象PCでのiptablesなどによるフィルタリング

などなど。

上記に対しての疎通確認は`ping`コマンドを行って確認してみます。

以下では外部ネットワークの`www.yahoo.co.jp`へのインターネット層の疎通確認を行っています。

```bash
$ping www.yahoo.co.jp
PING www.g.yahoo.co.jp (118.151.235.191) 56(84) bytes of data.
64 bytes from f1.top.vip.bbt.yahoo.co.jp (118.151.235.191): icmp_seq=1 ttl=57 time=1.97 ms
64 bytes from f1.top.vip.bbt.yahoo.co.jp (118.151.235.191): icmp_seq=2 ttl=57 time=1.79 ms
^C
--- www.g.yahoo.co.jp ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1846ms
rtt min/avg/max/mdev = 1.794/1.882/1.970/0.088 ms
```

パケットが返却されているのでインターネット層での接続は問題なさそうです。
ただ、`ping`コマンドはICMPプロトコルを使っている点については注意する必要があります。
サーバーによってはICMPプロトコルを拒否する設定を行っており、その場合にはTCPでは接続できるがICMPではできないという可能性もあります。

上記のような場合には`traceroute`コマンドを使ってTCP/UDPプロトコルによる通信確認を行います。(TCP/UDPはトランスポート層のプロトコルですが、大抵の場合、上記いずれかは利用するという前提で)

以下で実際にやってみます。

```bash
# -Iオプションを指定することでICMPプロトコルを利用して対象ホストへの接続確認
$sudo traceroute -I www.yahoo.co.jp
traceroute to www.yahoo.co.jp (182.22.70.250), 30 hops max, 60 byte packets
 1  ec2-175-41-192-132.ap-northeast-1.compute.amazonaws.com (175.41.192.132)  1.105 ms  1.098 ms  1.098 ms
 2  27.0.0.172 (27.0.0.172)  2.419 ms  2.514 ms  3.362 ms
 3  27.0.0.154 (27.0.0.154)  1.970 ms  1.974 ms  1.974 ms
 4  52.95.30.133 (52.95.30.133)  3.116 ms  3.171 ms  3.237 ms
 5  52.95.30.196 (52.95.30.196)  2.514 ms  2.697 ms  2.696 ms
 6  23816.tyo.equinix.com (203.190.230.58)  2.742 ms *  2.051 ms
 7  * * *
 8  * 118.151.224.250 (118.151.224.250)  4.820 ms  4.859 ms
 9  182.22.34.210 (182.22.34.210)  9.167 ms  9.208 ms  9.342 ms
10  f9.top.vip.ssk.yahoo.co.jp (182.22.70.250)  5.271 ms  5.272 ms  5.270 ms

# -Tオプションを指定することでTCPプロトコルを利用して対象ホストへの接続確認
$sudo traceroute -T www.yahoo.co.jp
traceroute to www.yahoo.co.jp (183.79.123.210), 30 hops max, 60 byte packets
 1  ec2-175-41-192-132.ap-northeast-1.compute.amazonaws.com (175.41.192.132)  1.225 ms  1.222 ms  1.216 ms
 2  27.0.0.210 (27.0.0.210)  2.924 ms  3.101 ms  3.121 ms
 3  54.239.52.174 (54.239.52.174)  3.020 ms 54.239.52.166 (54.239.52.166)  3.359 ms 54.239.52.174 (54.239.52.174)  6.687 ms
 4  54.239.52.140 (54.239.52.140)  10.434 ms 27.0.0.248 (27.0.0.248)  9.654 ms *
 5  * * *
 6  54.239.53.92 (54.239.53.92)  10.413 ms * *
 7  * 210.173.178.44 (210.173.178.44)  8.719 ms  8.786 ms
 8  124.83.228.221 (124.83.228.221)  22.239 ms  8.903 ms  8.767 ms
 9  124.83.252.242 (124.83.252.242)  16.590 ms  16.641 ms  16.549 ms
10  114.111.65.46 (114.111.65.46)  17.051 ms  17.395 ms  17.457 ms
11  114.111.65.2 (114.111.65.2)  17.034 ms  17.043 ms  17.127 ms
12  183.79.123.250 (183.79.123.250)  17.020 ms f8.top.vip.kks.yahoo.co.jp (183.79.123.210)  17.025 ms 183.79.123.250 (183.79.123.250)  16.416 ms

# オプション指定なしでUDPプロトコルによる対象ホストへの接続確認
$traceroute www.yahoo.co.jp
traceroute to www.yahoo.co.jp (183.79.75.234), 30 hops max, 60 byte packets
 1  ec2-175-41-192-132.ap-northeast-1.compute.amazonaws.com (175.41.192.132)  1.115 ms  1.110 ms  1.105 ms
 2  27.0.0.210 (27.0.0.210)  2.662 ms  2.839 ms  2.862 ms
 3  54.239.52.166 (54.239.52.166)  2.897 ms  2.978 ms 54.239.52.174 (54.239.52.174)  3.014 ms
 4  54.239.52.140 (54.239.52.140)  9.600 ms  9.873 ms  9.929 ms
 5  54.239.53.39 (54.239.53.39)  12.721 ms 54.239.53.21 (54.239.53.21)  10.524 ms 54.239.53.13 (54.239.53.13)  16.881 ms
 6  54.239.53.92 (54.239.53.92)  9.753 ms 54.239.53.98 (54.239.53.98)  9.085 ms 54.239.53.102 (54.239.53.102)  8.768 ms
 7  210.173.178.44 (210.173.178.44)  8.826 ms  8.731 ms  8.742 ms
 8  124.83.228.221 (124.83.228.221)  11.063 ms  10.914 ms  11.056 ms
 9  124.83.252.242 (124.83.252.242)  16.784 ms  16.843 ms  16.923 ms
10  114.111.65.46 (114.111.65.46)  17.292 ms  17.341 ms  17.470 ms
11  * * *
12  * * *
13  * * *
14  * * *
15  * * *
16  * * *
17  * * *
18  * * *
19  * * *
20  * * *
21  * * *
22  * * *
23  * * *
24  * * *
25  * * *
26  * * *
27  * * *
28  * * *
29  * * *
```

TCP及びICMPプロトコルでの通信は可能ですが、UDPプロトコルによる通信はできないことが分かりました。(正確にはTTLが0になってしまっている)
例えば接続先へHTTPによる通信がしたい場合にはTCPプロトコルを使うので、tracerouteコマンドでTCPによる通信確認ができればOKです。

1点補足としては上記で確認したように`www.yahoo.co.jp`というように通信先をドメインで指定した場合にはDNSを使って名前解決を行っています。DNSによる名前解決に失敗する場合も当然あるので問題をより明確にしたい場合には事前にドメインからIPアドレスを取得し、pingやtracerouteで指定する時はIPアドレスを利用するというのもやってみると良いかもしれません。

# トランスポート層

トランスポート層ではポート番号を指定して対象に通信します。

+ そもそも指定したポート番号が間違っている
+ 指定したポート番号を受け付けるプロセスが起動していない
+ 受信先ネットワークでのファイアウォールや対象PCでのiptablesなどによるフィルタリング

などでしょうか。

今回の通信は80番ポートなので対象IPアドレスの80番ポートに対して通信が出来るか確認します。
確認には`telnet`コマンドや先ほども利用した`tracerouteコマンド`または`nc`コマンドを使います。

```bash
# 接続確立時
$telnet www.yahoo.co.jp 80
Trying 183.79.43.200...
Connected to www.yahoo.co.jp.
Escape character is '^]'.

# 接続失敗時.接続できない
telnet www.yahoo.co.jp 3066
Trying 183.79.11.230...

```

また、同じように`nc`コマンドで同様のことが出来ます。

```bash
# OK
$nc -w1 www.yahoo.co.jp 80
$ echo $?
0

# NG
$nc -w1 www.yahoo.co.jp 3066
$ echo $?
1
```

ncコマンドではデフォルトでTCPプロトコルによる通信確認をしますが、オプション指定でUDPによる通信確認もできるようです。

# アプリケーション層

HTTPで言えば、URLのパスや利用するメソッド(GET,POST,HEADなど)を指定することになると思います。

HTTPプロトコルだと以下の問題点がある可能性があるでしょうか。

+ サーバーエラー(HTTPステータスコード500)
+ 対象ファイルなし(HTTPステーコード404)
+  リクエスト不正(HTTPステータスコード400)

などでしょうか。

例えばYahooのニュースの一覧を見る場合には

http://news.yahoo.co.jp/topics

というURLをGETメソッドでリクエストします。

HTTPについての接続確認はcurlやwgetコマンドを使います

```bash
# GETメソッドでアクセス
$curl http://news.yahoo.co.jp/topics
```

オプションを設定することでPOSTメソッドで任意のBodyを送信したり、HTTPリクエストヘッダなどを指定することも出来ます。

# (補足)DNSによる名前解決

これは以前書きました。

[Linux環境でnslookupやdigコマンドでDNSを学ぶ](http://qiita.com/toshihirock/items/1ff01a51570bf6ca4f59)