Linux で動く KDC に Windows クライアントを認証

UNIX 系 OS で構築された Kerberos の環境に、Windows クライアントを加える話は、Windows 2000Active Directory が登場したころには、ところどころで聞くことがありました。有名なのは、monyo こと、たかはしもとのぶさんの書いた記事でしょう。

Linux の認証を Active Directory で行なう方法
Windows 2000 マシンの認証を Linux 上の Kerberos サーバで行なう方法

ただ、当時は認証できても、肝心のアプリケーションで対応している物が少なく、「こんな風にしたら、認証通るよ」といった感じでした。

しかし、ふと気がつくと、HTTP や、IMAPPOP3SMTP といったメジャーなプロトコルで Kerberos を生かせる環境が増えてきて、実際に Kerberos 認証をサポートするソフトも、特に海外発祥のマルチ OS 対応ソフトを中心に増えているので、今だったら、シングルサインオン環境の良さを実感出来るのでは、と思って試しました。

Windows での Kerberos 対応

Windows クライアントを Kerberos に対応させる方法として、下記の2つあります。

前者は、究極的には Active Directory を構築し、参加する方法です。後者は、Kerberos 発祥のマサチューセッツ工科大学(MIT)がリリースしているものです。

もし、お金持ちなら Windows Server を買ってきて、Active Directory を構築すれば、参考になる資料もたくさんあるし、簡単です。お金が無いけど時間と知識があるなら、まだアルファ版扱いですが、Samba Ver.4 を使うと、Active Directory 環境は構築できます。

ただ、Active Directory 環境は、単なるシングルサインオンではありません。一番大きいポイントは、各クライアントの各種設定等をシステム管理者が強制できる、グループポリシーの仕組です。Active Directory に参加せずに PC を使っていて、後から Active Directory に参加すると、それまでと同じユーザ名であっても、全く別ユーザ扱いになることに戸惑う人は少なくないと思います。Active Directory によるシングルサインオンの利便性を得るなら、その Active Directory を管理する者に従う必要があります。

元々の Kerberos には、Active Directory のような、強力なポリシー適用の仕組はありません*1シングルサインオンだけの事を考えると、ちょっと大げさな感じがあります。で、純粋に Kerberos のシングルサインオンを利用する仕組も用意されています。その仕組に関しては、後述します。

MIT Kerberos for Windows(以下、KfW)は、UNIX 系 OS で使われる Kerberos の使い方を、Windows で使えるようにしたもので、実際に試してみると、前者の「Windows に元々備わっている機構」を使うより手軽に利用できます。但し、日本語版はありません...。

ksetup vs KfW

Windows ネイティブの Kerberos 対応の設定に使う ksetup というコマンドがあります。Windows の種類やサービスパックの状況等で、最初から入っている場合や、Support Pack をインストールしなきゃいけない場合がありますが、このコマンドを使って、Active Directory じゃない Kerberos 環境を利用できるようになります。

ところが、この ksetup を使った場合と KfW を使った場合で、KDC の設定・管理方法、及び、対応アプリケーションに違いがあります。

アプリケーション側の都合

対応アプリケーションでの違いは、端的に対応アプリケーションが使う API の違いになります。Windows ネイティブの場合は SSPI という API を使う事になります。一方、KfW の場合には、KfW に付属するライブラリを利用する事になります。つまり、アプリケーションが「どっちに対応しているか」がポイントになります。UNIX 系 OS 向けが発祥だったりする場合には、KfW の API を使うほうが実装しやすいし、メンテナンスもしやすい事になります。

しかし、元々 Windows 向けのアプリケーションだと、KfW がインストールされていないと使えないライブラリをあてにするよりも、Windows に最初から用意されている API を使う方が良い、という事になります。また、KfW を使うと、Windows へのログオン後に、改めて KfW を使って Kerberos での認証を受ける必要があります*2

サーバ側の都合

