おうちサーバー構築報告：DovecotでIMAPSとLMTP

## 能書き

[おうちサーバー構築報告：予告](https://qiita.com/katz_engineer/items/471408eda1d09507c451)からのおうちサーバー構築の続きです。

今回はDovecotを設定して、IMAPSとLMTPを使えるようにします。[以前も似たような事をやりました](https://qiita.com/katz_engineer/items/0e6b647e9cc3c7c457e5)が、今回はSSSD無しでいきます。

### 目標

- メール専用コンテナにDovecotをインストールしてIMAPSとLMTPを設定
- IMAP over SSL/TLS、通称 IMAPS にする（ただのIMAPは使えないように潰しておく）

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

### 参考文献

- [私的サーバー構築日誌：SSSDとDovecot - Qiita](https://qiita.com/katz_engineer/items/0e6b647e9cc3c7c457e5)
- [サーバー証明書を生成して認証 - オレオレ認証局が認証するサーバー証明書 - おうちサーバー構築報告：オレオレ認証局とサーバー証明書 - Qiita](https://qiita.com/katz_engineer/items/bffc988b10730305d757#%E3%82%AA%E3%83%AC%E3%82%AA%E3%83%AC%E8%AA%8D%E8%A8%BC%E5%B1%80%E3%81%8C%E8%AA%8D%E8%A8%BC%E3%81%99%E3%82%8B%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E8%A8%BC%E6%98%8E%E6%9B%B8)
- [ターゲットノードとしてコンテナ3台 - おうちサーバー構築報告：AnsibleでProxmoxVEのゲストマシン4台それぞれ/etcをSubversion管理 - Qiita](https://qiita.com/katz_engineer/items/d46b60e6606563e75859#%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%83%E3%83%88%E3%83%8E%E3%83%BC%E3%83%89%E3%81%A8%E3%81%97%E3%81%A6%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A3%E5%8F%B0)

## サーバー証明書の作成

サーバー証明書を作成してメールサーバーの所定のディレクトリに配置します。

[サーバー証明書を作成するコンテナのIPアドレスは`172.16.1.101`で名前は`network`](https://qiita.com/katz_engineer/items/d46b60e6606563e75859#%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%83%E3%83%88%E3%83%8E%E3%83%BC%E3%83%89%E3%81%A8%E3%81%97%E3%81%A6%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A3%E5%8F%B0)です。また[メール専用コンテナのIPアドレスは`172.16.1.102`で名前は`mail`](https://qiita.com/katz_engineer/items/d46b60e6606563e75859#%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%83%E3%83%88%E3%83%8E%E3%83%BC%E3%83%89%E3%81%A8%E3%81%97%E3%81%A6%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A3%E5%8F%B0)です。

実行ユーザーやコンテナがあっちこっち飛びますので御注意ください。

まず`mail.local`のサーバー証明書を作成します。

```console:サーバー172.16.1.101ユーザー名root
export CA_NAME=demoCA
export CA_USER=cert
export SRV_NAME=mail.local
TR_USER=transporter
TR_DIR=/srv/transport/publickey
```

```console:サーバー172.16.1.101ユーザー名root
su -m $CA_USER
```

ここで`/root/.bashrc`の権限エラーが出ますが無視。こんな感じです。

```console:サーバー172.16.1.101ユーザー名root
# su -m $CA_USER
bash: /root/.bashrc: Permission denied
```

権限エラーは無視して続けます。

```console:サーバー172.16.1.101ユーザー名cert
cd /home/$CA_USER/$CA_NAME
./easyrsa build-server-full $SRV_NAME nopass
```

ここで次のようなプロンプトが表示されますので、表示通り`yes`と入力します。

```console:サーバー172.16.1.101ユーザー名cert
Type the word 'yes' to continue, or any other input to abort.
  Confirm request details:
```

次は下記のプロンプトです。認証局のパスフレーズを入力します。

```console:サーバー172.16.1.101ユーザー名cert
Enter pass phrase for /home/cert/demoCA/pki/private/ca.key:
```

完了したらユーザー`cert`を抜けます。

```console:サーバー172.16.1.101ユーザー名cert
exit
```

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

```console:サーバー172.16.1.101ユーザー名root
cd /tmp
cp /home/$CA_USER/$CA_NAME/pki/private/$SRV_NAME.key dovecot_mail.pem
openssl x509 -outform pem -in /home/$CA_USER/$CA_NAME/pki/issued/$SRV_NAME.crt >>dovecot_mail.pem
cat /home/$CA_USER/$CA_NAME/pki/ca.crt >>dovecot_mail.pem
chown $TR_USER: dovecot_mail.pem
mv dovecot_mail.pem $TR_DIR
```

ここまで出来たら`172.16.1.101`での作業は終了です。

```console:サーバー172.16.1.101ユーザー名root
exit
```

次にメールサーバーコンテナ`172.16.1.102`でサーバー証明書を取得し、所定のディレクトリに移動します。

```console:サーバー172.16.1.102ユーザー名root
TR_USER=transporter
TR_IPADDR=172.16.1.101
TR_DIR=publickey
```

```console:サーバー172.16.1.102ユーザー名root
cd /tmp
sftp $TR_USER@$TR_IPADDR <<___
cd $TR_DIR
get dovecot_mail.pem
rm dovecot_mail.pem
exit
___
```

## Dovecotインストールと設定

引き続きメールサーバー`172.16.1.102`での作業になります。

```console:サーバー172.16.1.102ユーザー名root
LMTP_PORT=24
```

```console:サーバー172.16.1.102ユーザー名root
apt update
apt upgrade -y
```

```console:サーバー172.16.1.102ユーザー名root
apt install -y dovecot-lmtpd dovecot-imapd patch
```

```console:サーバー172.16.1.102ユーザー名root
cd /etc
svn st | grep "^?" | cut -b9- | sudo xargs -I{} find {} -type f -or -type d -or -type l | xargs -rt svn add
svn ci -m"install dovecot"

patch --ignore-whitespace -d /etc/dovecot/conf.d <<___
Index: dovecot/conf.d/10-auth.conf
===================================================================
--- dovecot/conf.d/10-auth.conf
+++ 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: dovecot/conf.d/10-logging.conf
===================================================================
--- dovecot/conf.d/10-logging.conf
+++ 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: dovecot/conf.d/10-mail.conf
===================================================================
--- dovecot/conf.d/10-mail.conf
+++ 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: dovecot/conf.d/10-master.conf
===================================================================
--- dovecot/conf.d/10-master.conf
+++ dovecot/conf.d/10-master.conf
@@ -55,16 +55,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: dovecot/conf.d/10-ssl.conf
===================================================================
--- dovecot/conf.d/10-ssl.conf
+++ 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_mail.pem
+ssl_key = </etc/dovecot/private/dovecot_mail.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
___

svn ci /etc -m"initialize dovecot"

mv /tmp/dovecot_mail.pem /etc/dovecot/private
systemctl reload dovecot
```

## 動作確認

まずはメールサーバーに新ユーザー`taro`を作成します。

```console:サーバー172.16.1.102ユーザー名root
NEWUSER=taro
```

```console:サーバー172.16.1.102ユーザー名root
useradd -m -s /bin/bash $NEWUSER
passwd $NEWUSER
```

パスワードは何でもいいですが、後の動作確認の都合で`Ma9H%6jg`にします。

### 1・作成したユーザーにメールが届いた場合

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

```console:サーバー172.16.1.102ユーザー名root
nc -C localhost $LMTP_PORT <<___
lhlo mail.local
mail from:<test@sender.local>
rcpt to:<$NEWUSER@localhost>
data
From: test@sender.local
To: $NEWUSER@localhost
Subject: test

hello, world
.
quit
___
```

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

```console:サーバー172.16.1.102ユーザー名root
openssl s_client -connect localhost:993
```

```console:openssl
1 login taro Ma9H%6jg
2 list "" *
3 select INBOX
4 fetch 1 body[]
5 logout
```

### 2・存在しないユーザーにメールが届いた場合

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

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

```console:サーバー172.16.1.102ユーザー名root
nc -C localhost $LMTP_PORT
```

```console:nc
lhlo mail.local
```

```console:nc
mail from:<test@sender.local>
```

```console:nc
rcpt to:<hanako@local>
```

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

```console:サーバー172.16.1.102ユーザー名root
# nc -C localhost $LMTP_PORT
220 mail.local Dovecot (Ubuntu) ready.
lhlo mail.local
250-mail.local
250-8BITMIME
250-CHUNKING
250-ENHANCEDSTATUSCODES
250-PIPELINING
250 STARTTLS
mail from:<test@sender.local>
250 2.1.0 OK
rcpt to:<hanako@local>
550 5.1.1 <hanako@local> User doesn't exist: hanako@local
```

# 仕舞い

メールサーバーの内MDAとしてDovecotを立てました。メール受信の方はこれで整いました。