【図解】初心者にも分かるKerberosとspnegoの仕組み ~SSOのシーケンス,統合windows認証について~

Kerberos とは

Kerberos (読み方:ケルベロス) とはシングルサインオンを実現する『認証・認可プロトコル』です。最新のバージョンは V5 で、RFC4120 にて規格化されています。TCP:88 番ポートを使います。

以下に、Kerberos のコンポーネントと一般的なシーケンスを示します。PC にログイン後、ファイルサーバと LDAP サーバに認証無しで (SSO で) SMB2 (CIFS) によるファイル共有アクセスします。

用語

[KDC = Key Distribution Center]

SSO に利用するチケット (TGT, サービスチケット) を払い出す機能のことです。KDC には AS と TGS が含まれています。

[AS = Authentication Service]

認証を行い、成功の場合には TGT を払い出す機能です。

[TGT = Ticket Granting Ticket]

身分証のことです。TGS に見せることで適切なチケットをもらえます。

[TGS = Ticket Granted Service]

TGT を持っているユーザがあるサービスにアクセスしたいときに、適切な権限でアクセスを許可するサービスチケットを払い出す機能です。

Kerberos のメッセージタイプ

Kerberos のメッセージタイプは RFC4120 の Section 7.5.7 に定められています。

  Message Type   Value  Meaning

  KRB_AS_REQ      10    Request for initial authentication
  KRB_AS_REP      11    Response to KRB_AS_REQ request
  KRB_TGS_REQ     12    Request for authentication based on TGT
  KRB_TGS_REP     13    Response to KRB_TGS_REQ request
  KRB_AP_REQ      14    Application request to server
  KRB_AP_REP      15    Response to KRB_AP_REQ_MUTUAL
  KRB_RESERVED16  16    Reserved for user-to-user krb_tgt_request
  KRB_RESERVED17  17    Reserved for user-to-user krb_tgt_reply
  KRB_SAFE        20    Safe (checksummed) application message
  KRB_PRIV        21    Private (encrypted) application message
  KRB_CRED        22    Private (encrypted) message to forward credentials
  KRB_ERROR       30    Error response

注意点として、KRB_AP_REQ および KRB_AP_REP は Kerberos 規格のメッセージなのですが SMB2 (ファイル) サーバや LDAP サーバ等への認証時に SSO のために利用するものであり、SMB2 や LDAP の認証モジュールがこれらの Kerberos 規格のメッセージを理解する必要があります。

プロトコル毎にこのモジュールを実装するのは大変なので、統一した認証モジュールインタフェースが作られました。それが GSS-API です。

GSS-API はフレームワークであり具体的な機能を提供するものではありません。つまり何かしらの実装が必要です。後述しますが、Microsoft では SPNEGO という GSS-API の実装規格を作り、この上に KRB_AP_REQ / REP を載せています。

Kerberos の特徴

Realm (レルム)

Kerberos では KDC の管理下を識別するために『Realm』という文字列の識別子を付けます。規格上 (RFC4120 Section 6.1) は 3 種類の形式がありますが、一般にはドメイン (FQDN) 形式が使われます。この記事では例えば example.com という Realm にします。

Principal (プリンシパル)

Principal とは、認証や認可を行う対象のことです。主にユーザーアカウントやグループアカウント等を指します。

Principal は [名前]@[Realm] という形式で表現します。つまり Realm が example.com の中に存在する taro.tanaka というユーザの場合、taro.tanaka@example.com という形式になります。

時刻同期

Kerberos で払い出すチケットは無制限であってはなりません。無制限だとチケットが漏れた場合にいつでも使えてしまうからです。

チケットには有効期限がありますから、クライアントとサーバで時間がずれていてはいけません。事実、Kerberos 認証では時間がある程度ずれていると認証に失敗します。

なので Kerberos を補完するために NTP による時刻同期が使われます

Active Directory の Kerberos 実装

Kerberos の一番有名な実装は Microsoft Windows の Active Directory (以降 AD) です。

AD とは、ソリューション名であって、(DNS や DHCP のような) サービス名ではありません。なので、AD を実現するための中心的なサーバを『AD サーバ』と呼ばれることがありますが、実は間違いです。正しくは『ドメインコントローラ』と呼びます。

前述の通り、AD では時刻同期が必須であるため、ドメインコントローラのうちの 1 台 (PDC エミュレータ) は NTP サーバを兼務します。同様に、Kerberos 関連で必須のサービスがいくつかあります。代表的なものとしては LDAP と DNS です。

LDAP

Kerberos を実装するにあたり、ユーザアカウントやグループアカウント、コンピュータアカウント等の Principal (プリンシパル) を保管する場所が必要です。

AD ではドメインコントローラ上に LDAP ツリーを作成し、その中に全ての Principal を格納します

LDAP ツリーは「Active Directory ユーザーとコンピューター」管理ツールで確認できます。コンピュータアカウントについてはデフォルトでは「Computers」という OU に格納され、ユーザーアカウントはデフォルトでは「Users」という OU に格納されます。

以下の例では PC1 というホスト名のコンピュータアカウントと test taro というユーザアカウントを作成しています。

LDAP にはアカウント (Principal) 以外にも環境情報が格納されており、ドメイン管理下の PC は LDAP を使ってアカウントの確認だけでなく、AD 環境の確認も行います (例えばサイト名の確認等)。

AD ではドメインコントローラの管理下を識別するために『ドメイン』という文字列の識別子を付けます。

LDAP ではドメインという概念に相当する DN (DistinguishName) が存在し、これがドメイン名と 1 対 1 でマッピングされます。例えば example.com というドメイン名は LDAP の世界では "DC=example,DC=com" という DN で表現されます。

DNS の SRV レコード

