2022/08/07 AzureCentOS7.9
2022/08/07 RockyLinux8.5





ActiveDirectoryと連携するメールサーバ(SSSDとMailDir)

LinuxのメールアカウントをActiveDirectoryで管理する方式です。

1.メールサーバのアカウントをAD上のユーザーと連携できる
2.メールのパスワードをActiveDirectoryで統一管理

などのメリットがあります。
複雑なことに思えますが、やっていることはシンプルで、Linuxのユーザー認証のときローカルユーザーに加えて、ActiveDirectory上もチェックする。ということです

本項では、PostfixにMailDir形式を使用する場合の手順です。
Maildir形式を使用する場合の手順は別項「ActiveDirectoryと連携するメールサーバ(SSSDとMBox)」を参照してください。


認証の仕組み



以前は連携にWinbindを使用した連携を紹介しましたが、Redhatの公式でもActiveDirectoryとの連携にはrealmdとsssdというサービスを使用することとなっています。

Redhat 「realmd を使用した Active Directory ドメインへの接続

sssdは、外部の認証機構(ディレクトリ)へ認証を求める仕組みです。
realmdは、sssdが行うActiveDirectoryとの認証設定を簡素化します。
realmdでは、ドメインクライアントとしてSSSDとWinbindのどちらも使えます。

いまのモダンな環境では、Winbindを使用するのではなく、ActiveDirectoryを外部認証ディレクトリと捉えて、sssdを使用するということなのでしょう。
RHELでの認証と認可の構成」という技術文書に、「SSSDの仕組み」という項目があり、そこに詳しく説明されています。


構成に必要なものは3つです。
・構築済みのActiveDirectory
・意図した通りに動作するメールサーバ(SMTP・POP)
・sssdとrealmd


1.メールサーバの構築
2.メールの通信試験
3.ドメイン参加の事前準備
4.ActiveDirectoryへドメイン参加
5.AD上の認証範囲を制御する
6.キャッシュの削除





1.メールサーバの構築

MailDir方式とは、1メール1ファイルでディレクトリに保存する方式です。
mbox方式とは、メール全てを1つのファイルに保存する方式です。postfixのデフォルトです。

ActiveDirectoryと連携する場合、MailDirのほうが考慮することが少なく、簡単です。
新規に構築する場合はMailDirを選択する方が無難でしょう。

インストール
#sudo yum install postfix dovecot


Postfixの設定
#sudo vi /etc/postfix/main.cf

mydestination = $myhostname, localhost.$mydomain, example.local (追加)
inet_interfaces = all
inet_protocols = ipv4
mynetworks = localhost (ここではメールボックス用サーバとして)
#home_mailbox = MailBox (コメントアウト確認)
mail_spool_directory = /var/mail/  末尾へスラッシュを加えてMailDir形式へ設定



Dovecot設定
各種コンフィグファイルを設定し、POP3のプレーンテキストで認証できる構成とします。
/etc/dovecot/dovecot.conf の編集

listen = *       :: を削除して*だけに変更
protocols = pop3       imap lmtpを削除してpop3だけに


/etc/dovecot/conf.d/10-auth.conf の編集

disable_plaintext_auth = no


/etc/dovecot/conf.d/10-mail.conf の編集

mail_location = maildir:/var/mail/%u


/etc/dovecot/conf.d/10-ssl.conf の編集

#ssl = required    #コメントアウト


メールが着信したとき、メールスプールにMailDirのディレクトリが生成されるようにするため、書き込み権を追加します。
#sudo chmod o+w /var/spool/mail
なお /var/mail はシンボリックリンクなので、指定してもアクセス権は追加できません。


最後にサービスの起動と設定をします。
#sudo systemctl restart postfix
#sudo systemctl start dovecot
#sudo systemctl enable postfix
#sudo systemctl enable dovecot
もちろん、必要に応じてファイアウォールで25/110ポートを開放しなければいけません。

#firewall-cmd --get-active-zones
public
  interfaces: enp0s3

