そろそろLDAPにしてみないか?

第4回UNIXアカウント以外でLDAP

FTPアカウントにLDAP

LDAPに対応しているアプリケーションは数多く存在するため、何から紹介すればよいのか迷ってしまうのですが、わかりやすさ、容易に構築できるという点で今回はFTPサーバ+LDAPサーバの組み合わせを紹介してみたいと思います。⁠えー? 今さらFTPサーバ?」なんて言わないで最後まで読んでみてください(笑)

通常であれば、あるユーザがFTPサービスを利用する場合、そのアカウント情報は/etc/passwd/etc/shadowに登録されている必要があります。

しかし、ユーザにFTPのみを使用させたい場合、/etc/passwdなどにアカウントが存在してしまうと都合が悪いことがあります。なぜなら/etc/passwdに登録されているユーザ情報はgetpwent(3)などにより、さまざまなアプリケーションから参照されるためです。ldapuserというユーザにはFTPサービスのみ提供したいのに、ldapuser@example.comというメールアドレス宛にメールを送ると/var/mail/ldapuserというメールボックスが作成されては、都合が悪い・ですよね。

さて、LDAPサーバ内にFTPアカウントを作成するためには、いくつかの方法が考えられます。1つめの方法はPAMを利用することです。多くの一般的なFTPサーバ、たとえばvsftpdはPAMによる認証に対応しているため、この方法を用いると、特別な設定をすることなくFTPアカウントを使用することができます。

開発者にとってのメリットとしては、ソフトウェアをPAMにさえ対応させれば自動的にLDAP認証(pam_ldap)にも対応できることが挙げられます。一方、認証関連の設定は/etc/ldap.confを用いて行うことになるため、設定の影響範囲が大きいことがデメリットとも言えるでしょう。例えばvsftpdの設定を変更するつもりで/etc/ldap.confを編集しても、その設定がpam_ldapを使用するすべてのソフトウェアに反映されてしまいます。

もう1つの方法は、PAMとは独立してLDAP内にFTP専用のアカウントを作成することです。このようなアカウントを作成しておけば、仮にFTP専用ユーザのユーザ名とパスワードが漏洩してしまっても、その被害の影響範囲はFTPサービスのみに限定されます。アカウント情報を勝手に使われてしまっても用途はFTPに限定されているため、その情報を元にSSHログインできるわけではありません。もちろん開発者は各種LDAP関数を活用してソフトウェアを構成しておく必要があります。Proftpdはこの方式に対応していますが、先ほど例として挙げたvsftpdには、残念ながらこの実装が含まれていません。

それではFTP専用アカウント、ということを前提として、FTP認証用の属性などを設計してみましょう。最低限の情報としては表1のようなものになると思います。

表1 必要な属性
必要な項目必要な理由
ユーザ 認証に使用するためftpuser
パスワード認証に使用するためftppass
ホームディレクトリログイン時のホームディレクトリ/home/ftproot/ftpuser
UID番号ファイル作成時などに使用される10000
GID番号ファイル作成時などに使用される10000
グループ名(必要に応じて)ls-laなどでGID番号だけでなくグループ名が表示されるようにsales

標準スキーマで用意されている属性を使えば、ftpuserのエントリはリスト1のようになるはずです。

リスト1 LDIFで表現
# FTPグループ
dn: cn=sales,ou=FTPGroup,dc=example,dc=com
cn: sales
gidNumber: 10000

# FTPユーザ
dn: uid=ftpuser, ou=ftpuser, dc=example, dc=com
uid: ftpuser
userPassword: ftppass
homeDirectory: /home/ftproot/ftpuser
uidNumber: 10000
gidNumber: 10000

とりあえずは必要な属性のみを列挙してみましたが、すでに皆さんご存じのように、ある属性を使用するにはそれが属するobjectClassを定義する必要があります。上記のFTPグループではcngidNumber属性を使用しています。ということで、gidNumberというキーワードを/etc/openldap/schema以下からgrepしてみれば、目的のobjectClassがわかります。

gidNumberが含まれるobjectClassは次のように定義されています。

objectclass ( 1.3.6.1.1.1.2.2 NAME 'posixGroup' SUP top STRUCTURAL
        DESC 'Abstraction of a group of accounts'
        MUST ( cn $ gidNumber )
        MAY ( userPassword $ memberUid $ description ) )

ということで、cnとgidNumberが含まれている今回のエントリにobjectClass: posixGroupを追加しておくだけで良さそうです。グループではなくユーザ部分はどうなるでしょうか? 今度はuidNumberをキーワードにschemaディレクトリを検索してみます。次のようなエントリが見つかりました。

objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top AUXILIARY
        DESC 'Abstraction of an account with POSIX attributes'
        MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
        MAY ( userPassword $ loginShell $ gecos $ description ) )