KDC を UNIX 系 OS で作って、UNIX 系 OS 間で Kerberos 認証を使っていると、KfW の方が、UNIX 系 OS 向けと同じ感覚で運用できます。元々、UNIX 系 OS の場合、OS へのログインとは別に、kinit、kdestory というコマンドで、Kerberos へのログイン、ログアウト*3が可能です*4。なので、「Kerberos が使えた!」という実感を手っ取り早く得るには KfW の方が便利です。私が最初に試したのは putty で、パスワードやパスフレーズの入力なしにログインできた時の感動は忘れられません。Thunderbird も設定エディタから Network.auth.use-sspi を false にしてやると、KfW を使う事が可能です。

それ以上に大きいのが、Windows ネイティブの認証を可能にするための条件です。「こうすれば Linux の KDC に ksetup を使って認証できるようになったよ」という記事は多いのですが、その手順の中のどれが必須で、それがオプションなのか、はっきりと書かれている記事を見つける事が出来ませんでした。

ということで、実際にあれこれ試してみました。

Windows ネイティブで Kerberos に対応させるための条件

ホストプリンシパルと名前解決

プリンシパル、という言葉は Kerberos 特有ですが、Active Directory のオブジェクトに近いかもしれません。Kerberos の認証の対象となる物全般を指す言葉で、ユーザだったり、コンピュータだったり、サービスだったりします。

KfW を使う場合、クライアント PC の情報を Kerberos 側に持たせる必要はありません。基本的には、ユーザのプリンシパルと、実際に使おうとしているサービスのプリンシパルがあれば OK です。

ところが、Windows ネイティブの場合、そもそも、そのユーザがその PC を使って良いのかが問われます。実際に KDC が吐き出すログを見ていると、認証要求の後に必ず、クライアント PC のホストプリンシパルに対するチケット要求があるのが分かります。KfW の場合、Windows へのログオンが終わったあとに Kerberos の認証を受けるので、「そのユーザがその PC を使って良いのか」は問われません。UNIX 系 OS をクライアントとして使う場合も同様です。

このため、クライアント PC に対するホストプリンシパルが KDC に登録されている必要があります。で、正式には、ホストプリンシパル名に含まれる FQDN がユニークである事を保証するために、Dynamic DNS でも使ってやるのが良いのだと思いますが、FQDN がきちんと名前解決できる必要は無さそうです。但し、Windows 側の「フルコンピュータ名」からホストプリンシパル名が決まるので、この「フルコンピュータ名」と、KDC に登録されているホストプリンシパルFQDN が合致している必要はあります。

暗号

チケットの暗号化に使える暗号方式に違いがあります。Windows 2000 が登場した当初は、アメリカの暗号輸出規制の影響などもあって、RC4 が使われましたが、XP では DES が、Vista 以降では AES が使えるようです*5

で、この対応している暗号方式の関係で、KDC に保存される鍵が、どの暗号方式の鍵かが問題になります。

/etc/krb5.conf の設定で、デフォルトの暗号方式を変更する、と書かれている記事は多いのですが、肝はむしろ、プリンシパルの鍵がどの形式か、です。

プリンシパル作成時、もしくは、パスワード変更時に「-e」オプションを使うと、作成する鍵の種類が指定できます。

kadmin.local:  addprinc -e des-cbc-crc:normal test
NOTICE: no policy specified for test@EXAMPLE.COM; assigning "default"
Enter password for principal "test@EXAMPLE.COM":
Re-enter password for principal "test@EXAMPLE.COM":
Principal "test@EXAMPLE.COM" created.

確認してみると、下記のようになります。

kadmin.local:  getprinc test
Principal: test@EXAMPLE.COM
Expiration date: [never]
Last password change: Thu Aug 04 14:58:09 JST 2011
Password expiration date: Tue Jan 31 14:58:09 JST 2012
Maximum ticket life: 1 day 00:00:00
Maximum renewable life: 0 days 00:00:00
Last modified: Thu Aug 04 14:58:09 JST 2011 (root/admin@EXAMPLE.COM)
Last successful authentication: [never]
Last failed authentication: [never]
Failed password attempts: 0
Number of keys: 1
Key: vno 1, DES cbc mode with CRC-32, no salt
Attributes:
Policy: default

