面倒くさいから nginx の LDAP 認証モジュール公開したよ

2022年06月14日 火曜日


【この記事を書いた人】
ふぇにっくちゅん(守田 瞬)

2021年11月にセキュリティ情報統括室に所属。頑固なので、ニックネームだけでもやわらかくひらがなにしてみました。普段はハニーポットで収集したDDoSの発生源であるマルウェアを対象に分析しています。

「面倒くさいから nginx の LDAP 認証モジュール公開したよ」のイメージ

おはようございます。こんにちは。こんばんは。ふぇにっくちゅん です。

今回紹介するのは nginx で利用できる LDAP 認証モジュール(ngx_auth_mod)です。
nginx は Web サーバやリバースプロキシなどを構築でき、オープンソースとして公開されています。
nginx の詳細はこちらに記載されています。

本記事で紹介する ngx_auth_mod は CATSHAND と呼ぶ情報共有システムのモジュールとして開発したものです。
情報共有についての記事「情報を流れに乗せよう:セキュリティ調査の共有方法」も併せて一読ください。

CATSHAND のシステムは Web サーバとして nginx を利用しており、扱う情報は機密性が高いものです。
そのため、認証・認可の仕組みをシンプルかつ丁寧に行う必要があります。

認証の仕組みにはいくつかの種類があり、本記事では LDAP認証 を対象とします。
LDAP を利用するものの代表として Microsoft Active Directory があります。
CATSHAND に LDAP 認証を導入したのは、運用を考える上でユーザ管理をできるだけしたくないからです。
つまり LDAP にユーザ管理を任せるわけです。
ふぇにっくちゅん は面倒くさがり屋なのです。

今回紹介する ngx_auth_mod を開発するのは面倒ではないのか?という問いについての返答は NO です。
これは、既存の LDAP 認証モジュールや LDAP 認証の処理について調べた結果、面倒だと感じたからです。
こんな面倒なことを他の人もやっているのか?ということを思うと ngx_auth_mod を公開せずにはいられなくなりました。

ngx_auth_mod は2020年度に IIJ で開発したもので、こちらから入手できます。
使い方のガイドや仕様なども記載しています。
本記事は ngx_auth_mod の開発背景やモジュールの特徴などの補足情報を紹介します。

なんで作ったの?

冒頭で紹介した CATSHAND は、調査や分析を効果的に行いたいという欲から生まれた情報共有システムです。
CATSHAND には調査結果などの情報が蓄積され、情報共有のネタを守る金庫としての立場があります。
この立場は、セキュリティ分野の調査で扱う情報であるため、取り扱いに注意しなければならないものが含まれているからです。
つまり CATSHAND には、金庫としての役割と共有のために金庫の中が見える仕組みが組み込まれています。

この金庫の中を守ること(見せない)と金庫の中が見える仕組みは矛盾しているため同時に行うことは困難です。
これを解決するために、事前に金庫の中を見せてよい人には鍵を渡しておけばいいのです。
そうすることで、鍵を所持している人は好きな時に金庫の中を見ることができるようになります。

しかし、金庫を管理している人は苦労します。
たとえば、誰に鍵を渡したか?など金庫の利用者を管理しなければなりません。
面倒なことはできるだけ手を抜いて、守るべきものを守れるようにしたいものです。
そこで LDAP を利用します。

LDAP には組織に所属している人の情報が含まれています。
この仕組を使って認証を実現すれば、人や鍵の管理は LDAP に任せることができます。

CATSHAND のイメージは以下の通りです。

CATSHANDのイメージ

共有の仕組みについては、冒頭で紹介した「情報を流れに乗せよう:セキュリティ調査の共有方法」で触れているため、本記事では金庫の仕組みの一部を紹介していきます。
ngx_auth_mod は扱う情報を守るのは当たり前として、面倒くさがり屋が作った認証モジュールとなっています。
以降では、開発する上での面倒事やその解決方法を紹介していきます。

まずは nginx の気持ちを感じ取ろう

まずは nginx の認証について調べていきます。
nginx における認証処理を調べていくと、標準モジュールとして ngx_http_auth_request_module が見つかります。
ngx_http_auth_request_module は LDAP などの仕組みを使って認証処理の結果を受け取るだけの機能となっています。
つまり nginx では認証処理を用意しておらず、認証処理と nginx は切り離すようにしているわけです。

これは nginx を動作させる権限で認証処理の責任を持たないようになっており、セキュリティ的な視点では嬉しいことです。
世の中には認証方式として LDAP 以外にも手段はあるため、柔軟に認証処理を nginx と組み合わせることができるようになっています。
つまり nginx で認証の仕組みを導入するためには、認証処理を請け負うツールを用意すればいいことがわかります。

nginx の LDAP 認証モジュールあるけども…

nginx の認証モジュールについては、以下の2つが代表的なものです。

  1. NGINX 3rd Party Modulesとして紹介されているもの
  2. NGINX, Inc.がリファレンス実装として公開しているもの

まず、1番について見てみます。

./configure –add-module=path_to_http_auth_ldap_module
make install

