最近のMTA(Mail Transfer Agent)はLDAPを参照して、宛先を決定することができるようになっています。またIMAPサーバなどでもLDAPを参照してメールボックスを決定することができるようにもなっています。これらの設定の仕方について簡単に説明します。
Debian 2.2(potato)では、標準のMTAであるeximが既にLDAPをサポートしています。なお開発版のsidではpostfixなどもLDAPサポートが追加されています。ここではpotatoにあるeximでLDAPを使う場合について簡単に説明します。なお、eximを普通に動かす方法についてはここでは説明しません。ここの例ではeximはexample.jpドメインのメールを処理するものとします。
eximでLDAPを参照する一番簡単な方法はaliasfileでLDAPを見るように設定することです。
exim.confにリスト1のような設定をsystem_aliases:の定義の後ろに追加します。これによりaliasfileドライバを使うldap_aliases:が定義されます。普通のaliasでは検索タイプ(search_type)はlsearchなどを使いますが、ここではldapもしくはldapmを使います。ldapmを使うと複数のエントリからの結果も使うことができるという点がldapと違います。この設定で$local_part@example.jp宛のメールはlocalhostのポート389のLDAPサーバでuid=$local_part,ou=People,dc=example,dc=jpを検索して、そのmailアトリビュートをaliasを展開したものとして使うようになります(図1)
ldap_aliases: driver = aliasfile search_type = ldapm query = "ldap://localhost:389/uid=$local_part,ou=People,dc=example,dc=jp?mail?base?"
| | $local_part@example.jp | | | ----- exim ----- | | | v | ldap_aliases: | ---- query ---------------------------------------------> | basedn = uid=$local_part,ou=People,dc=example,dc=jp | scope = base LDAP server | attribute = mail | <-------------------------------------------------------- | | | v | uid=$local_part,ou=People,dc=example,dc=jpの | mailアトリビュートの値 |
queryに指定するのはRFC2255「The LDAP URL Format」に従った記述方法でLDAPの検索方法を指定します。
ldap://localhost:389/uid=$local_part,ou=People,dc=example,dc=jp?mail?base?
この例では次のような意味になります。
uid=$local_part,ou=People,dc=example,dc=jp が検索ベースになる
ここで$local_partはうけとったメールのローカルパートの文字列に eximがおきかえます。
さらに?の後のbaseというのは検索の範囲を意味しています。baseというのは
検索ベースのディレクトリエントリだけを検索することを意味しています。
つまり上のURLは以下のようなコマンドの実行結果と同等の意味になります。
% ldapsearch -x -h localhost -p 389 -s base -b "uid=$local_part,ou=People,dc=example,dc=jp" '(objectclass=*)' mail
ここで-s baseというのが検索範囲を指定するためのオプションです。
次のような書きかたもできます。
ldap:///dc=example,dc=jp?mail?sub?uid=$local_part
この場合は以下のような意味になります。
LDAPサーバはデフォルトを使う。
特に指定がなければ普通はlocalhost:389が使われます。後述するようにldap_default_serversで設定できます。
なお、この場合ldap_default_serversに次のように指定しておくとLDAPサーバとしてldap1.example.jpのポート10389とldap2.example.jpのポート389(ldapのデフォルトポート)を使うようになります。ldap_default_serversはコロンで区切るのでポートを指定する時はコロンを二つ::使わなければなりません。
ldap_default_servers = ldap1.example.jp::10389:ldap2.example.jp
このURLをldapsearchで同じように検索するとすると次のようになります。
% ldapsearch -x -b "dc=example,dc=jp" "uid=$local_part" mail
eximが期待するような情報をLDAPに登録する必要があります。リスト1のような設定にする場合uid=$local_part,ou=People,dc=example,dc=jpがmailという属性をもてばいいことになります。
mailという属性はcore.schemaにリスト2のように定義されているのでこれを使うことができます。このmailを含むようなobjectclassの定義はinetorgperson.schemaにリスト3のように定義されているのでこれを使うことにします。
attributetype ( 0.9.2342.19200300.100.1.3 NAME ( 'mail' 'rfc822Mailbox' ) DESC 'RFC1274: RFC822 Mailbox' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
objectclass ( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RFC2798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL MAY ( audio $ businessCategory $ carLicense $ departmentNumber $ displayName $ employeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ initials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo $ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIdentifier $ preferredLanguage $ userSMIMECertificate $ userPKCS12 ) )
例えばfoo@example.jpのメールをfoo@example.netに転送する場合、uid=foo,ou=People,dc=example,dc=jpはリスト4のようなLDIFにしておけばいいことになります。このようにobjectclassとしてinetOrgPersonを追加して、mail: foo@example.netを追加します。さらに、objectclass inetOrgPersonはsn属性(surname; 姓)も必要とするのでsn: fooを追加してあります。このように追加するためのldapmodifyに入力するためのLDIFはfoo-mail.ldif(リスト5)のようになります。
dn: uid=foo,ou=people,dc=example,dc=jp uid: foo objectClass: posixAccount objectClass: shadowAccount objectClass: inetOrgPerson homeDirectory: /home/foo cn: foo bar sn: foo shadowMin: 0 shadowMax: 99999 shadowWarning: 7 uidNumber: 1001 gidNumber: 1001 loginShell: /usr/bin/zsh gecos: foo,0000,1111,2222 shadowLastChange: 11588 mail: foo@example.net
dn: uid=foo,ou=People,dc=example,dc=jp changetype: modify add: objectclass objectclass: inetOrgPerson - add: sn sn: foo - add: mail mail: foo@example.net
まずinetOrgPersonを使うのでinetorgperson.schemaをincludeするようslapd.confにリスト6の行を追加する必要があります。
include /usr/local/etc/openldap/schema/inetorgperson.schema
追加したらslapdを起動しなおします。
# kill `cat /usr/local/var/slapd.pid` # /usr/local/libexec/slapd
それからldapmodifyでディレクトリエントリの修正をします。
% ldapmodify -D 'cn=Manager,dc=example,dc=jp' -W -f foo-mail.ldif Enter LDAP password: modifying entry "uid=foo,ou=People,dc=example,dc=jp"
これでfoo@example.jp宛のメールが届くと、exim.confで設定したldap_alias:のqueryで指定してLDAP URLを使ってmailを検索して得られた値、つまりuid=foo,ou=People,dc=example,dc=jpのmailアトリビュートの値 foo@example.netにメールを送るようになります。 一つのディレクトリエントリに複数のmailがあればそれが展開されてそれぞれの宛先に送られるようになります。従って例えばリスト7のようなディレクトリエントリの場合foo@example.jpはfoo@example.netとfoo@example.orgの二箇所に送られるようになります。これを応用すればグループに対するメールや簡単なメイリングリストのメンバー管理もLDAPで行なえるようになります。この場合はobjectclass: nisMailAliasで、rfc822MailMemberというアトリビュートを使うほうがいいのかもしれません。これらはmisc.schemaに定義されているのでこれをincludeして使うことになります(リスト8)。
dn: uid=foo,ou=people,dc=example,dc=jp uid: foo objectClass: posixAccount objectClass: shadowAccount objectClass: inetOrgPerson homeDirectory: /home/foo cn: foo bar sn: foo shadowMin: 0 shadowMax: 99999 shadowWarning: 7 uidNumber: 1001 gidNumber: 1001 loginShell: /usr/bin/zsh gecos: foo,0000,1111,2222 shadowLastChange: 11588 mail: foo@example.net mail: foo@example.org
include /usr/local/etc/openldap/schema/misc.schema
eximとcourier-imapを使うとLDAPでメールアカウントの管理をすることができます。
OpenLDAP-2.0.18ではmisc.schemaにmailLocalAddressなどがあるのでこれを使うことにします(リスト9)。残念ながらこのアトリビュートをもつinetLocalMailRecipientにはまだOID(Object Identifier)がわりあててられていないので、そのままでは使うことができません。現状ではschemacheck offにすることでobjectclassによる持つことのでくる属性のチェックをはずす必要があります(リスト10)。
attributetype ( 2.16.840.1.113730.3.1.13 NAME 'mailLocalAddress' DESC 'RFC822 email address of this recipient' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
include /usr/local/etc/openldap/schema/misc.schema schemacheck off
まず、LDAPでどのように情報を持つかを決める必要があります。ここでは図2のようにすることにします。mailLocalAddress属性が受信するe-mailアドレスです。このアドレスにきたメールはmail属性で示されるディレクトリにMaildir形式でスプールします。userPasswordアトリビュートはこのスプールに対するIMAPでアクセスする時のパスワードです。なお、courier-imapはLDAPを参照する時にもホームディレクトリを必要とするのでhomeDirectoryアトリビュートに指定しておきます。メールは配送とLDAPの関係は図3のようになります。
dn: uid=bar,ou=people,dc=example,dc=jp uid: bar objectClass: top cn: foo bar mailLocalAddress: bar@example.jp mail: /var/local/maildir/bar// homeDirectory: /var/local/maildir userPassword: {CRYPT}I.oaTeBKQv5j.
| incoming mail | | | | | V LDAPサーバ | exim | | | | | ldap_aliases | | による配送先 ----------------------------------------->| | の検索 base dc=example,dc=jp | | | search | | | mailLocalAddress=$local_part@example.jp | | | <-----------------------------------------| | | mailアトリビュート | | | | | | | | address_directoryによりMaildirとして配送 | | | | | | | | V | | /var/local/maildir/$local_part | | ^| | | || | | || | | |V | | mailアトリビュートで得られたディレクトリにアクセス | | ^ homeDirectory, mail | | | <-------------------------------------| | | | | | bindできるか? | | authldapによる認証 ------------------------------------->| | ^ dc=example,dc=jp | | | mailLocalAddress=ログイン名@example.jp | | | | | courier-imap | ^ | | | | | IMAP user
まず、スプールディレクトリを作成します。ここでは/var/local/maildirに全員のメールスプールを作ることにします。courier-imapで必要としているMaildir形式のディレクトリを作るにはcourier-imapパッケージについてくるmaildirmake.courier-imapコマンドを使います。それから実際のアカウントなしでメールのみを読むことになるので、これらのMaildirはlistユーザの所有にしてアクセス権限はlistユーザだけにしておきます。
mkdir /var/local/maildir maildirmake.courier-imap /var/local/maildir/bar chown -R list.list /var/local/maildir/bar
exim側ではexim.confでリスト11のように設定しておきます。
address_directory: driver = appendfile no_from_hack prefix = "" suffix = "" maildir_format ldap_aliases: driver = aliasfile file_transport = address_file directory_transport = address_directory user = list search_type = ldapm query = "ldap:///dc=example,dc=jp?mail?sub?mailLocalAddress=$local_part@example.jp"
デフォルトではaddress_directoryはmaildir_formatが有効になってないのでこれを有効にします。これによりaliasでディレクトリを指定した時にそのディレクトリをMaildir形式として新規メールをスプールしていくことができるようになります。
次にldap_aliasesでLDAPの情報でメールの配送先を決めます。directory_transport = address_directoryをいれておくことでLDAPで引いてきた結果がディレクトリだと上で設定したようにaddress_directoryを使うことでそのディレクトリをMaildir形式として新規メールをスプールすることになります。user = list でMaildirのディレクトリの所有者を指定しています。これによりスプールに新規メールを書きにいく時にはlistユーザ権限で書きこみにいきます。queryにLDAPの検索方法を指定しておきます。
query = "ldap:///dc=example,dc=jp?mail?sub?mailLocalAddress=$local_part@example.jp"
このqueryはデフォルトのLDAPサーバ(localhost:389)にdc=example,dc=jpを検索ベースとしてmailLocalAddressが$local_part@example.jpであるディレクトリエントリを探してそのディレクトリエントリのmail属性を検索結果として使うということを意味しています。 このeximにbar@example.jp宛のメールがくれば、LDAPで図2のエントリが検索でひっかかって、そのmail属性の値/var/local/maildir/bar//が配送先に決定します。これはディレクトリなのでldap_aliasesのdirectory_transportで指定しているaddress_directoryの記述に従い/var/local/maildir/bar/にMaildir形式で新規メールをスプールします。この時ldap_aliasesでuser = listと指定しておいた通りlistユーザ権限で/var/local/maildir/bar/以下に書きこみにいきます。
このようにexim側の配送を設定します。
eximでメールを/var/local/maildir/以下に配送できるようにしても、これがユーザから読めるようになっていなければ意味がありません。ここでは例としてcourier-imapを使い、IMAPでアクセスできるようにしてみましょう。courier-imapにはauthldapをいうLDAPを使う認証モジュールがあるのでそれを使うことにします。
courier-imapのdebianパッケージを使っている場合、/etc/courier-imap.configでどの認証モジュールを使うかをAUTHMODULESで定義します。ここではLDAPによる認証を使うのでリスト12のようにAUTHMODULESにauthldapを指定します。
AUTHMODULES="authldap"
authldapの設定は/etc/courier-imap.authldaprcによりおこないます(リスト13)。
LDAP_SERVER 192.168.0.1 LDAP_BASEDN dc=example,dc=jp LDAP_AUTHBIND 1 LDAP_MAIL mailLocalAddress LDAP_DOMAIN example.jp LDAP_GLOB_UID list LDAP_GLOB_GID list LDAP_HOMEDIR homeDirectory LDAP_MAILDIR mail
IMAPでログインする時にそのユーザはどのディレクトリエントリに対応するかを決定するためにLDAP_MAIL属性が検索されます。IMAPでログインする時に、ユーザ名で@移行を付けなかった場合LDAP_DOMAINで指定したドメインが追加されて検索されます。LDAP_DOMAINを定義していない時はドメイン部分は*が追加されて検索されます。
つまりLDAPの検索式としては次のようになります。 <LDAP_MAILで指定したアトリビュート>=<IMAP login名>@<LDAP_DOMAINの値> IMAP login名に@が含まれている場合はLDAP_DOMAINによる補完はおこなわれなくて次のようになります。 <LDAP_MAILで指定したアトリビュート>=<IMAP login名>
ここではLDAP_MAILをmailLocalAddress、LDAP_DOMAINをexample.jpにしているのでLDAPで次のように検索することになります。
mailLocalAddress=<IMAP login名>@example.jp
もしIMAPでbarでログインすると次のように検索します。
mailLocalAddress=<IMAP login名>@example.jp
bar@example.netでログインすると LDAP_DOMAINのexample.jpを無視して次のように検索します。
mailLocalAddress=bar@example.net
リスト13のようにcourier-imap.authldaprcに設定したあと/etc/courier-imap.configの最後のIMAPDSTARTをYESにして(IMAPDSTART=YES)から、/etc/init.d/courier-imap start で起動します。
Debian 2.2にあるpostfixパッケージは古いのでまだLDAPサポートはありませんが、開発版の方ではLDAPサポートがついたpostfixになっています。最近のパッケージではpostfix-ldapというパッケージをインストールするとLDAPサポートが使えるようになります。これを使うとpostfixでもLDAPをaliasの一つとして使うことができるます(リスト14)。
alias_maps = hash:/etc/aliases, ldap:ldapsource
このようにldap:ldapsourceと記述することでldapsourceで記述される設定でLDAPからaliasを検索することができます。ここのldapsourceという文字列で、ここで使うLDAPの検索をどうするかを設定するパラメータのプレフィクスを決めます。ldap:ldapsourceとした場合ldapsourceではじまるパラメータが使われることになります。ldap:ldapaliasなどとするとldapaliasではじまるパラメータを使うことになるわけです。
ldap:ldapsourceだとするとLDAPに関するパラメータはリスト15のように/etc/postfix/main.cfで設定します。
ldapsource_server_host = localhost ldapsource_server_port = 389 ldapsource_search_base = dc=example,dc=jp ldapsource_query_filter = (mailLocalAddress=%s) ldapsource_result_attribute = mail ldapsource_scope = sub ldapsource_bind = yes ldapsource_bind_dn = "" ldapsource_bind_pw = ""