現在のFirewallゾーンで、SMTP/POP3サービスが許可されているか確認
#firewall-cmd --list-all
public (active)
(略)
  services: dhcpv6-client ssh
  ports:
(略)

現在のFirewallゾーンにSMTPとPOP3サービス許可を追加
#firewall-cmd --add-service=smtp,pop3
success

#firewall-cmd --get-services
public (active)
(略)
  services: dhcpv6-client smtp pop3 ssh
  ports:
(略)

設定を永続化
#firewall-cmd --runtime-to-permanent
success




2.メールの通信試験

ユーザーを作成し、試験します。
#sudo useradd -s /sbin/nologin user1
#sudo passwd user1

仮メールを送信し、ディレクトリが生成されているか確認します。
#mail -s TestMail user1@example.local
test (本文)
. (ドットで修了)

#ls /var/mail
 user1
popでメールが取り出せるか、メーラーかtelnetで確認します。
#telnet localhost 110
user user1
+OK
pass user1P@ssword
+OK Logged in.
list
+OK 1 messages:
1 823
.
retr 1
(メールの内容の表示)
この時点でメールが正常に送受信できない場合、
・サービスが起動していない
・ファイアウォールでポートが締まっている
・メール送信が成功していなくて、まだメールが1通もない
・すでに同名のメールファイルが/var/mailに存在している
が考えられます。




3.ドメイン参加の事前準備


前提条件として、DNSの設定がドメインコントローラに向いている必要があります。


必要なパッケージはまとめて事前にインストールしておきます。
#sudo yum install realmd sssd adcli
パッケージが不足していると、realmコマンドを使ってActiveDirectoryへドメイン参加する際、
「 realm: Couldn't join realm: Necessary packages are not installed: oddjob, oddjob-mkhomedir, sssd, adcli 」
と怒られます。
このうち、oddjob、oddjob-mkhomedirは、realmのインストール時に依存関係で解決されます。


インストール後、まずはドメインコントローラへ通信確認をします。
DNSの指定がADへ向けられている必要があります。
#realm discover dc1.example.local

example.local
  type: kerberos
  realm-name: EXAMPLE.LOCAL
  domain-name: example.local
  configured: no
  server-software: active-directory
  client-software: sssd
  required-package: oddjob
  required-package: oddjob-mkhomedir
  required-package: sssd
  required-package: adcli
  required-package: samba-common-tools





4.ActiveDirectoryへドメイン参加


ActiveDirectoryへドメイン参加します。

まずはLinuxのホスト名から変更しておきましょう。

realmでドメイン参加すると、現在のホスト名がActiveDirectory上のメンバサーバ名となります。
(Winbindのときはsmb.confで指定したnetbiosNameがメンバサーバ名に使用されました)
ドメイン参加した場合、ホスト名は重要になってくるので、忘れず変更しておきます。
#sudo hostnamectl set-hostname mailsv
#hostname
mailsv
#cat /etc/hostname
mailsv


次にドメイン参加します。
ADサーバのfqdnを入力します。無論、DNSがADサーバへ向いている必要があります。
ドメインのAdministratorのパスワードが尋ねられます。
#sudo realm join dc1.example.local
Password for Administrator: *****

ドメインのアカウントが登録されました。




うっかり間違えたホスト名でドメイン参加してしまった場合、後からホスト名を変更してもAD上のコンピュータアカウント名には、反映されませんでした。
一度ドメインから離脱して、ホスト名変えてから再度参加します。
間違えた時は、一度離脱して再度参加

#sudo realm leave
#sudo hostnamectl set-hostname mailsv
#sudo realm join dc1.example.local
Password for Administrator: *****


参加したドメイン情報が表示できるか確認します。
#sudo realm list
example.local
  type: kerberos
  realm-name: EXAMPLE.LOCAL
  domain-name: example.local
  configured: kerberos-member
  server-software: active-directory
  client-software: sssd
  required-package: oddjob
  required-package: oddjob-mkhomedir
  required-package: sssd
  required-package: adcli
  required-package: samba-common-tools
  login-formats: %U@example.local
  login-policy: allow-realm-logins