nginx をビルドする際に LDAP 認証モジュールも含めるようになっています。
これでは上述した「認証処理と nginx は切り離すようにしている」nginx の気持ちに則っていません。
--add-module としてビルドすると認証処理が nginx の動作権限で制御されてしまいます。
また、認証モジュールに問題があった際に切り離しに手間がかかり、再度 nginx をビルドし直さなければなりません。
これは運用する上で、手間がかかりそうです。

つぎに、2番を見てみます。
リファレンス実装ということなので、そもそもそのまま使うには疑問があります。
また、動的型付け言語である Python で記述されているため、認証処理で扱うデータのバリデーションに苦労することがわかります。
このことは認証処理を担うため、予期しないデータに対してできるだけ正しく処理を停止するように実装したいわけです。

つまり、自分で作ったほうが楽できそうなことがわかりました。

LDAP の認証処理を作ろう

まずは LDAP について見てみます。
wikipediaには以下のようなことが書いてあります。

ディレクトリ・サービスに接続するために使用される通信プロトコルの一つ。

認証という言葉は書いてありません。
そもそも認証とは「何かによって対象の正しさを確認する行為」を意味するものです。
つまり「何かによって」の部分を「LDAP のデータを使って」に置き換えたものを LDAP 認証と呼んでいるのです。
そのため LDAP に登録されている情報を用いて正しさを確認しているだけにしか過ぎません。

では、LDAPの情報を活用して対象の正しさを確認する方法を考えてみます。

  • 利用者のアカウント名とパスワードで LDAP のバインドができる

非常にシンプルです。
バインドは認証処理をするために LDAP のデータをやり取りするための準備フェーズです。
LDAP にアカウント名とパスワードが登録されていることでバインドが可能です。
組織内で LDAP を用いて人を管理していれば、この準備フェーズだけで組織内外の判断(認証)ができるわけです。

たとえば社内であったとしても、部門ごとに認証の範囲を限定したいこともあります。
その場合は、バインドしたアカウントの所属する部門情報から認証の可否を判断すればいいのです。

他の実装例として以下のようなものがあります。

  1. LDAP にバインドした後に一度アカウントの登録有無を確認する
  2. 再度入力されたアカウントとパスワードを用いてバインドし直す

ngx_auth_mod は、この様なまどろっこしい処理はしません。
他にも匿名バインドを使うようなセキュリティ的に疑問が出てくる概念は当てにしていません。
また LDAP 上のデータを検索できる共有アカウントのような概念も必要ありません。

つまり、組織内の LDAP に自身の情報が登録してあればいいのです。
その登録は LDAP を管理している人に委ね、楽できそうです<3
※ LDAP の管理をしている方々は大変そう…

ngx_auth_mod を利用したコンテンツの閲覧

先述したキーワードも含めて、ここでは ngx_auth_mod を利用した Web コンテンツの閲覧について紹介します。
ngx_auth_mod は nginx の標準モジュールである ngx_http_auth_request_module を前提としています。
Web コンテンツ閲覧者からのリクエストは以下の流れで処理されます。

  1. nginx がユーザから Web コンテンツ閲覧のリクエストを受けとる
  2. ngx_auth_mod が LDAP 情報を利用して認証(・認可)処理を実施する
  3. 認証結果を ngx_http_auth_request_module が受け取り、リクエストに対するレスポンスを判断する

ngx_auth_modの簡易図

簡単に設定できるの?

ここまでシンプルにしているので、楽に Web サーバを構築したいです。
以下のことを行うだけで LDAP 認証付き Web サーバを構築できます。

  1. nginx
    • ngx_http_auth_request_module を含めて nginx をビルド
    • nginx の設定ファイルに ngx_http_auth_request_module の設定を記述
    • systemd で起動する service ファイルを用意
  2. ngx_auth_mod
    • ngx_auth_mod のビルド
    • 認証処理に必要な LDAP の情報を ngx_auth_mod の設定ファイルに記述
    • nginx の設定ファイルに ngx_auth_mod へ認証処理を委ねる設定を記述
    • systemd で起動する service ファイルを用意

より具体的な手順はこちらに記載しています。
認証情報を扱うため、閲覧者からのアカウント名とパスワードをやり取りする通信を SSL/TLS 化しておくことをおすすめします。

ngx_auth_mod は運用面でも楽ができるように作られています。
ngx_auth_mod の処理権限を systemd で指定することになるため、認証処理だけ独立させて ngx_auth_mod をコントロールしやすい状況を実現しています。
このようにしておくことで、問題が発生した際など、認証モジュールだけ切り離したり、差し替えたりできるようになります。

おわりに

本記事では nginx で利用できる LDAP 認証モジュールの ngx_auth_mod について紹介しました。
LDAP 認証処理の仕組みもシンプルにしているため、はじめての方でも理解する面倒事が減っていると思います。
利用するための手数も少なくでき、運用も楽できるとなれば、読者の皆さんも使いたくありませんか??
nginx で LDAP 認証を必要としているのであれば、検討材料の一つとなれば幸いです。

それでは、良い認証ライフを<3

ふぇにっくちゅん(守田 瞬)

2022年06月14日 火曜日

2021年11月にセキュリティ情報統括室に所属。頑固なので、ニックネームだけでもやわらかくひらがなにしてみました。普段はハニーポットで収集したDDoSの発生源であるマルウェアを対象に分析しています。

Related
関連記事