DNS の SRV レコードとは、クライアントアプリケーションが『あるサービスを使いたい』というときにサービスの提供先を調べるためのレコードです。

AD 用として以下のように kerberos と ldap の SRV レコードが用意されています。

_ldap._tcp.dc._msdcs.example.com
_kerberos._tcp.dc._msdcs.example.com

前述の通り、ドメイン管理下の PC は LDAP を使って AD 環境の確認を行いますし、認証時は Kerberos の KDC に認証をしにいきますので、上記 SRV レコードを引いて、LDAP サーバや KDC のホスト名およびその IP を見つけます

ドメインコントローラは一般に DNS サーバも兼務することが多いですので、この場合はドメイン管理下の PC は DNS サーバをドメインコントローラに向けます。

LDAP では DN をドメイン名と対応付けしていたように、Kerberos では『Realm』をドメイン名と対応付けています。つまり『ドメイン名 = example.com』であれば必然的に『Realm = example.com』となります。

なお、Kerberos がドメインコントローラを SRV レコードで探索するのは Kerberos V5 規格 (RFC4120 Section 7.2.3.2) に定められた通りです (Kerberos V4 では設定ファイルに直接ホスト名や IP をしていた)。

余談ですが、ドメインコントローラを複数台で冗長化している場合、SRV レコードのレスポンスはどちらか一方のドメインコントローラを返します。どのように返すかは SRV レコードの設定編集により Priority (優先順位) と Weight (重さ) をデフォルトから変更することで制御できます。デフォルトではいわゆる DNS ラウンドロビンで等負荷分散が行われます。

参考までに SRV レコードのレスポンスのパケットキャプチャを以下に示します。

SPNEGO による SSO

SPNEGO (読み方:スプネゴ) とは Simple and Protected gss-api NEGOtiation mechanism の略で、Microsoft が作成した SSO のためのプロトコルです。GSS-API の上で動作します。

GSS-API は (http, ldap, smtp, pop3, imap4 等の認証が必要な) 通信プロトコルの種類に依存せず、全ての通信プロトコル間で SSO を実現するためのフレームワークです。GSS-API では枠組みだけですので具体的な実装が必要です。その実装の 1 つが SPNEGO なのです。

GSS-API については以下も併せてご参照下さい。

【図解】SASLとGSS-APIの仕組みと違い, LDAPやSMB2での利用例とシーケンス
【図解】SASLとGSS-APIの仕組みと違い, LDAPやSMB2での利用例とシーケンス
SASL とは Simple Authentication and Secur...

統合 Windows 認証

統合 Windows 認証とは、ドメイン認証済のユーザが Web サーバへアクセスする際に、再度認証することなく、Kerberos サービスチケットを使ってそのユーザの権限でログインできる http(s) のための SSO 機能です。

以下にシーケンスを示します。

Windows統合認証に対応した Web サーバでは認証していない状態で http リクエストを送ると、『401 Unauthorized』というステータスコードが返ってきます。

つまり認証が必要だよということを伝えてきます。これに加え、『WWW-Authenticate: Negotiate』というヘッダフィールドも付いてきます。統合Windows認証に対応しているブラウザはこのヘッダフィールドを受け、KDC にサービスチケットを要求 (KRB_TGS_REQ) します。

そして受け取ったサービスチケットを KRB_AP_REQ メッセージに埋め込み、それを SPNEGO 形式で表現した後に Base64 にエンコードし、http の Authorization ヘッダフィールドにセットします。

そして認証が成功した場合は Web サーバから『200 OK』のステータスコードおよびコンテンツファイルと共に、http の WWW-Authenticate ヘッダフィールドに KRB_AP_REP メッセージが同様の形式で返ってきます。

http のリクエストやステータスコード、ヘッダフィールドについてよく分からないという人は以下の記事も併せてご参照下さい。

【図解/初心者向け】httpフォーマットとメソッド/ステータスコード一覧 ~getとpostの違い,よく使われるものとか原因とか~
【図解/初心者向け】httpフォーマットとメソッド/ステータスコード一覧 ~getとpostの違い,よく使われるものとか原因とか~
http のメソッドとステータスコード http はクライアントからメソッドで...

LDAP や SMB2 の SPNEGO による SSO

前述の通り、AD では LDAP を Principal の保管場所として使います。また、グループポリシー等の機能を使うために SMB2 も使います。

このようなプロトコルでいちいち認証していては大変ですので、これらも SPNEGO による SSO で透過的にセキュアな利用を実現しています。

LDAP での利用例

以下に Kerberos 認証をした後に LDAP の BindRequest (認証) ~ SearchRequest (LDAP検索) の流れのパケットキャプチャを示します。

[ LDAP サーバへの BindRequest (認証) ]

SASL + GSS-API + SPNEGO (Kerberos) で Kerberos のチケットを提示

[ LDAP サーバからの BindResponse (認証成功) ]

[ LDAP サーバへの SearchRequest (検索) ]

認証成功後の通信にも SASL + GSS-API のレイヤーにより通信のセキュリティを保護している様子が確認できます。

SMB2 での利用例

以下に SMB2 での認証~ 共有アクセスの様子をパケットキャプチャで示します。

[ SMB2 ファイルサーバへの Session Setup Request (認証) ]

SASL はありませんが、GSS-API + SPNEGO (Kerberos) を使っています。

[ SMB2 ファイルサーバへの Session Setup Request (認証) ]

SMB2 としての Session Setup Request (認証) が成功していること、および GSS-API + SPNEGO が使われていることが分かります。

[ SMB2 ファイルサーバへの Tree Connect Request (共有アクセス要求) ]

GSS-API は出てきません。このあたりは SMB2 のプロトコルおよびアプリケーションの作り方に依るためです。