次に、/etc/krb5.confへ、レルム情報を追加します。
#vi /etc/krb5.conf

includedir /etc/krb5.conf.d/

includedir /var/lib/sss/pubconf/krb5.include.d/
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
# default_realm = EXAMPLE.COM
 default_ccache_name = KEYRING:persistent:%{uid}

※defaultに参加したドメインが自動的に追加されている
 default_realm = EXAMPLE.LOCAL

[realms]
# EXAMPLE.COM = {
#  kdc = kerberos.example.com
#  admin_server = kerberos.example.com
# }

※EXAMPLE.LOCALの項目を作成し、kdcなどを追記
 大文字小文字に注意

  EXAMPLE.LOCAL = {
  kdc = dc1.example.local
  kdc = dc2.example.local
  admin_server=dc1.example.local
 }

[domain_realm]
# .example.com = EXAMPLE.COM
# example.com = EXAMPLE.COM
 example.local = EXAMPLE.LOCAL
 .example.local = EXAMPLE.LOCAL
※大文字に注意

OSに依っては、realmでドメイン参加すると、krb5.confが変更されて親切にもドメイン情報が追記されています。(Rocky8.5では追記されていませんでした)
コンフィグで例示されているEXMAP.COMを参考に、kdc情報など入力します。


realmでドメイン参加すると、/etc/sssd/sssd.confが生成されます。
なお、このディレクトリはroot権限者にしか閲覧できません。
なお、realmでドメイン参加しなおすと、このsssd.confは再生成されます。その都度設定しましょう。
#cd /etc/sssd/
#sudo vi sssd.conf

[sssd]
domains = example.local
config_file_version = 2
services = nss, pam

[domain/example.local]
ad_server = dc1.example.local
ad_domain = example.local
krb5_realm = EXAMPLE.LOCAL
realmd_tags = manages-system joined-with-adcli
cache_credentials = True
id_provider = ad
krb5_store_password_if_offline = True
default_shell = /bin/bash
ldap_id_mapping = True
use_fully_qualified_names = False
fallback_homedir = /home/%u@%d
access_provider = permit
use_fully_qualified_namesとは、ユーザー確認の際にユーザー@ドメイン名の形式を指定する設定です。
今回はメールサーバとして使用するため、ユーザー名だけでADへ確認してもらいたいので、use_fully_qualified_namesをオフにします。

access_providerは、Redhat7系でも8系でも動作するように、permitにしました。
Redhat7系ではデフォルトの access_provider = ad で動作するのですが、Redhat8系になるとパスワードの認証が成功しませんでした。
(smtpのメール着信は可能ですが、popで取り出そうとすると認証エラーになります)
そこで、permitにして認証範囲を「全て許可」としています。


以下のコマンドを実行して、/etc/nsswitch.confの認証方式にsssを追加します。
#authconfig --enablesssd --update
と、Redhat本家の「システムサービスの設定」「authconfigからauthselectへのスクリプト変更」にありますが、/etc/nsswitch.confの中を見るとコマンド実行前から、すでにsssの設定があります。
nsswitch.conf以外にも変更しているのかもしれませんが、検証環境でもこのコマンドは実行なしでもADへの認証は利用可能でした。


authselectは使用しない
なお余談ですが、Redhat8以降では認証方式の更新・切り替えにはauthselectコマンドを使用することが推奨されています。
しかし本家では「このコマンドはLDAPなどのIdMを切り替える場合に使用するのであって、SSSD経由でActiveDirectoryと通信する場合は使用する必要はない」とあります。
ActiveDirectory連携の場合、「プロファイルを変更しないことをお勧めします」とも。

Redhatで公開されている「RHELでの認証と認可の構成」という技術文書では、Redhat7系までで指定していたauthconfigの変更コマンドの、authselectとの対応表があります。