このposixAccountというobjectClassを使用するためには、先ほど列挙した内容以外にuid属性が必要となります(uid属性がMUSTと定義されているため⁠⁠。さらに、このobjectClassはtopから派生し、補助オブジェクト(AUXILIARY)であることもわかります。補助オブジェクトとなっているobjectClassは単体で宣言することができません。補助オブジェクトはSTRUCTURALであるaccountなどのobjectClassと一緒に使用する必要があります。

よって、これらをまとめるとリスト2のようなLDIFを作成すれば良いことがわかります。userPassword属性については、例のごとくslappasswdコマンドにて作成された文字列を使用しています。

リスト2 ftpuser.ldif
dn: dc=example,dc=com
objectClass: dcObject
objectClass: organization
dc: example
o: example

dn: ou=FTPGroup,dc=example,dc=com
objectClass: organizationalUnit
ou: FTPGroup

dn: ou=FTPUser,dc=example,dc=com
objectClass: organizationalUnit
ou: FTPUser

dn: cn=sales,ou=FTPGroup,dc=example,dc=com
objectClass: posixGroup
cn: sales
gidNumber: 10000

dn: cn=ftpuser, ou=FTPUser, dc=example, dc=com
objectClass: posixAccount
objectClass: account
cn: ftpuser
uid: ftpuser
userPassword: {SSHA}uuj0BIaaMIPrmjBZy8NBD0kTB7XSCSLb
homeDirectory: /home/ftproot/ftpuser
uidNumber: 10000
gidNumber: 10000

スキーマファイルの読み方に関しては、今後の連載で紹介していくつもりですので、今回はこのような簡単な説明でお許しください。

FTPサーバの設定

冒頭で述べたよう、FTPサーバを構築するためにはいくつかの選択肢が存在しますが、十分にLDAP認証をサポートしていると言えるのがProftpdです。CentOSではyumコマンドで直接導入することができないため、今回は図1のようにソースファイルからインストールを行いました。

図1 Proftpdのインストール
% tar xfv proftpd-1.3.0a.tar.bz2
% cd proftpd-1.3.0a
% ./configure --with-modules=mod_ldap
% make
# make install

proftpdの設定

ここでは必要最低限の設定のみを行います。

リスト3 /usr/local/etc/proftpd.conf
DefaultServer      on
RequireValidShell  off
LDAPServer         10.0.100.10
LDAPDoAuth         on "dc=example,dc=com" "(&(cn=%v)(objectClass=posixAccount))"
LDAPDoUIDLookups   on "ou=FTPUser,dc=example,dc=com"
LDAPDoGIDLookups   on "ou=FTPGroup,dc=example,dc=com"

Proftpdはさまざまなオプションを備えていますので、実際のサーバ環境に適用する場合にはそれ以外の項目にも十分注意してください。今回の必要条件としては次の通りです。

  • LDAP内のFTPユーザにシェルは必要ないためRequireValidShell offを定義
  • LDAPサーバの場所をLDAPServerで定義する
  • 検索ベースをdc=example,dc=comとし、検索条件を(&(cn=ユーザ名)(objectClass=posixAccount))とする(そこで見つかったユーザのDNとFTPセッションで入力されたパスワードを元に再度バインドを行い認証する)
  • ou=FTPUser,dc=example,dc=comツリー以下よりUID情報の検索を行う
  • ou=FTPGroup,dc=example,dc=comツリー以下よりGID情報の検索を行う

設定ファイル中のLDAPDoUIDLookupsとLDAPDoGIDLookupsは必須ではないのですが、このオプションが無い場合にFTPセッション中でls-laなどすると、次のように所有者と所有グループが不明な状態となります。

> ls -la
drwxr-xr-x   2 (?)      (?)          4096 Sep 11 07:48 .
drwxr-xr-x   3 root     root         4096 Sep 11 07:47 ..

これでは気持ち悪いので、それぞれのオプションを有効にしておく方が良いでしょう。そうすることで、

> ls -la
drwxr-xr-x   2 ftpuser  sales        4096 Sep 11 07:48 .
drwxr-xr-x   3 root     root         4096 Sep 11 07:47 ..

このような表示となりすっきりします。設定が終わったら図2のようにproftpdを起動して、クライアントから接続を行ってみてください。うまくいかないようであれば、proftpdをproftpd -d 10 -nのような形で起動させつつ認証を行い、トラブルシューティングを行います。LDAPサーバ側のログを確認することも忘れないでください。

図2 proftpdの起動
# /usr/local/sbin/proftpd

まとめ

Proftpdには今回紹介したオプション以外にも、基本的なところではLDAPProtocolVersion、LDAPQueryTimeoutなどがあります。おもしろいところでは、LDAP中に数値で指定されたQuotaを参照するためのLDAPDoQuotaLookupsや、ホームディレクトリを自動作成させるためのLDAPGenerateHomedirなど、ほかにもさまざまなものが用意されています。http://www.proftpd.org/docs/directives/linked/by-name.html

ftpEnabledなどといった独自の属性を定義して、

LDAPDoAuth         on "dc=example,dc=com" "(&(cn=%v)(objectClass=posixAccount)(ftpEnabled=1))"

とするのもおもしろそうですね。さまざまなオプションを組み合わせて、FTPとLDAPの連携を堪能してみてください!

おすすめ記事

記事・ニュース一覧