HEARTBEATS

Nagios Pluginsのcheck_httpを使いこなそう

   

あけましておめでとうございます。MSP事業部エンジニアリンググループの寺島です。

弊社の監視システムは Nagios を利用しており、実行している監視も多くが Nagios Plugins を用いています。 Nagios PluginsはNagiosとセットで使うものと思われがちですが、実はNagiosと組み合わせずコマンド単体で利用しても非常に便利なものです。 この記事ではNagios Pluginsの中からHTTP監視のためのcheck_httpを取り上げ、使い方を説明します。

check_httpとは

Nagios Pluginsの中に含まれている、HTTP(S)サービスを監視するためのNagiosプラグインです。C言語で書かれています。 check_httpには多くのオプションがあり、それらのオプションを組み合わせるとCLIで様々なケースの応答確認・動作テストが行えます。

インストール

はじめにcheck_httpをインストールしてみましょう。 Red Hat Enterprise Linuxやその互換ディストリビューションの場合、まずFedora ProjectのUser Documentationの手順でEPELリポジトリをセットアップします。 次に、EPELリポジトリからRPMパッケージをインストールします。

$ sudo dnf -y install nagios-plugins-http

上のコマンドはRed Hat Enterprise Linux 8やその互換ディストリビューションの例です。Red Hat Enterprise Linux 7やCentOS 7の場合にはdnfをyumに置き換えてください。

RPMパッケージnagios-plugins-httpをインストールするとcheck_httpコマンドは/usr/lib64/nagios/plugins/check_httpに置かれます。 コマンドファイルがどこにあるか調べたいときには下のようなコマンドを実行します。

$ rpm -ql nagios-plugins-http | grep check_http
/usr/lib64/nagios/plugins/check_http

check_httpコマンドの詳しい使い方は--helpオプションで確認できます。

$ /usr/lib64/nagios/plugins/check_http --help

実行のたびにフルパスを入力するのは大変なので、下のコマンドを実行してパスを通しておきます。

$ export PATH=$PATH:/usr/lib64/nagios/plugins

インストールが完了したら、さっそくcheck_httpを使ってみましょう。


基本的な使い方

使用頻度の高いオプション

check_httpは -H ( --hostname ) オプションで接続先のホストネームを指定します。 弊社の新サービスであるkozutumi.comを指定すると、結果は下のようになりました。

$ check_http -H kozutumi.com
HTTP OK: HTTP/1.1 301 Moved Permanently - 142 bytes in 0.148 second response time |time=0.148278s;;;0.000000 size=142B;;;0

いろいろ出力されましたが、ここではHTTP/1.1 301 Moved Permanentlyの部分に注目してみます。 301 Moved Permanentlyはリダイレクト応答なのですが、リダイレクト先がどこなのか、この実行例からはわかりません。 応答の内容をもう少し詳しく観察するために -v ( --verbose ) オプションをつけて再実行してみます。-vオプションをつけることでリクエストヘッダ、レスポンスヘッダ、レスポンスボディが出力されます。

