何のエラーが出たのですか?
안녕하신게라!パナソニックコネクト株式会社クラウドソリューション部の加賀です。
白い目で見られるのツラくないですか?自分はツラくて耐えられません。
根性の昭和では無く、タイパの令和だからこそ、どストレートに「こうすれば白い目で見られないよ!」となるような記事を書いてみました。
はじめに
エンジニアが助けを乞う事はよくある事です。けれどその時に冷ややかな反応をされた経験やそんな場面を見掛けたことはありませんか?いったい何があったのか少し振り返ってみます。
たとえば、そのときの質問が「ブラウザでエラーが出たんですけど…」「ブラウザ画面が真っ白なんですけど…」みたいな感じだったりしませんでしたか?
つまり、白い目で見られているのは、そもそもエンジニアが問題の切り分けをせず質問していることが原因なのですが、もしかしたら裏側で何が起きているのかを想像しにくいからかも?と考え執筆しました。もちろん、あやふやな知識では断言できないよというエンジニア魂もあると思います。再確認も大事ですのでサラッとでも確認してください。
この記事では例で上げた、ブラウザが動作する時に発生するエラーと、そのトラブルシュート方法を紹介しながら、実際に処理される順番で7つの基礎知識を紹介したいと思います。
DNS(名前解決)
インターネットの根幹をなす要素です。
ブラウザのアドレスバーに入力した文字はドメイン名が含まれており、人間には理解しやすいですが、そのままではインターネット上では使えません。インターネット上で使える通信方式であり人間には覚えにくいIPアドレスに変換する必要があります。これをDNSサービスを利用した名前解決と言い、ドメイン名→IPアドレスへの変換を正引きと言います。逆引きはIPアドレス→ドメイン名です。
また、応答がドメイン名→ドメイン名となった場合、IPアドレスに辿り着くまで正引きを繰り返し行います。
名前解決には辞書が必要であり、参照する順番は以下です。
キャッシュ含め、名前解決に必要な辞書データが見つかった時点で参照を中断して応答します。
- ブラウザのDNSキャッシュ
- OSのDNSキャッシュ
- ネットワークの途中経路にあるルータやプロバイダのDNSキャッシュ
- ルートサーバのキャッシュ
- 上位ドメインDNSサーバのキャッシュ
- 権威DNSサーバのキャッシュ
- 権威DNSサーバの辞書データ
辞書データ上でキャッシュの有効生存時間(TTL)を指定できるので、反映待ちや浸透待ちという表現が産まれる余地があり、エンジニアは待ちを減らすようにコントロールすべきですが、これだけで1本記事が書けてしまうのでまた別の機会に。
DNSのトラブルシュート
この時点のエラーではブラウザとWebサーバの間で通信は一切発生していないため、確認するポイントは限られてきます。
症状 | 対処 |
---|---|
ドメイン名が存在しない |
FQDN部の正当性を確認 whoisサービスを利用する |
応答するIPアドレスが存在しない | DNSサーバの辞書データに登録されているFQDNを確認 digコマンドやnslookupコマンドで確認 |
応答するIPアドレスが異なる | TTL値をdigコマンドやnslookupコマンドで確認 可能ならDNSキャッシュクリア 別のDNSサーバを利用するのも有効 |
DNSサーバに接続できない | 上記順番を参考に、ネットワーク接続を確認(次項も参照) 別のDNSサーバを利用するのも有効 |
名前解決に成功し、接続すべきIPアドレスが判明したら次ステップ。
ネットワーク(経路特定とルーティング)
ネットワーク層の話です。データリンク層や物理層は取り上げませんが通信エラー発生時には考慮すべきです。
さて、DNSを用いて接続すべきIPアドレスが判ったら、次にネットワークのどこへ向けてリクエストを通信したら良いでしょうか?という疑問を解消するために、以下の順番に経路情報から次のネットワークはこちらですよーと誘導し、最終目的地まで繰り返し案内します。それがルーティングです。
- OS上のゲートウェイ
- ルータ上のゲートウェイ
- AS間のルーティング情報
- 接続元IPアドレスと接続先IPアドレスが接続完了
利用者から見ると最終的にIPアドレス同士が直接接続しているように見えますが、実際には間にたくさんのネットワークやルータを介して接続しています。これがインターネットの実体です。特殊なパターンとして、間の通信機器やネットワークの全てが自分の管理下の場合だけ、占有環境や専用線やオンプレミス等と呼ばれる状況となります。
インターネットは複数のネットワーク同士が接続しているため、基本的に意識しなくても接続は多重化され安定していますが、その一方で、途中経路国の政治方針や国同士の戦争・紛争で、一時的に不安定になったり切断される事もあり得ます。
ネットワークのトラブルシュート
症状 | 対処 |
---|---|
インターネットに接続できない | OSが利用するネットワークインターフェースの確認 OS上のゲートウェイIPアドレスを確認 ネットワーク自身の正常性を確認 |
特定のIPアドレス範囲だけ接続できない | OSの上の経路情報をip routeコマンドやrouteコマンドで確認、ルータ上の設定確認を行うか、担当者に依頼する |
途中経路で接続エラーになる | 自動的に修復されるはずだが、AS番号の管理団体に確認(レアケース) 途中経路を特定するにはtracepathコマンドやtracertコマンドを用いるが、最近はICMPに応答しないルータが多いためあまり機能しない |
この層でエラーになることは少ない(インフラ部隊に感謝!)とはいえ、問題の切り分けは知っておくべきでしょう。実際は次のステップと同時にまとめて切り分けを行うことも多いです。
TCP/IP(ポート接続とセッション確立)
トランスポート層の話です。ここでようやくブラウザとWebサーバが繋がります。
ネットワークでIPアドレス同士の通信が出来るようになり、そのIPアドレスを占有して利用し続けると、他に利用したい人から見ると通話中で使えないという状況になってしまい不便です。そうならないために港や空港みたく、複数のポートを使い分け複数の接続を同時に処理することを実現しています。
いくつかの実現手段がありますが、現在主流となっているのがTCP/IPです。
- ブラウザ側で空いているポート番号を選出する
- Webサーバのポート番号はほぼ固定(80か443が標準だが変更可能)
- IPアドレスで接続し、先の1.2.で指定したポート番号同士で接続を開始する
- 3ウェイハンドシェイク実施
- TCP/IP接続完了
3ウェイハンドシェイクは、このポート番号は俺様が使うやで!OK?という合意形成のやり取りを双方で実施する手続き(プロトコル)です。切断時もいきなりLANケーブルを抜かずに同じ手続きを踏むのがベターです。
TCP/IPのトラブルシュート
症状 | 対処 |
---|---|
接続が即時却下される | 通信経路上で却下するルール(FWやルータのルール)に抵触してる可能性 |
接続がタイムアウトする | 通信経路上で無視するルール(FWやSG)に抵触してる可能性 Webサーバが多忙で応答が間に合わない可能性(次項) netstatコマンドで状況を確認 |
ブラウザ側のnetstat上でSYN_SENT | ブラウザからのリクエストがWebサーバまで到達していない可能性 Webサーバからの応答がブラウザまで返って来ていない可能性 |
Webサーバ側のnetstat上でSYN_RECV | Webサーバからブラウザへの応答が届いていない可能性 ブラウザ側が多忙で応答が間に合わない可能性 |
ブラウザかWebサーバどちらかの netstat上でESTABLISHED |
接続成功しています、次ステップへ |
接続成功していても、ブラウザ上は真っ白だったりするので、ここで質問に行くと真っ白い目で見られる可能性が高いです。ちゃんと最後の7つ目までチェックするようにしましょう。
ミドルウェア(リクエスト処理と橋渡し)
ミドルウェアとは、今回の例ではapacheやnginxやIIS等のWebサーバ用ミドルウェアを指します。ブラウザからのリクエストを解釈し、アプリケーションにデータの橋渡しを行い、結果データを返答します。今回の記事では、分かりやすさを優先し、プロキシ(中継)サーバやCDNやロードバランサも広義の橋渡しの一部と捉え、同列に記載しております。
ミドルウェアはブラウザとアプリケーションとの間でデータの橋渡しを行う事を主とします。
- ブラウザ
- ミドルウェア(フォワードプロキシ)
- ミドルウェア(CDN)
- ミドルウェア(ロードバランサ)
- ミドルウェア(Webサーバソフトウェア本体)
- ミドルウェア(リバースプロキシ)
- アプリケーション
ミドルウェアは各種パラメータを設定可能で、用途に応じたチューニングは可能ですが、性能には限界があります。思ったよりも同時接続や大量接続に対して弱いため、前段の橋渡し役にCDNキャッシュを用いたり、ロードバランサを配置してサーバの負荷分散を行ったりして、インフラ構成でフォローしていく部分でもあります。
そのため、構成によってトラブルシュートすべき視点や対象は変化しますが、基本的に共通している確認ポイントは、ずばりミドルウェアのログを確認することとなります。
ミドルウェアのトラブルシュート
症状 | 対処 |
---|---|
接続が即時で終了する | 正常な接続の可能性 |
接続がタイムアウトする | 橋渡しが正しく行われているかミドルウェアのアクセスログを確認 Webサーバが多忙で応答が間に合わない可能性 アプリケーション応答時間が長すぎる可能性 |
想定外のサーバに接続する | 橋渡しが正しく行われているかミドルウェアのアクセスログを確認 |
想定外のページが表示される | 橋渡しが正しく行われているかミドルウェアのアクセスログや設定値を確認 |
プロキシエラーが表示される | 途中経路にあるプロキシサーバでの橋渡しが正しく行われているかミドルウェアのアクセスログやエラーログを確認 |
CDNエラーが表示される | CDNのソースであるオリジンの橋渡しが正しく行われているかミドルウェアのアクセスログやエラーログを確認 |
橋渡しを成功させるのはインフラの仕事ではありますが、始点と終点であるブラウザやアプリの協力も大事だと思えるようになってきましたか?
SSL証明書(通信の暗号化と公正性)
ミドルウェアとの接続が出来て、やっとリクエストを配達してもらう事が出来ます。が、昨今のインターネットでは第三者に通信を覗かれないよう暗号化通信を行なうのが当然の様になっております。
どのように安全を担保するのかという暗号化の基礎を掘り下げるのはまた他の記事で触れたいと思いますが、基本は公開鍵暗号とCA認証を用い、第三者によるドメイン名・組織の実在確認等の検証プロセスを通してSSL証明書が発行されます。
発行されたSSL証明書をWebサーバの検証で用いる事で、ドメイン名の所有者とWebサーバの所有者が同一であることが、有効期限付きで保証されます。補足ですが、Webサーバのコンテンツ改竄は保証されません。
SSL証明書を用いることでWebサーバのなりすましや途中経路でのデータ盗聴を防ぐことが目的ですが、秘密鍵の取り扱いを間違えると中間者攻撃を許してしまい、途中経路上で通信内容が暗号化してあっても覗き見ることができてしまいます。
SSL証明書のトラブルシュート
症状 | 対処 |
---|---|
安全ではない通信という警告 | HTTP(ポート80)通信を行おうとしている HTTPS(ポート443)通信で無効なSSL証明書が提示された |
SSL証明書の署名が不当という警告 |
中間証明書やCA認証への信頼経路を確認 openssl s_clientコマンドのchain validationを確認 |
SSL証明書のドメイン名が異なる警告 | SSL証明書のFQDNとWebサーバのFQDNが一致していない |
SSL証明書の有効期限切れの警告 | SSL証明書の有効期限が切れている (ドメイン名によってはニュースになるので軽視禁止) |
ミドルウェアが橋渡しをする前にSSL証明書を検証するインフラ構成も取れますが、ミドルウェアのログが出る前にSSL証明書が検証される事は無いため、処理順通りに記載しています。
ただ、SSL証明書が正しくてもブラウザは真っ白になったりします。そろそろ最後まで読む覚悟出来ました?
HTTPステータスコード(Webサーバの応答)
ここまで来て、やっとWebサーバの応答がブラウザに表示されるようになります。
ミドルウェアからの応答には、Webサーバのコンテンツ以外にHTTPヘッダという手続きがあり、そのデータがブラウザに到達することではじめてブラウザは機能し始めます。
そのHTTPヘッダで一番重要となるのが、3桁の数字で表されるHTTPステータスコードです。有名どころですと、200 OK、302 リダイレクト、404 not found、等でしょうか。
ただ、ブラウザ上ではこれらのHTTPステータスコードは表示されることが無いため、curlコマンドやブラウザの開発者モードで確認しましょう。
HTTPステータスコードのトラブルシュート
症状 | 対処 |
---|---|
200 OK | 正常にコンテンツが表示されてます ブラウザが真っ白でも、応答としては正常 |
301/302/307/308 リダイレクトが繰り返し行われました |
ブラウザがリダイレクト無限ループを検知しました |
401 Authorization Required | リクエストしたコンテンツは認証が必要です |
403 Forbidden | リクエストしたコンテンツのアクセス権がありません |
404 Not found | リクエストしたコンテンツが存在しません |
500 Internal Server Error | ミドルウェア内でエラーが発生している可能性 ミドルウェアの橋渡しに失敗している可能性 アプリケーションでエラーが発生している可能性 |
503 Service Unavailable | Webサーバがメンテナンスの可能性 サーバが多忙で応答が間に合わない可能性 アプリケーションでエラーが発生している可能性 |
504 Gateway Timeout | リクエストの処理時間が長すぎる可能性 サーバが多忙で応答が間に合わない可能性 アプリケーションでエラーが発生している可能性 |
HTTPステータスコードを読むことで、ほぼ白い目で見られることは回避できるかと想像されますが、やはりエンジニアたるもの、問題解決の糸口まで指摘できると素敵ですね。次で最後のステップです。
アプリケーション(最終処理とコンテンツ生成)
最終チェックポイントです。ここまで確認したらあとはアプリケーション応答内容だけですが、多種多様な言語・フレームワーク等もあり、実は確認が一番むずかしいポイントだったりします。
基本的にはアプリケーションのログやデバッグ出力を確認することになりますが、ブラウザ側の開発者モード上での確認が出来るように構築すると何かと便利です。言語やフレームワークの構成によっては部分的な確認が簡単では無かったり、PHPのようにWebサーバ内部にエンジンが組み込まれている場合など、問題の切り分けの難易度は跳ね上がります。
アプリケーションのトラブルシュート
症状 | 対処 |
---|---|
真っ白なコンテンツが表示される | 0バイト応答の可能性(ブラウザは何もレンダリングしない) アプリケーションから何でも良いので文字列を出力 |
コンテンツが何も表示されない | ミドルウェアとの橋渡しを確認 フレームワークの設定を確認 アプリケーション単体の動作結果をコマンドラインやユニットテスト等で確認 |
アプリケーションエラーが表示される | エラーメッセージから該当箇所を絞り込む 最小要素の構成にし、絞り込んで原因を特定する |
アプリケーションやフレームワークのデバッグモードに設定値やクレデンシャル漏洩の可能性もあるため要注意、インターネット経由での確認時の接続経路やアクセス制限を要確認してトラブルシュートを行ってください。
アプリケーションの深淵を覗く時、ハッカーもまた一緒に覗いているのだ。
まとめ
かなり簡素化しているとはいえ結構な文量になっている気もしますが、もっと正確な情報を知りたい!方は、記事中リンクやQiitaタグから他の方の記事も参照してみてください。
本記事が、裏で起きているドミノ倒し的な事象に対する理解と、実際に構成を考えるときの解像度・想像力の一助となれば幸いです。
お断り
記事内容は個人の見解であり、所属組織の立場や戦略・意見を代表するものではありません。
あくまでエンジニアとしての経験や考えを発信していますので、ご了承ください。