Featured image of post docker-mailserver メールサーバーセットアップ記録

docker-mailserver メールサーバーセットアップ記録

Caddy に TLS 証明書を要求させるのは本当に大変。

ある朝、私は誰かが別の国から私のアカウントにログインしたという通知メールで目を覚ました。最初は単なるIPエラーだと思い、あまり気にしませんでした。

しかし、その後数日間、断続的に新しいメールが届き、毎回 IP が異なっていました。これは問題です。早急に対策を講じないと、メールボックスが本当に大量送信に使われてしまうかもしれません。そこで、ドメインの MX、SPF、DMARC レコードを削除し、新しい解決策を探しました。

もともとはパスワードを変更するだけのつもりでしたが、Tencent Enterprise Mail のパスワード変更の入口が非常に分かりにくく、どこにも見つかりませんでした。もういい、移行しよう。こんなことで悩む必要はありません。

設定ファイルの取得

docker-mailserver には compose.yamlmailserver.env の2つの設定ファイルが必要です。以下のように設定ファイルを取得します:

1
2
3
4
mkdir mailserver && cd mailserver
sudo apt install wget
wget -O compose.yaml "https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/compose.yaml"
wget -O mailserver.env "https://github.com/docker-mailserver/docker-mailserver/blob/master/mailserver.env"

必要に応じて設定を変更できます。以下は私が変更した部分です:

1
2
3
4
5
POSTMASTER_ADDRESS=webmaster@l3zc.com
TZ=Asia/Shanghai
SSL_TYPE=manual
SSL_CERT_PATH=/certs/cert.crt
SSL_KEY_PATH=/certs/cert.key

Caddy を使って TLS 証明書を管理する1

すでに Caddy を使用していたので、今回は Caddy を使って証明書を自動管理することにしました。プロジェクトの公式ドキュメントによると、Caddyfile にサブドメインを追加するだけで、Caddy が自動的に証明書を管理してくれます。

1
2
3
4
5
6
7
8
9
mail.example.com {
  tls internal {
    # ?? これは内部証明書を生成するだけではないのか
    key_type rsa2048
  }

  # オプション、正しい証明書で Caddy への接続をトラブルシューティングするのに役立つ
  respond "Hello DMS"
}

DNS レコードを更新した後、私の状況が少し特殊であることに気づきました:私のサーバーは Caddy の自動証明書申請機能を使用しておらず、15年間有効なワイルドカード Cloudflare Origin Certificate を使用していました。このサブドメインに証明書ファイルを指定しなくても、Caddy はこのワイルドカード証明書を読み込み、新しい証明書を申請する必要がないと判断します。これはかなり厄介です。Caddy を使用する場合、Cloudflare Origin Certificate とメールサーバーはどちらか一方しか選べません。そこで dns.providers.cloudflare をインストールしました。すべて自動化されているので、見えないところで心配する必要はありません。

dns.providers.cloudflare をインストールした後のグローバル設定:

1
2
3
{
        acme_dns cloudflare {API_KEY}
}

最後に、Caddy の証明書保存場所を docker-mailserver コンテナ内にマッピングします。

1
2
volumes:
   - /home/user/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.tld/:/certs/

Caddy が root ユーザーとして実行される場合、証明書の場所は /root/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.tld/ である必要があります。対応する変更を行ってください。

次に、前述のように、証明書保存場所をコンテナ内の /certs/ ディレクトリにマッピングしたので、設定は次のようになります:

1
2
SSL_CERT_PATH=/certs/cert.crt
SSL_KEY_PATH=/certs/cert.key

ファイアウォールの設定

私のファイアウォールは少し特殊で、ufwTo Fix The Docker and UFW Security Flaw Without Disabling Iptables に記載されている設定を使用しています。そのため、Docker コンテナのポートを外部に公開する場合、追加の設定が必要です。

1
2
3
4
5
6
# メールサーバーに必要なポートを開放
ufw route allow proto tcp from any to any port 25
ufw route allow proto tcp from any to any port 143
ufw route allow proto tcp from any to any port 465
ufw route allow proto tcp from any to any port 587
ufw route allow proto tcp from any to any port 993

コンテナの初回起動

コンテナを初めて起動する際には、すぐに(120 秒以内に)新しい Postmaster アカウントを作成する必要があります。

1
2
docker compose up -d
docker exec -it <CONTAINER NAME> setup email add <postmaster@yourdomain.tld>

その後、コンテナを停止して設定を続けることができます。

1
docker compose down

DNS レコード

  • A レコードを 1 件、名前は任意(仮に mail とする)、サーバー IP に向ける(Cloudflare の場合「DNS のみ」を使用)
  • MX レコードを 1 件、Apex ドメイン(@)に設定し、mail.yourdomain.tld を指す
  • TXT レコード(SPF)を 1 件、Apex ドメイン(@)に設定しこちらで生成可能 (任意)
  • TXT レコード(DMARC)を 1 件、名前は _dmarc として こちらで生成可能 (任意)
  • TXT レコード(DKIM)を 1 件、名前は mail._domainkey として後述の具体的な設定内容による (任意)

DKIM、SPF、DMARC2

DKIM、SPF、DMARCとは何ですか?簡単に言うと、DKIMはデジタル署名の仕組みです。SPFは「従業員リスト」のようなもので、合法的な送信サーバーを記録します。DMARCは、DKIMおよびSPFの検証に失敗したメールを受信側のサーバーがどのように処理するかを指示するために使用されます。3

まず、サーバー上で公開鍵と秘密鍵のペアを生成してDKIMを設定します。

1
docker exec -it <CONTAINER NAME> setup config dkim

生成された公開鍵と秘密鍵のペアは、マッピングされたコンテナディレクトリ./docker-data/dms/config/opendkim/keys/にあります。

mail.txt は公開鍵の DNS ゾーンファイルです Cloudflare のインポートセクション

mail.txtをダウンロードするか、その内容をすべてコピーしてローカルファイルに貼り付け、CloudflareダッシュボードにインポートすればDKIMの設定が完了します。DKIMの設定が完了した後、コンテナを再起動する必要があることに注意してください。4

1
docker compose up -d --force-recreate

前述のとおり、SPFは「従業員リスト」に相当します。合法的な送信サーバーが1台しかないため、DNSは次のように設定します。

1
"v=spf1 mx ~all"

最後に、DMARCについては、前述のテンプレートを使用できるため、ここでは繰り返しません。

もしあなたのドメインプロバイダーが独自の設定ウィザードを持っている場合(例:Cloudflare)、それらを使用して設定プロセスを簡略化することもできます。

クライアント設定

クライアント設定は比較的簡単です。IMAP と SMTP サーバーはどちらも mail.yourdomain.ltd です。SSL を有効にした後、ポートはそれぞれ 465 と 993 です。ログインするだけです。

設定例

TODO-リスト

  • WebUI のサポート
Hugo で構築されています。
テーマ StackJimmy によって設計されています。