$ check_http -H kozutumi.com -v
GET / HTTP/1.1
User-Agent: check_http/v2.3.3 (nagios-plugins 2.3.3)
Connection: close
Host: kozutumi.com
Accept: */*


http://kozutumi.com:80/ is 142 characters
STATUS: HTTP/1.1 301 Moved Permanently
**** HEADER ****
Content-Length: 0
Connection: close
Date: Fri, 16 Dec 2022 00:20:50 GMT
Location: https://kozutumi.com/
**** CONTENT ****

HTTP OK: HTTP/1.1 301 Moved Permanently - 142 bytes in 0.102 second response time |time=0.102127s;;;0.000000 size=142B;;;0

レスポンスヘッダの中にLocation: https://kozutumi.com/が含まれていますので、リダイレクト先は https://kozutumi.com/ であることがわかりました。 つまり、これはHTTPからHTTPSへのリダイレクト応答でした。

なお、レスポンスボディを出力する必要がない(=HTTPヘッダだけを観察したい)という場合には -N ( --no-body ) オプションを併用します。

$ check_http -H kozutumi.com -v -N

特定のヘッダだけを観察したい場合には、下のようなコマンドを実行するとよいでしょう。

$ check_http -H kozutumi.com -v -N | grep Location

また、-Hと同様にほぼ必ず指定することになるオプションで、URIを指定する -u ( --uri ) があります。 --uriを指定しなければ --uri '/' を指定したのと同じ動きになります。

$ check_http -H kozutumi.com --uri '/'

--uriでの指定に&などのメタ文字が含まれていると意図したとおりのコマンド実行にならないことがあるので、メタ文字が含まれているかどうかに関わらず常にシングルクォートで囲うとよいでしょう。

接続先の指定

DNSが指しているホストとは別のホストに対してHTTPリクエストを送信したいときがあります。 そのようなときには -I ( --IP-address ) オプションでリクエスト宛先のIPアドレスを指定できます。

ロードバランサーで複数台のサーバーがバランシング対象になっていて、更にProxyサーバーとアプリケーションサーバーが分かれているようなWebシステムがあったとします。 そのようなシステムでなんらかの問題が発生し状況を詳しく調査しなければならないとき、下のようなコマンドでシステム内部の任意の部分の応答を確認できます。

$ check_http -H your-app.example.com -I 127.0.0.1 -v -N

宛先ポートを変更したい場合には -p ( --port ) オプションを利用します。

$ check_http -H your-app.example.com -I 127.0.0.1 --port 8080 -v -N

また、Webシステムのリプレースを行うためにDNSレコード更新で新システムに切り替えるようなときにも、切り替え前の動作テストにこのオプションを利用できます。


SSL接続

HTTPではなくHTTPSリクエストを行うためには -S ( --ssl ) オプションを使用します。 併せて --sniオプションを指定しておくことにします。--sniについて、この記事で説明はできませんが興味のある方は調べてみてください。

$ check_http -H kozutumi.com --ssl --sni
HTTP OK: HTTP/1.1 200 OK - 27905 bytes in 0.264 second response time |time=0.263747s;;;0.000000 size=27905B;;;0

こんどは、はじめの実行例のような 301 Moved Permanently ではなく 200 OK の応答が確認できました。

SSL/TLSバージョンの指定

--sslオプションでSSL/TLSのバージョンを明示的に指定できます。TLS1.1で接続したいときは下のように指定します。

$ check_http -H kozutumi.com --ssl=1.1 --sni
CRITICAL - Cannot make SSL connection.
281473416189008:error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version:ssl/record/rec_layer_s3.c:1544:SSL alert number 70

上の例ではCannot make SSL connection.と出力されており、接続に失敗しています。 TLS1.1はすでに安全な暗号プロトコルではなくなってしまいましたので、サーバー側で意図的にTLS1.1を無効化していればこのような結果になります。 同じkozutumi.comに、現在も安全とされているTLS1.2で接続を試みると下のように接続に成功します。

$ check_http -H kozutumi.com --ssl=1.2 --sni
HTTP OK: HTTP/1.1 200 OK - 27905 bytes in 0.270 second response time |time=0.269592s;;;0.000000 size=27905B;;;0

このようにして、check_httpコマンドで接続先のTLSサポート状況を観察できます。

TLS証明書の期限チェック

check_httpで -C ( --certificate ) オプションを使用するとTLS証明書の期限を確認できます。

$ check_http -H kozutumi.com --ssl --sni --certificate 30
SSL WARNING - Certificate 'kozutumi.com' expires in 25 day(s) (2023-01-14 23:59 +0000/UTC).

この実行例では30(単位は日)を指定しているのに対して、証明書の期限切れまでの日数がそれ以下(25日)のためWARNINGと出力されました。

check_httpに限らず、Nagiosプラグインは結果とコマンドの終了コードが下のように紐づいています。

  • OK: 0
  • WARNING: 1
  • CRITICAL: 2
  • UNKNOWN: 3

コマンドの終了コードは、監視の結果に応じて処理を変えたいときに役立ちます。 例えば下のようなコマンドを定期実行しておくと、TLS証明書の期限が切れる前にメール通知が行われます。

$ check_http -H your-app.example.com --ssl --sni --certificate 5 >/dev/null \
  || echo 'TLS証明書の期限切れが間近です。' | mail infra-team@example.com

ただし、このコマンドではTLS証明書の期限がしきい値以下の場合だけでなく、障害発生中などでyour-app.example.comに接続できなかった場合もメール通知が行われてしまいます。 特に高い頻度での実行が求められる用途のときは、シェルスクリプトにしてエラー処理をきちんと行ったほうがよいでしょう。


応答時間のチェック

Webシステムで継続的にチェックしておきたいのは、応答時間です。

check_httpでは -w ( WARNING ) と -c ( CRITICAL ) という2つのしきい値と、それとは別に -t ( timeout ) を指定できます。

$ check_http -H kozutumi.com --ssl --sni -w 3 -c 5 -t 10
HTTP OK: HTTP/1.1 200 OK - 27905 bytes in 0.369 second response time |time=0.368831s;3.000000;5.000000;0.000000 size=27905B;;;0

この例では実際の応答時間は0.369秒でした。-wで指定した3(秒)を下回っているのでOKと出力されています。 試しにWARNINGのしきい値を0.1(秒)と指定すると、下のような結果になりました。

$ check_http -H kozutumi.com --ssl --sni -w 0.1 -c 5 -t 10
HTTP WARNING: HTTP/1.1 200 OK - 27905 bytes in 0.432 second response time |time=0.432100s;0.100000;5.000000;0.000000 size=27905B;;;0

システムのユーザーから「システムの応答が遅い」と連絡を受けたものの、システム担当者が試してみても遅延は再現せず本当に遅延が起きていたかどうかもわからないということがあります。 常日頃からきちんとモニタリングして応答時間の状況を記録しておくべきですが、そういった仕組みがまだ導入できていないということもよくあります。 そのような場合、応急処置として上のようなコマンドを定期実行してログ記録しておくだけでも遅延状況の把握に役立つでしょう。

応答時間に関連したオプションをもうひとつ紹介します。 -E ( --extended-perfdata ) オプションを使用すると応答時間の詳細な内訳を確認できます。 下の例では実行結果を見やすくするためにsedコマンドを併用しています。

$ check_http -H kozutumi.com --ssl --sni -E | sed -e 's/time_\([a-z]*\)=/\ntime_\1\t= /g'
HTTP OK: HTTP/1.1 200 OK - 27905 bytes in 0.329 second response time |time=0.328687s;;;0.000000 size=27905B;;;0 
time_connect    = 0.052619s;;; 
time_ssl        = 0.126966s;;; 
time_headers    = 0.000027s;;; 
time_firstbyte  = 0.097263s;;; 
time_transfer   = 0.148974s;;;

Webシステムの応答が遅いとき、問題箇所を絞り込むための参考になることがあります。


応答内容のチェック

応答時間の他に、応答内容のチェックが必要なこともあります。

コンテンツの中に特定の文字列が含まれているかどうかをチェックしたい場合には --stringオプションを使用します。下の例では、コンテンツに文字列PPAPが含まれていればOKに、含まれていなければCRITICALになります。

$ check_http -H kozutumi.com --ssl --sni --string 'PPAP'
HTTP OK: HTTP/1.1 200 OK - 27905 bytes in 0.432 second response time |time=0.432208s;;;0.000000;10.000000 size=27905B;;;0

身近な活用例として「ショッピングサイトで在庫切れ商品の在庫が復活したらメール通知する」ということもできます。

$ check_http -H shop.example.com --ssl --sni --string 'In Stock' \
  && echo '商品の在庫があります' | mail $MAIL_ADDRESS

他にも --expectや --header-stringといったオプションがあり、ステータスコードやレスポンスヘッダの内容をチェックできます。 「コンテンツ圧縮に対応したHTTPクライアントに対しては圧縮済みコンテンツを返す」ということをテストするコマンドは下のようになります。 この例ではリクエストヘッダを追加するオプション -k ( --header ) と、レスポンスヘッダをチェックする --header-stringオプションを組み合わせて使用しています。

$ check_http -H kozutumi.com --ssl --sni \
  --header 'Accept-Encoding: gzip' \
  --header-string 'Content-Encoding: gzip'

なお、--headerオプションは複数回指定できます。下のように指定します。

$ check_http -H your-app.example.com --ssl --sni -v -N \
  --header 'Via: 1.1 cdn.example.net' \
  --header 'X-Forwarded-For: 203.0.113.10' \
  --header 'X-Forwarded-Proto: https' 

上はCDNからオリジンへの通信を模したHTTPリクエストを送信する例です。

このようにして、任意のリクエストヘッダのHTTPリクエストを送信し、その応答を観察できます。

User-Agent の変更

-A ( --useragent ) オプションを使用することでHTTPリクエストのUser-Agentを変更できます。

Bad Botからのリクエストを大量に受信したことでWebシステムの負荷が高くなってしまうことがあります。 Bad BotのUser-Agentが固有であればUser-Agentをもとにしたアクセス制限を検討することになりますが、アクセス制限の動作テストにこのオプションが利用できます。

※システムに脆弱な部分がないか探索する、不正ログインを試みる、スパムコメントを投稿する、というような振る舞いをする有害なボットプログラム

$ check_http -H your-app.example.com --useragent 'Bad Bot' --expect 403

上の例では --expect 403 というオプション指定を併用しているため、応答のステータスコードが403 ForbiddenであればOKとなります。

もうひとつ例をあげます。 あなたが担当しているWebシステムで「User-Agentに "iPhone" か "Android" が含まれていたら /sp/ にリダイレクトする」という設定をすることになりました。 要件に沿った設定をシステムに反映し、設定反映後の応答が予定通りかどうかを確かめる必要があります。下のコマンドを実行することで応答をテストできます。

$ check_http -H your-app.example.com --useragent iPhone -v -N
$ check_http -H your-app.example.com --useragent Android -v -N

ただしこの動作確認はあくまで簡易的なものですので、できれば実機での動作確認も行いましょう。


まとめ

監視のプラグインであるcheck_httpがWebシステムの応答確認や動作テストにも利用できるという例をいくつかご紹介しました。 これまでNagios Pluginsに触れる機会のあまりなかった方が、この記事をきっかけに興味をもっていただけたら幸いです。 この記事で紹介できたのはcheck_httpのオプションの一部のみですので、他のオプションもぜひ調べてみてください。

補足

Debian GNU/LinuxやUbuntuでもmonitoring-pluginsをインストールすることでcheck_httpが利用できます。 Monitoring Plugins Projectは過去にNagios Pluginsから分かれたプロジェクトです。