sssdの起動と、認証のコンフィグ確認をします。
ただし、authconfig --testが使用できるのは、7系までです。8系ではauthselectコマンドにとって代わられていますが、testに相当する機能が見つかりません。
#sudo systemctl restart sssd
#sudo systemctl enable sssd
#authconfig --test

AD認証確認をします。
idコマンドに続き、AD上にあるユーザー名を指定します。
情報がとれたら成功です。
#id user2
uid=106601107(user2) gid=106600513(domain users) groups=106600513(domain users)
もし、「no such user」とユーザーが見つからない旨が表示されたら、ユーザー名をプリンシパルネームで指定してみます。
#id user2@example.local
uid=106601107(user2@example.local) gid=106600513(domain users@example.local) groups=106600513(domain users@example.local)
プリンシパルネームでsidが取得できた場合、前述のsssd.confの「se_fully_qualified_names」の値がtrueになっている可能性があります。コメントアウトするかfalseにする必要があります。

また、パスワード認証が成功するかも確認できます。
#getent passwd user2

Linux上には存在せず、AD上にあるユーザー宛にメールを送信し、正常に受信できるか試験します。
そしてAD上のパスワードを使ってメールが取り出せることを確認します。
こういう時、telnetでメール送信する方法を体で覚えておくと便利です。
メールの送信
#telnet 192.168.1.100 25
helo localhost
mail from:admin@exapmle.local
rcpt to:user2@example.local
data
test mail
.


メールの取り出し
#telnet 192.168.1.100 110
user user2
+OK
pass user2P@ssword
+OK Logged in.
list
+OK 1 messages:
1 823
.
retr 1






AD上の認証範囲を制御する

メールアカウントをADと連携させると、AD上の全てのユーザーが、メールアドレスとして着信可能となります。
もしそういった環境が望ましくないなら、特定のユーザーのみをAD連携対象とできます。
/etc/sssd/sssd.conf

[sssd]
domains = example.local
config_file_version = 2
services = nss, pam

[domain/example.local]
ad_server = dc1.example.local
ad_domain = example.local
krb5_realm = EXAMPLE.LOCAL
realmd_tags = manages-system joined-with-adcli
cache_credentials = True
id_provider = ad
krb5_store_password_if_offline = True
default_shell = /bin/bash
ldap_id_mapping = True
use_fully_qualified_names = False
fallback_homedir = /home/%u@%d
access_provider = simple
simple_allow_users = admin
simple_allow_groups = mailgroup
access_providerをsimpleに設定することで、単純なユーザー名やグループ名で許可アカウントを制限できます。
allow_usersとallow_groupsで許可アカウントを指定すれば、AD上のadminと、mailgroupに所属しているユーザーアカウントだけがPOPのパスワード認証に成功します。
mailgroupのメンバーアカウントを変更した場合は、割とすぐに反映されました。

他にも、access_provider=ad と ad_access_filter を組み合わせれば、特定のOU配下のみのユーザーをメールアカウントとすることもできると思います。





キャッシュの削除



sssd.confの値を変更した場合など、sssdを再起動する必要があります。
でもsssd.confを変更したのに、さっきとユーザー認証の成否が変化しなかったります。
例えば設定変更により、認証しない範囲を変更したのに引き続き認証できてしまう、などです。

それはsssdはオフライン(一時的にDCと通信できないなど)の場合でも認証を継続できるよう、認証キャッシュを持っているからです。

Redhat 「SSSDキャッシュの管理」にもありますが、そういう場合はsssdの認証キャッシュを削除します。
キャッシュファイルは /var/lib/sss/db/ にありますが、通常はコマンドから削除します。
全ての認証キャッシュを削除
#sss_cache -E

example.localドメインの認証キャッシュだけ削除
#sss_cache -Ed example.local

特定のユーザーの認証キャッシュを削除
#sss_cache -u user2
認証範囲の設定変更をすぐに反映したい場合、まずはキャッシュを疑ってみましょう。







prev.gif