LoginSignup
0
0

私的サーバー構築日誌:SSSDとDovecot

Posted at

能書き

私的サーバー構築日誌:仕切り直しからの自宅サーバー構築の続きです。

今、メールサーバー(MTA)を立てるのは大変なんですね。迷惑メール対策でガッチガチに固められて、気を使わなきゃいけない点が増えてます。技術的にかなり面倒な感じ。そしてGoogleとかの世界的大手メールサービスがそれを強要してます。やって出来ない事はないけれど、とても大変です。

そんな面倒臭いだけのレガシーなメールサーバーを今立てようとする理由は、GitLabです。この後でGitLabサーバーを立てたいと考えていますが、そこでメールサーバーとの連携が必要になります。これが今のモチベーションになっています。

以前はDovecotを3回に分けて設定しましたが、今回は一気に全部やります。

なお、今回もLXDコンテナに設定します。その意味ですが。

  • 受信メールをコンテナ内に蓄積できます。Dockerコンテナではコンテナ内へのデータ蓄積は不向きです。ホスト側のディレクトリに保存させる手段もありますけども、LXDコンテナならそのままコンテナ内に蓄積できます。
  • 蓄積したメールのバックアップコピーを作ろうとした場合、LXDコンテナ内にメールがあれば、コンテナをエクスポートする事でDovecotの設定ごとバックアップできます。
  • 将来はDRBDも入れて、リアルタイムでミラーリングして「絶対に喪失しないメールシステム」を実現したい。こういった複数ソフトのインストールにはDockerは不向きでしょう。

そういう訳で、常時起動のLXDコンテナを立てて、その中にMDAとしてDovecotをインストールします。MTAは、志を低くした形で次回立てます。

目標

  • LXDコンテナにSSSDを設定してLDAPと連携
  • そのコンテナにDovecotをインストールしてIMAPSとLMTPを設定
  • cloud-initを利用して自動化可能な部分は自動化する

POP3は使いません。どうせ私専用のメールサーバーですので、私自身が使わない以上、選択肢として用意しておく必要もありません。

そして IMAP over SSL/TLS、通称 IMAPS にします。ただのIMAPは使えないように潰しておきます。

参考文献

Dovecot関連。

SSSDについて。

証明書関係。

LXDコンテナの初期化処理を自動化するcloud-initについて。

LXDコンテナの用意

Dovecot(及びメール蓄積)の為のLXDコンテナを作成します。

コンテナ名とそのIPアドレス、ポート番号などは何度か参照するので、環境変数に設定しておきます。異なる設定を使いたい場合は、ここを修正して下さい。

ホスト側
CONTAINER=dovecot1
IPADDRESS=192.168.0.201
IMAPS_PORT=993
LMTP_PORT=24
HOST_IPADDR=172.16.1.2

LXDコンテナを初期設定します。今回は/etcのSubversion管理は設定しません。煩雑なだけで役に立ちそうにないので。

ホスト側
lxc init images:ubuntu/jammy/cloud $CONTAINER --device eth0,ipv4.address=$IPADDRESS
lxc config set $CONTAINER cloud-init.user-data="$(cat <<___
#cloud-config
timezone: Asia/Tokyo
locale: ja_JP.utf8
package_upgrade: true
packages:
  - sssd-ldap
  - sssd-tools
  - dovecot-lmtpd
  - dovecot-imapd
___
)"
lxc start $CONTAINER
lxc exec $CONTAINER -- cloud-init status --wait

証明書の用意

以前用意したオレオレ認証局証明書のパスは下記の通りです。

認証局:

  • 秘密鍵 /home/cert/demoCA/pki/private/ca.key
  • 公開鍵 /home/cert/demoCA/pki/ca.crt

サーバーマシンprimary.homeの証明書:

  • 秘密鍵 /home/cert/demoCA/pki/private/primary.home.key
  • 公開鍵 /home/cert/demoCA/pki/issued/primary.home.crt

Dovecot

認証局と証明書

Dovecot-IMAPで必要な証明書は、書き方が他とはちょっと違うようです。証明書と認証局の鍵を結合したpemファイルを作成します。

ホスト側
mkdir /tmp/dovecotIMAP
cd /tmp/dovecotIMAP
ホスト側
sudo -u cert cat /home/cert/demoCA/pki/private/primary.home.key >dovecot_primary.pem
ホスト側
sudo -u cert openssl x509 -outform pem -in /home/cert/demoCA/pki/issued/primary.home.crt >>dovecot_primary.pem
ホスト側
sudo -u cert cat /home/cert/demoCA/pki/ca.crt >>dovecot_primary.pem

