こんにちは。
リンクアンドモチベーション SREの篠原です。
普段アプリケーションの開発をしていると、何かしらに繋がらなくて困るといった場面は少なくないと思います。
現在SREとして、そして過去インフラエンジニア/システム管理者としての経験もある筆者がこのような時にどうやって調査し解決しているかを紹介します。
特に若手の開発者やインフラエンジニアの方々に参考になれば幸いです。
(あくまで個人の考えのため、もしより良い方法などありましたらぜひコメントで教えてください!)
役に立つコマンド
OSI参照モデルにおけるL4、トランスポート層での通信ができるかどうかをまず確認します。
誤解を恐れずにいうと具体的にはIPアドレスとポートの組み合わせが許可されているかを確認します。
この確認にはnc/telnet等のコマンドが活用できます。
※ ncコマンドのバージョンが古いと-z
オプションが使えないので注意
ubuntu@gratified-gunnel:~$ nc -zv 192.168.64.3 80Connection to 192.168.64.3 80 port [tcp/http] succeeded!ubuntu@gratified-gunnel:~$
余談ですがコンテナなどのncもtelnetもインストールされていない環境の場合curlでも疎通確認できます。
ubuntu@gratified-gunnel:~$ curl -v telnet://192.168.64.3:22* Trying 192.168.64.3:22...* TCP_NODELAY set* Connected to 192.168.64.3 (192.168.64.3) port 22 (#0)SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.3^Cubuntu@gratified-gunnel:~$
通信できなかった場合には下記を確かめていきましょう。
役に立つコマンド
疎通先サーバのfirewallや、AWSの場合Security Groupが適切に設定されているかを確認しましょう。また疎通元のIPアドレスを今一度確認して、フィルター設定が適切か見直しましょう。
プライベートIPの場合はip/hostname等のコマンドで確認できます。
ubuntu@gratified-gunnel:~$ ip a s1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever2: enp0s2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether f6:39:81:a7:32:ac brd ff:ff:ff:ff:ff:ff inet 192.168.64.2/24 brd 192.168.64.255 scope global dynamic enp0s2 valid_lft 80544sec preferred_lft 80544sec inet6 fe80::f439:81ff:fea7:32ac/64 scope link valid_lft forever preferred_lft foreverubuntu@gratified-gunnel:~$ hostname -I192.168.64.2ubuntu@gratified-gunnel:~$
グローバルIPの場合はcheckip.amazonaws.com
等のIPを確認できるサイトを利用しましょう。
ubuntu@gratified-gunnel:~$ curl checkip.amazonaws.com203.0.113.1ubuntu@gratified-gunnel:~$
またifconfig.io
の場合はipv6のIPアドレスを優先的に返してくれるので、ipv4のつもりが想定外にipv6でアクセスしていないかを確認することもできます。
ubuntu@gratified-gunnel:~$ curl ifconfig.io2001:db8::1ubuntu@gratified-gunnel:~$
役に立つコマンド
疎通先がIPアドレスではなくドメイン名やホスト名の場合名前解決の不具合を疑いましょうこの確認にはdig/nslookup/ping等のコマンドが活用できます。
ubuntu@gratified-gunnel:~$ dig +short example.com93.184.216.34ubuntu@gratified-gunnel:~$ubuntu@gratified-gunnel:~$ ping -c 1 example.comPING example.com (93.184.216.34) 56(84) bytes of data.64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=54 time=110 ms--- example.com ping statistics ---1 packets transmitted, 1 received, 0% packet loss, time 0msrtt min/avg/max/mdev = 109.553/109.553/109.553/0.000 msubuntu@gratified-gunnel:~$
もしもexample.com
等の一般的なドメインの名前解決が失敗する場合にはローカルのresolverの設定を確認しましょう。特定の宛先のみ名前解決が失敗する場合には参照しているDNSの設定を確認しましょう。またローカルの/etc/hosts
に余計なエントリーが入っていないかも確認すると良いです。
役に立つコマンド
no route to host
のようなログの場合にはルーティング設定を確認しましょう。ipコマンドやnetstatなどでサーバのルートテーブルを確認できます。AWSの場合にはVPCのルートテーブルの設定を確認しましょう。
ubuntu@gratified-gunnel:~$ ip r sdefault via 192.168.64.1 dev enp0s2 proto dhcp src 192.168.64.2 metric 100192.168.64.0/24 dev enp0s2 proto kernel scope link src 192.168.64.2192.168.64.1 dev enp0s2 proto dhcp scope link src 192.168.64.2 metric 100ubuntu@gratified-gunnel:~$
traceroute/tracepath等のコマンドで実際の経路を確認することもできますが、宛先がicmpを許可していない場合にはブロックされてしまうので気をつけましょう。
ubuntu@gratified-gunnel:~$ tracepath example.com 1?: [LOCALHOST] pmtu 1500 1: _gateway 0.171ms 1: _gateway 0.232ms 2: hogehoge.(実際にはipアドレス等が入ります) 5.669ms 3: fugafuga 7.505ms 4: foobarbaz. 22.078ms
L4(IPアドレス/ポート)で疎通できる場合は大きく下記の2パターンに分けて調べましょう。
役に立つコマンド
基本的にはアクセスした際に返却されるステータスコードを確認しましょう。curlに-I
オプションを付けるとステータスコードが確認できます。
ubuntu@gratified-gunnel:~$ curl -I http://example.com/nothingHTTP/1.1 404 Not FoundCache-Control: max-age=604800Content-Type: text/html; charset=UTF-8Date: Tue, 07 Dec 2021 08:15:38 GMTExpires: Tue, 14 Dec 2021 08:15:38 GMTServer: EOS (vny/0453)Vary: Accept-EncodingContent-Length: 1256ubuntu@gratified-gunnel:~$
出力の一番上にステータスコード(上記だと404)が表示されるので確認しましょう。
https://developer.mozilla.org/ja/docs/Web/HTTP/Status.基本的には4xxの場合にはパスが正しいか、認証が正しくできているかあたりを確認します。
5xxの場合はwebサーバ側が正しい状態になっているか、負荷が以上にかかっていないかなどが原因として考えられます。
またHTTPSの場合はSSLの処理が正しく行われているかを確認しましょう。
ubuntu@gratified-gunnel:~$ curl -v https://example.com(省略)* successfully set certificate verify locations:* CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs* TLSv1.3 (OUT), TLS handshake, Client hello (1):* TLSv1.3 (IN), TLS handshake, Server hello (2):* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):* TLSv1.3 (OUT), TLS handshake, Client hello (1):* TLSv1.3 (IN), TLS handshake, Server hello (2):* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):* TLSv1.3 (IN), TLS handshake, Certificate (11):* TLSv1.3 (IN), TLS handshake, CERT verify (15):* TLSv1.3 (IN), TLS handshake, Finished (20):* TLSv1.3 (OUT), TLS handshake, Finished (20):* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384* ALPN, server accepted to use h2* Server certificate:* subject: C=US; ST=California; L=Los Angeles; O=Internet Corporation for Assigned Names and Numbers; CN=www.example.org* start date: Nov 24 00:00:00 2020 GMT* expire date: Dec 25 23:59:59 2021 GMT* subjectAltName: host "example.com" matched cert's "example.com"* issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1* SSL certificate verify ok.(省略)ubuntu@gratified-gunnel:~$
上記のSSL certificate verify ok.
が出力されなかった場合にはサーバ側のSSL証明書失効や、設定が不適切である可能性があります。
また、クライアント側のOSが古いと配置してあるCA証明書が古い可能性もあるのでそちらも確認しましょう。
HTTP以外の場合にはあまり有用なメッセージが出力されないケースもあります。(攻撃者に情報を与えてしまうため)
例えばSSHでログインできない場合、原因の候補はいろいろありますが基本的には同じメッセージしか出力されません。
(クライアント側)ubuntu@effectual-caracal:~$ ssh ubunt@192.168.64.2ubunt@192.168.64.2: Permission denied (publickey).ubuntu@effectual-caracal:~$(サーバ側のauth.log)Dec 7 17:30:31 gratified-gunnel sshd[1325]: Connection closed by authenticating user ubuntu 192.168.64.3 port 36100 [preauth]Dec 7 17:30:50 gratified-gunnel sshd[1327]: Invalid user ubunt from 192.168.64.3 port 36102Dec 7 17:30:50 gratified-gunnel sshd[1327]: Connection closed by invalid user ubunt 192.168.64.3 port 36102 [preauth]
上記のようにユーザ名が間違っているという情報はクライアント側には伝わらないため、アクセスを受ける側から調査をした方が基本的には効率的です。
サービス側で出力された情報をもとにアプリのドキュメントを参照するのがいいと思います。もしくはエラーログを適当にコピペしてググると早いかもしれません。
これらを試しても解決できない場合には上位者やシステム管理者へ問い合わせるのが良いかと思います。クライアント側からだと調査が難しくてもサービス側からであれば容易なケースも少なくないため。
問い合わせる際には下記のような情報があると調査する際に助かるかなと思います。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。