ネットワークで疎通できないときの、原因の切り分け方
休日なのにまじめな話題です。
ネットワーク関連の仕事をしていると、「通信できない状態」というのが結構頻繁にあります。ネットワークは様々な機器が連携して構成されているので、何が悪いのかを切り分けられるかどうかは、とても重要なのです。
まだファイアーウォールなどが存在しなくても問題なかった平和な時代は、通信できないという場合、
・ケーブルがつながっていない
・相手の機器が立ち上がっていない
・相手のプログラムが立ち上がっていない
・IPアドレスやポート番号が間違えている
・ルーティングが通っていない
・DNSが引けていない(IPアドレスではなくホスト名の場合)
という感じに、比較的想像しやすい原因が多かったのですが、今ではインターネットでの通信にファイアーウォールがないことはまずありませんから、ファイアーウォールで拒否されている可能性が大きく関係してきます。
設定やプログラムの問題なのか、ファイアーウォールの問題なのかを素早く切り分けられるかどうかは、ネットワーク関連の仕事がスイスイ進むかどうかの大きなポイントになります。たいていの場合、ファイアーウォールは別の担当者がいて、自分で自由に設定を変更できないからです。原因の切り分けに自信があれば、「これはファイアーウォールの問題なので、ファイアーウォール担当者に変更を依頼してください」と言えますが、原因が切り分けできていないと、まずは自分で原因を調べて欲しい、と言われることがほとんどです。なかなか仕事が進まないのです。
さて、ファイアーウォールの問題かどうかを、TCP/IPの場合に簡単に見分ける方法は、たいていの場合、そんなに難しいことではありません。ファイアーウォールが原因で通信できない場合は、「相手からの応答がない」という場合がほとんどなのです。もう少し具体的に動きを説明すると、「相手と通信しようとして、なかなかつながるかどうかがわからない場合」は、大抵ファイアーウォールが原因です。そうでない場合は、すぐにエラーになる場合が多いのです。
理由としては、ファイアーウォールで遮断されていると、応答パケットが返ってこないからです。TCP/IPでは、接続を確立する際に、3ウェイ・ハンドシェークを行いますが、自分からSYNパケットを送信して、SYN+ACKパケットの応答がこないのです。そうすると、TCP/IPはしばらくリトライしますので、プログラムを使う側としては、しばらく待って、タイムアウトしてエラーになる、という感じになります。IPアドレス・ポート番号の間違いや、設定の間違いの場合は、大抵すぐにエラーになります。特に、pingが通るのにSSHがなかなかつながらない、とかいう感じに、疎通するものとしないものがあり、白黒はっきりするのに時間がかかる場合は大抵ファイアーウォールの問題です。
「モタモタしてからエラーになるから、ファイアーウォールが悪い」というのは、お客さんに説明しにくい、というのであれば、パケットキャプチャを見れば良いでしょう。
telnetで当社のサイトにつなごうとすると、次のようにタイムアウトエラーになります。
$ telnet ncad.co.jp
Trying 219.101.47.162...
telnet: connect to address 219.101.47.162: Operation timed out
telnet: Unable to connect to remote host
このときに、パケットをキャプチャしてみると、
# tcpdump -i en0 port telnet
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on en0, link-type EN10MB (Ethernet), capture size 65535 bytes
20:27:56.645298 IP 192.168.17.32.57819 > dns.ncad.jp.telnet: Flags [S], seq 1335778315, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 403301021 ecr 0,sackOK,eol], length 0
20:27:57.562042 IP 192.168.17.32.57819 > dns.ncad.jp.telnet: Flags [S], seq 1335778315, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 403301030 ecr 0,sackOK,eol], length 0
20:27:58.563460 IP 192.168.17.32.57819 > dns.ncad.jp.telnet: Flags [S], seq 1335778315, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 403301040 ecr 0,sackOK,eol], length 0
・・・
こんな感じに、SYNパケットを繰り返し送信するだけで、相手からは何の応答もない状態になります。これはファイアーウォールでパケットを遮断されているだろうと判断できます。
相手がtelnetポートで待ち受けしていない場合は、すぐに拒否されたというエラーになります。
$ telnet 192.168.0.3
Trying 192.168.0.3...
telnet: connect to address 192.168.0.3: Connection refused
telnet: Unable to connect to remote host
# tcpdump -i en0 port telnet
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on en0, link-type EN10MB (Ethernet), capture size 65535 bytes
20:32:00.947140 IP 192.168.17.32.57828 > 192.168.0.3.telnet: Flags [S], seq 22532758, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 403303461 ecr 0,sackOK,eol], length 0
20:32:00.961333 IP 192.168.0.3.telnet > 192.168.17.32.57828: Flags [R.], seq 0, ack 22532759, win 0, length 0
パケットキャプチャすると、SYNに対してRSTが応答されているので、すぐにエラーとわかるのです。
IPアドレスが間違えていれば、
$ telnet 192.168.17.5
Trying 192.168.17.5...
telnet: connect to address 192.168.17.5: Host is down
telnet: Unable to connect to remote host
同一セグメントであればARPで相手を調べるので、多少待つかも知れませんが、telnetポートのパケットは一つも飛びません。
$ telnet 192.168.0.6
Trying 192.168.0.6...
telnet: connect to address 192.168.0.6: Network is unreachable
telnet: Unable to connect to remote host
他のセグメント宛だと、ルーターのMACアドレス向けにSYNパケットは飛びますが、ICMPで到達不能が戻り、エラーになります。
ホスト名が間違えていれば、こんなエラーになります。
$ telnet ncadd.co.jp
ncadd.co.jp: nodename nor servname provided, or not known
エラーメッセージの観察と、パケットの観察をすれば、ほぼ確実にファイアーウォールによる遮断かどうかはわかるのです。
本当は他の原因の場合もまだまだあるのですが、、とりあえず、こんな感じに原因を自力で切り分けられるかどうかで、仕事の進み方は大きく変わります。一緒にいるお客さんからも頼りにされることでしょうし、何よりも、自分の側が悪いのではないかと疑われるのをはね除けることができます。
ITの仕事をしている人でお、ネットワークはよくわからん、というように嫌う人は多いので、このようなちょっとした知識があるだけでも、だいぶ違ってくると思います。是非勉強してみてください。