このpemファイルをLXDコンテナ内の所定の場所に置きます。

ホスト側
lxc file push /tmp/dovecotIMAP/dovecot_primary.pem $CONTAINER/etc/dovecot/private/dovecot_primary.pem

終わったら、ホスト側のファイルは不要なので削除します。

ホスト側
cd ..
rm -r dovecotIMAP

Dovecotの設定

LMTPとIMAPSを一緒に設定します。

まずは作業場所を確保。

ホスト側
mkdir /tmp/dovecotPatch
cd /tmp/dovecotPatch

次にパッチを用意します。

ホスト側
cat >dovecot.patch <<___
Index: /etc/dovecot/conf.d/10-auth.conf
===================================================================
--- /etc/dovecot/conf.d/10-auth.conf
+++ /etc/dovecot/conf.d/10-auth.conf
@@ -48,7 +48,7 @@
 # the standard variables here, eg. %Lu would lowercase the username, %n would
 # drop away the domain if it was given, or "%n-AT-%d" would change the '@' into
 # "-AT-". This translation is done after auth_username_translation changes.
-#auth_username_format = %Lu
+auth_username_format = %Ln

 # If you want to allow master users to log in by specifying the master
 # username within the normal username string (ie. not using SASL mechanism's
Index: /etc/dovecot/conf.d/10-logging.conf
===================================================================
--- /etc/dovecot/conf.d/10-logging.conf
+++ /etc/dovecot/conf.d/10-logging.conf
@@ -4,7 +4,7 @@

 # Log file to use for error messages. "syslog" logs to syslog,
 # /dev/stderr logs to stderr.
-#log_path = syslog
+log_path = syslog

 # Log file to use for informational messages. Defaults to log_path.
 #info_log_path =
@@ -14,7 +14,7 @@
 # Syslog facility to use if you're logging to syslog. Usually if you don't
 # want to use "mail", you'll use local0..local7. Also other standard
 # facilities are supported.
-#syslog_facility = mail
+syslog_facility = mail

 ##
 ## Logging verbosity and debugging.
Index: /etc/dovecot/conf.d/10-mail.conf
===================================================================
--- /etc/dovecot/conf.d/10-mail.conf
+++ /etc/dovecot/conf.d/10-mail.conf
@@ -27,7 +27,7 @@
 #
 # <doc/wiki/MailLocation.txt>
 #
-mail_location = mbox:~/mail:INBOX=/var/mail/%u
+mail_location = maildir:~/Maildir

 # If you need to set multiple mailbox locations or want to change default
 # namespace settings, you can do it by defining namespace sections.