で、ここで作った鍵と同じ物が使えるように、Windows 側で「ksetup /setcomputerpassword 〜」を実行する訳ですが、この時に保存される物が何か、という事がはっきりしません。どうやら、少なくとも XP では des-cbc-crc が使えるようです。CentOS 5.6 上で、普通にホストプリンシパルをパスワード指定で作ると、デフォルトで作られる鍵は以下のようになります。

  • Triple DES cbc mode with HMAC/sha1, no salt
  • ArcFour with HMAC/md5, no salt
  • DES with HMAC/sha1, no salt
  • DES cbc mode with RSA-MD5, no salt
  • DES cbc mode with CRC-32, Version 4
  • DES cbc mode with CRC-32, AFS version 3

des-cbc-crc に該当しそうなものが最後の2つですが、それぞれ後ろに「Version 4」と「AFS version 3」というのが付いています。一方、先に「-e des-cbc-crc:normal」として鍵を作った時は、「no salt」になってます。

この「normal」の部分は、鍵を生成する際に、パスワード文字列に付けるソルトの種類らしく、「normal」は「default for Kerberos 5」と Kerberos V5 System Administrator’s Guide*6 に書かれています。で、その「default for Kerberos 5」が「no salt」らしい。

ということで、Windows クライアントに対するホストプリンシパルを作成する場合、クライアントが XP であれば、「des-cbc-crc:normal」で鍵を作る必要があるようです。Vista 以降の場合は、「aes128-ctc:normal」とかになりそうな気がしますが、いつか、確認してみたいと思います。

暗号方式で問題になるのは、この「Windows クライアントのホストプリンシパル」だけで、ユーザやサービスのプリンシパルに関しては、デフォルトのままで大丈夫でした。但し、前述のソルトの関係で、結果的に使えるのが rc4-hmac(getprinc の表示で「ArcFour with HMAC/md5」)になってしまいます。

ちなみに、kadmin で鍵を作る際に、どの種類の鍵を作るかは、/etc/krb5.conf の [realms」セクションで「supported_enctypes」に列記すると変更できます。より強力な暗号が使えるようにするためには、これを変更して、Windows からも使える暗号に対する鍵が、デフォルトでも生成されるようにしておくのが良さそうです。

DNS 上での SRV レコードの登録

DNS 上に Kerberos 関係の SRV レコードを追加する、という話がありますが、これは必須ではありません。

そもそも、「ksetup /AddKdc 〜」という手順を見た瞬間、SRV レコードは要らないだろうな、と思いましたが、実際に試して、不要な事を確認しました。おそらく、DNS 側に SRV レコードを用意すれば「ksetup /AddKdc 〜」の手順は不要なんだろうと思います。同様の事は、「ksetup /AddKpasswd 〜」にも言えると思います。

それにしても、やっぱり難しい

とりあえず、自分が試した成功した時のポイントを書くだけのつもりが、ずいぶん長い文章になりました。

自分もまだ、分からない事だらけで、間違ったことを書いている可能性大です。でも、シングルサインオン環境の快感はたまらない(^^;

*1:Kerberos そのものにポリシーという概念はありますが、パスワードの有効期限や長さの話で、デスクトップ環境を強制するような機能ではありません。

*2:Windows ネイティブでの Kerberos 対応の場合、KfW でも自動的にその認証情報を使えるようです。なので、SSPI 非対応の Kerberos 対応アプリケーションがある場合、KfW を入れるだけで、そのアプリケーションも使えるようになると思います。

*3:TGT の取得と破棄、というのが正しい言い方。まぁ、Kerberos の仕組から考えれば、ログイン、ログアウトという言い方が不適切なのは分かるんだけど、そこが敷居の高い原因じゃないかなぁ、と個人的には思います

*4:UNIX 系 OS でも、pam と Kerberos を組み合わせると、OS へのログインと同時に Kerberos に関しても準備完了、という状態にできます。

*5:Windows 7, Windows Server 2008 R2 では、DES がデフォルトでは無効になっているようです(Changes in Kerberos Authentication | Microsoft Docs)。

*6:CentOS 5.6 だと、/usr/share/doc/krb5-server/admin-guide.ps.gz にあります。Postscript ファイルを gzip で圧縮したものなので、展開後、ps2pdf とかで PDF にしておくと良いでしょう。