Index: /etc/dovecot/conf.d/10-master.conf
===================================================================
--- /etc/dovecot/conf.d/10-master.conf  (revision 3)
+++ /etc/dovecot/conf.d/10-master.conf  (working copy)
@@ -52,16 +52,16 @@
 }

 service lmtp {
-  unix_listener lmtp {
+  #unix_listener lmtp {
     #mode = 0666
-  }
+  #}

   # Create inet listener only if you can't use the above UNIX socket
-  #inet_listener lmtp {
+  inet_listener lmtp {
     # Avoid making LMTP visible for the entire internet
     #address =
-    #port =
-  #}
+    port = $LMTP_PORT
+  }
 }

 service imap {
Index: /etc/dovecot/conf.d/10-ssl.conf
===================================================================
--- /etc/dovecot/conf.d/10-ssl.conf
+++ /etc/dovecot/conf.d/10-ssl.conf
@@ -9,8 +9,8 @@
 # dropping root privileges, so keep the key file unreadable by anyone but
 # root. Included doc/mkcert.sh can be used to easily generate self-signed
 # certificate, just make sure to update the domains in dovecot-openssl.cnf
-ssl_cert = </etc/dovecot/private/dovecot.pem
-ssl_key = </etc/dovecot/private/dovecot.key
+ssl_cert = </etc/dovecot/private/dovecot_primary.pem
+ssl_key = </etc/dovecot/private/dovecot_primary.pem

 # If key file is password protected, give the password here. Alternatively
 # give it when starting dovecot with -p parameter. Since this file is often
___

必要な設定ファイルを取り出します。

ホスト側
mkdir etc
lxc file pull $CONTAINER/etc/dovecot/conf.d/{10-auth.conf,10-logging.conf,10-mail.conf,10-master.conf,10-ssl.conf} etc

そうしたらpatchコマンドで一気に適用!
タブ文字の関係などでエラーが発生する可能性があるので、--ignore-whitespaceオプションを付けて実行します。

ホスト側
patch --ignore-whitespace -d etc <dovecot.patch

エラーが表示されなければ成功です。

ホスト側
$ patch --ignore-whitespace -d etc <dovecot.patch
patching file 10-auth.conf
patching file 10-logging.conf
patching file 10-mail.conf
patching file 10-master.conf
patching file 10-ssl.conf

パッチを当てた設定ファイルをコンテナに戻します。

ホスト側
lxc file push etc/* $CONTAINER/etc/dovecot/conf.d/

Dovecotに設定を読み込ませます。

ホスト側
lxc exec $CONTAINER systemctl reload dovecot

不要になったファイル達は削除しましょう。

ホスト側
cd ..
rm -r dovecotPatch

LXDコンテナのネットワークの設定

現在のネットワークの状態を確認してみましょう。

ホスト側
lxc network list-leases lxdbr0

今の状態ならこんな風に表示されるでしょう。コンテナを既に色々弄っていたら、違う表示になるかも知れません。

ホスト側
$ lxc network list-leases lxdbr0
+-----------+-------------------+---------------+---------+
| HOSTNAME  |    MAC ADDRESS    |  IP ADDRESS   |  TYPE   |
+-----------+-------------------+---------------+---------+
| dovecot1  | 00:16:3e:fb:bf:ed | 192.168.0.201 | STATIC  |
+-----------+-------------------+---------------+---------+
| lxdbr0.gw |                   | 192.168.0.1   | GATEWAY |
+-----------+-------------------+---------------+---------+

コンテナのNATを設定します。

ホスト側
lxc network forward create lxdbr0 $HOST_IPADDR
lxc network forward port add lxdbr0 $HOST_IPADDR tcp $LMTP_PORT $IPADDRESS $LMTP_PORT
lxc network forward port add lxdbr0 $HOST_IPADDR tcp $IMAPS_PORT $IPADDRESS $IMAPS_PORT

SSSD

認証局

まずは認証局の公開鍵を用意します。

ホスト側
sudo -u cert cp -p /home/cert/demoCA/pki/ca.crt /tmp/demoCA.crt
ホスト側
sudo chown $USER: /tmp/demoCA.crt
ホスト側
chmod 644 /tmp/demoCA.crt
lxc exec $CONTAINER mkdir /usr/share/ca-certificates/demoCA
ホスト側
lxc file push /tmp/demoCA.crt $CONTAINER/usr/share/ca-certificates/demoCA/demoCA.crt
rm /tmp/demoCA.crt

次に認証局を信頼します。

ホスト側
lxc shell $CONTAINER
コンテナ内
echo demoCA/demoCA.crt >>/etc/ca-certificates.conf
update-ca-certificates

SSSDの設定

引き続きコンテナ内で操作します。

コンテナ内
cat <<___ >/etc/sssd/sssd.conf
[sssd]
config_file_version = 2
domains = home

[domain/home]
id_provider = ldap
auth_provider = ldap
ldap_uri = ldaps://primary.home
cache_credentials = True
ldap_search_base = dc=home
ldap_default_bind_dn = cn=readonly,dc=home
___
chmod 600 /etc/sssd/sssd.conf
コンテナ内
sss_obfuscate -d home

ここで要求に従いパスワードを入力します。
パスワードを入力したら、SSSDサービスを開始します。

コンテナ内
systemctl start sssd

ホームディレクトリの自動作成を有効にします。

コンテナ内
pam-auth-update --enable mkhomedir

これでコンテナ内の操作は終了です。

コンテナ内
exit

動作確認1・未ログインユーザーにメールが届いた場合

ホームディレクトリが無いユーザーにメールが届いたらどうなるか、ですね。Internal error が発生します。実験してみましょう。

以前の設定の通りならば、LDAPにはユーザー名taroが登録されています。そして今の段階ではまだログインしていません。

LMTPコマンドを手で入力して、反応を1つずつ確認してみます。

ホスト側
nc -C $HOST_IPADDR $LMTP_PORT
nc
lhlo primary.home
nc
mail from:<test@sender.home>
nc
rcpt to:<taro@home>
nc
data
From: test@sender.home
To: $USERNAME@primary.home
Subject: test

hello, world
.

下記のような結果になります。

ホスト側
$ nc -C $HOST_IPADDR $LMTP_PORT
220 dovecot1 Dovecot (Ubuntu) ready.
lhlo primary.home
250-dovecot1
250-8BITMIME
250-CHUNKING
250-ENHANCEDSTATUSCODES
250-PIPELINING
250 STARTTLS
mail from:<test@sender.home>
250 2.1.0 OK
rcpt to:<taro@home>
250 2.1.5 OK
data
From: test@sender.home
To354 OK
: $USERNAME@primary.home
Subject: test

hello, world
.
451 4.2.0 <taro@home> Internal error occurred. Refer to server log for more information. [2023-11-15 13:23:58]

つまり、メール本文の入力が終わった時点で Internal error ですね。

この時のエラーログを見てみましょう。

ホスト側
lxc exec $CONTAINER cat /var/log/mail.err

下記のような感じで、/home/taro/Maildirディレクトリを作ろうとして権限不足で失敗しています。うむ、想定内ですな。

ホスト側
$ lxc exec $CONTAINER cat /var/log/mail.err
Nov 15 04:23:58 dovecot1 dovecot: lmtp(taro)<8235><tsplGMBHVGUrIAAA9sUnBg>: Error: lmtp-server: conn 172.16.1.2:60146 [1]: rcpt taro@home: mkdir(/home/taro/Maildir) failed: Permission denied (euid=10000(taro) egid=10000(taro) missing +w perm: /home, dir owned by 0:0 mode=0755)
Nov 15 04:23:58 dovecot1 dovecot: lmtp(taro)<8235><tsplGMBHVGUrIAAA9sUnBg>: Error: lmtp-server: conn 172.16.1.2:60146 [1]: rcpt taro@home: mkdir(/home/taro/Maildir) failed: Permission denied (euid=10000(taro) egid=10000(taro) missing +w perm: /home, dir owned by 0:0 mode=0755)
Nov 15 04:23:58 dovecot1 dovecot: lmtp(taro)<8235><tsplGMBHVGUrIAAA9sUnBg>: Error: lmtp-server: conn 172.16.1.2:60146 [1]: rcpt taro@home: Mailbox INBOX: Failed to autocreate mailbox: Internal error occurred. Refer to server log for more information. [2023-11-15 13:23:58]

LDAPユーザーでログイン

上述のエラーを踏まえ、コンテナのコンソールに接続して一度ログインします。ログインする事によってホームディレクトリも作られます。

ホスト側
USERNAME=taro

下記のコマンドならばtaroのパスワード入力は省略できます。

ホスト側
lxc exec $CONTAINER -- login -f $USERNAME

特にする事も無いので、確認できたらexitしましょう。

残念ながらloginコマンドはコンソールからの入出力しか受け付けないようです。exitは手で入力しなければなりません。

コンテナ内
exit

動作確認2・ログイン済ユーザーにメールお届け

LDAPユーザーtaroのホームディレクトリが作成されたら、dovecotでメール配送できる筈
です。

taro宛にメールを送信します。成功する事を期待して、LMTPコマンドを一気に流します。

ホスト側
nc -C $HOST_IPADDR $LMTP_PORT <<___
lhlo primary.home
mail from:<test@sender.home>
rcpt to:<$USERNAME@home>
data
From: test@sender.home
To: $USERNAME@home
Subject: test

hello, world
.
quit
___

メールが正しく届いていれば、LDAPユーザーtaroに対してIMAPSで確認できる筈です。

ホスト側
openssl s_client -connect $HOST_IPADDR:$IMAPS_PORT
openssl
1 login taro Ma9H%6jg
2 list "" *
3 select INBOX
4 fetch 1 body[]
5 logout

動作確認3・存在しないユーザーにメールが届いた場合

登録されていないユーザーとして、例えばhanako宛のメールが届いた場合の挙動です。

今回もまたLMTPコマンドを手で入力して、反応を1つずつ確認してみます。

ホスト側
nc -C $HOST_IPADDR $LMTP_PORT
nc
lhlo primary.home
nc
mail from:<test@sender.home>
nc
rcpt to:<hanako@home>

今回はrcpt toの段階でエラーが発生します。

nc
$ nc -C $HOST_IPADDR $LMTP_PORT
220 dovecot1 Dovecot (Ubuntu) ready.
lhlo primary.home
250-dovecot1
250-8BITMIME
250-CHUNKING
250-ENHANCEDSTATUSCODES
250-PIPELINING
250 STARTTLS
mail from:<test@sender.home>
250 2.1.0 OK
rcpt to:<hanako@home>
550 5.1.1 <hanako@home> User doesn't exist: hanako@home

仕舞い

メールサーバーの内MDAとしてDovecotを立て、SSSDと連携させました。そして少々詳しく動作確認しました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0