docker-mailserverでメールサーバー構築(24/6/12:rspamd追記)

独自ドメインにメールも統合しようと思ったのでdocker-mailserverを使用してVPSにメールサーバーを構築しました。

docker-mailserverを使うとPostfixとDovecotでサクッとメールサーバーが構築できます。

送信にはリレーサーバーを使用、また受信ガイドラインの厳しくなったGmailでも受信できるようにdocker-mailserver+CloudflareでDKIM,DMARC,SPFの設定を行います。

元々example.comドメインを使用している前提で[email protected]のメアドを作る感じで説明を入れていきます。

続きを読む

証明書の取得

IMAP,SMTPサーバーを作成するのでmail.example.comの証明書をLet’s encryptで取得しておきます。

Nginxを使用している場合一度止めてスタンドアロンでサクッと取得

sudo systemctl stop nginx
sudo certbot certonly --standalone -d mail.example.com
sudo systemctl start nginx

またメールサーバーのAコードとMXレコードをDNS設定しておきます。

CloudflareのDNS設定でタイプ:MX、名前:example.com、コンテンツ:mail.example.comを登録します。

docker-mailserver導入

導入

早速サーバー(Ubuntu)上にgithubからcloneして導入します。導入時点の最新バージョンはv13.3.1でした。

git clone https://github.com/docker-mailserver/docker-mailserver.git
cd docker-mailserver

公式ドキュメントを読みつつ設定していきます。

必要ファイルをダウンロードします。

DMS_GITHUB_URL="https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master"
wget "${DMS_GITHUB_URL}/compose.yaml"
wget "${DMS_GITHUB_URL}/mailserver.env"

compose.yamlを編集します。メールサーバーのホストを入力します。

またletsencryptのSSL認証を使用するので←の付いている部分を追加します。

services:
  mailserver:
    image: ghcr.io/docker-mailserver/docker-mailserver:latest
    container_name: mailserver
    # Provide the FQDN of your mail server here (Your DNS MX record should point to this value)
    hostname: mail.example.com ←ここを編集
    environment:
      - SSL_TYPE=letsencrypt  ←ここを追加
    env_file: mailserver.env
    # More information about the mail-server ports:
    # https://docker-mailserver.github.io/docker-mailserver/latest/config/security/understanding-the-ports/
    ports:
      - "25:25"    # SMTP  (explicit TLS => STARTTLS, Authentication is DISABLED => use port 465/587 instead)
      - "143:143"  # IMAP4 (explicit TLS => STARTTLS)
      - "465:465"  # ESMTP (implicit TLS)
      - "587:587"  # ESMTP (explicit TLS => STARTTLS)
      - "993:993"  # IMAP4 (implicit TLS)
    volumes:
      - ./docker-data/dms/mail-data/:/var/mail/
      - ./docker-data/dms/mail-state/:/var/mail-state/
      - ./docker-data/dms/mail-logs/:/var/log/mail/
      - ./docker-data/dms/config/:/tmp/docker-mailserver/
      - /etc/localtime:/etc/localtime:ro
      - /etc/letsencrypt:/etc/letsencrypt ←ここを追加
// 以下略

mailserver.envを必要に応じて編集します。

送信にはリレーサーバーを使用するので末尾を編集してその設定を入れます。自分の場合はプロバイダメールを使用しています。例:リレーサーバー(プロバイダメール)のSMTPサーバー:mail.provider.ne.jp

# -----------------------------------------------
# --- Default Relay Host Section ----------------
# -----------------------------------------------

# Setup relaying all mail through a default relay host
#
# Set a default host to relay all mail through (optionally include a port)
# Example: [mail.example.com]:587
DEFAULT_RELAY_HOST=[mail.provider.ne.jp]:465 ←リレーサーバーのホストとポート番号

# -----------------------------------------------
# --- Multi-Domain Relay Section ----------------
# -----------------------------------------------

# Setup relaying for multiple domains based on the domain name of the sender
# optionally uses usernames and passwords in postfix-sasl-password.cf and relay host mappings in postfix-relaymap.cf
#
# Set a default host to relay mail through
# Example: mail.example.com
RELAY_HOST=mail.provider.ne.jp ←リレーサーバーのホスト

# empty => 25
# default port to relay mail
RELAY_PORT=465 ←リレーサーバーのポート番号

# -----------------------------------------------
# --- Relay Host Credentials Section ------------
# -----------------------------------------------

# Configure a relay user and password to use with RELAY_HOST / DEFAULT_RELAY_HOST

# empty => no default
[email protected] ←リレーサーバーのユーザー名

# empty => no default
RELAY_PASSWORD=リレーサーバーのメールパスワード

リレーサーバのポート番号が465の場合、./docker-data/dms/config/postfix-main.cfを新規作成して下記でpostfixのmain.cfをオーバーライドしてあげます。

smtp_tls_wrappermode = yes
smtp_tls_security_level = encrypt

またmailserver.envではメールの最大受信サイズなど細かい設定や、fail2banやSpamAssasinといったスパム対策ツールなどの有効化もできるので必要に応じて設定していきます。公式ドキュメントに詳細があります。

設定が完了したらdockerコンテナを立ち上げます。

sudo docker compose up -d

ポート開放

ファイヤーウォール(ufw)のポートを開放します。常に暗号化したい場合143,587ポートは開放しなくて大丈夫です。

sudo ufw allow 25/tcp
sudo ufw allow 143/tcp
sudo ufw allow 465/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp

メールアドレスの追加

dockerコマンドで簡単に追加できます。コマンド入力後パスワードを聞かれるので設定したいパスワードを入力します。

sudo docker exec -ti mailserver setup email add [email protected]

メールソフトの設定

ThunderbirdやSparkのようなメールソフトでアカウントを設定します。

メールアドレス、パスワードは先ほど作成したもの

IMAP,SMTPサーバー共に「mail.example.com」

IMAPポート993、SMTPポート465

他の手持ちのメアドから作ったメールアドレスに送信テストをしてみて受信の確認をしましょう。

受信が出来なかった場合DNS設定やポート開放状態を見直します。

DKIM,DMARC,SPFの設定

なりすまし防止のための送信ドメイン認証を設定します。Gmailなどは受信条件が厳しくなったため、色々とクリアしていないと正常に受信できません。

設定の仕方が公式ドキュメントに詳しく載っています。

DKIMの設定

送信メールに署名を行います。

DKIMのセットアップ

docker-mailserverではOpenDKIMがデフォルトで有効になっています。

dockerコマンドで下記を実行すると鍵が生成されます。

sudo docker exec -it mailserver setup config dkim

その後sudo docker compose stop && sudo docker compose up -dで再起動した後から送信メールにDKIMの認証が付いた状態でメールが送信されるようになります。

Cloudflareの設定

./docker-mailserver/docker-data/dms/config/opendkim/keys/example.commail.txtが生成されるので開いて確認します。下記のようになっている筈です。

mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQMMqhb1S52Rg7VFS3EC6JQIMxNDdiBmOKZvY5fiVtD3Z+yd9ZV+V8e4IARVoMXWcJWSR6xkloitzfrRtJRwOYvmrcgugOalkmM0V4Gy/2aXeamuiBuUc4esDQEI3egmtAsHcVY1XCoYfs+9VqoHEq3vdr3UQ8zP/l+FP5UfcaJFCK/ZllqcO2P1GjIDVSHLdPpRHbMP/tU1a9mNZ"
"5QMZBJ/JuJK/s+2bp8gpxKn8rh1akSQjlynlV9NI+7J3CC7CUf3bGvoXIrb37C/lpJehS39KNtcGdaRufKauSfqx/7SxA0zyZC+r13f7ASbMaQFzm+/RRusTqozY/p/MsWx8QIDAQAB"
) ;

()の中身を""を外して結合してあげます。BASE64部分はそのままくっつけます。

v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQMMqhb1S52Rg7VFS3EC6JQIMxNDdiBmOKZvY5fiVtD3Z+yd9ZV+V8e4IARVoMXWcJWSR6xkloitzfrRtJRwOYvmrcgugOalkmM0V4Gy/2aXeamuiBuUc4esDQEI3egmtAsHcVY1XCoYfs+9VqoHEq3vdr3UQ8zP/l+FP5UfcaJFCK/ZllqcO2P1GjIDVSHLdPpRHbMP/tU1a9mNZ5QMZBJ/JuJK/s+2bp8gpxKn8rh1akSQjlynlV9NI+7J3CC7CUf3bGvoXIrb37C/lpJehS39KNtcGdaRufKauSfqx/7SxA0zyZC+r13f7ASbMaQFzm+/RRusTqozY/p/MsWx8QIDAQAB

CloudflareのDNS設定画面を開き、レコードを追加します。

タイプ:TXT

名前:mail._domainkey.example.com

コンテンツ:先ほど編集したキー

設定後DNSが伝播するまでは~48時間程度かかるようです。DKIMチェッカーサイトがあるので自分のドメインとセレクター:mailで確認してみましょう。

SPFの設定

CloudflareのDNS設定画面のレコード追加で下記を登録します。

タイプ:TXT

名前:example.com

コンテンツ:

v=spf1 mx ~all

通常はこれだけでも送信はできるのですが、Gmailでスパム扱いされないようにする為には足りず、リレーサーバーのSPF設定を取り込む必要がありました。SPFチェッカーでリレーサーバーにしている自分のプロバイダのSPF設定(例ではprovider.ne.jp)を確認してincludeしました。

v=spf1 include:spf.provider.ne.jp ~all

DMARCの設定

自分のドメインから送信されたメールがDKIM署名に合わない場合に受信側がメールをどうするか等の設定です。

CloudflareのDNS設定画面で同様に入力するのですが、色々面倒なので、コンテンツ部分を自分はこちらのサイトで作成しました。

なりすましメールの対処について自分はq=rejectにしています。

タイプ:TXT

名前:_dmarc.example.com

コンテンツ:サイトで作成したキー

送信テスト

手持ちのGmailアドレス宛にメール送信をしてみて受信できるか確認します。

自分の場合:

メールがそもそも送信に失敗→「./docker-mailserver/docker-data/dms/mail-logs/mail.log」を確認。リレーサーバーの設定誤りで引っかかりました。

送信は完了したものの、リレーサーバーからのエラーメールによってDKIM等の設定が足りずにgmailに受け取って貰えないという内容のエラー→DKIM設定など見直し(DNS伝播に時間がかかった)

その後Gmailで受信できていたもののスパムに振り分けられていました。Gmail側でメールのソースを表示するとSPFの設定が足りないと出たので、自分のSPFにリレーサーバーのSPFをincludeしてようやく正常受信までこぎ着けました。

rspamdの導入(24/6/12追加)

一通り出来たので今度はrspamdを導入します。

導入

rspamdのweb UIが11334ポートで使用できるのでcompose.yamlにポートを追記しておきます。

    ports:
      - "25:25"    # SMTP  (explicit TLS => STARTTLS, Authentication is DISABLED => use port 465/587 instead)
      - "465:465"  # ESMTP (implicit TLS)
      - "993:993"  # IMAP4 (implicit TLS)
      - "11334:11334"  # rspamd web UI ←追加

ufwのポート開放もしておきます。自分はアクセスポートは変えてnginxで11334ポートに飛ばしているのでアクセス用のポートだけ自分のIP限定で開放しました。

mailserver.envを編集してrspamdやウイルスチェックのClamAVをオンにし、DKIM署名もrspamdに担当して貰うためにOpenDKIMなどをオフにします。

ENABLE_RSPAMD=1
ENABLE_CLAMAV=1
ENABLE_OPENDKIM=0
ENABLE_OPENDMARC=0
ENABLE_POLICYD_SPF=0
ENABLE_AMAVIS=0
ENABLE_SPAMASSASSIN=0
ENABLE_POSTGREY=0

dockerコンテナを再起動して有効化します。

DKIM設定

DKIMはrspamd用の鍵を生成してあげます。

sudo docker exec -it mailserver setup config dkim domain example.com

するとTXTレコードに入力する為のデータが表示されるのでcloudflareのDNS設定にコピペしてあげます。先述のmail._domainkey.example.comのコンテンツ部分です。

webUIの確認

webUIのパスワードを設定します。下記コマンドを実行するとパスワードが聞かれるので設定したいパスワードを入力します。パスワードのハッシュが生成されます。

sudo docker exec -it mailserver rspamadm pw

docker-data/dms/config/rspamdcustom-commands.confというファイルを作成するとrspamdの設定を上書きできます。

set-option-for-controller password "ここにパスワードハッシュ"

上記を追記することでwebUIにパスワードでログインできます。

rspamdの確認

サーティーワンの会員登録完了がスパムマークを付けられていたのでrspamdのwebUIで見てみました。

内訳が見れるので確認してみます。

VIOLATED_DIRECT_SPF (3.5): SPFで送信元IPアドレスが許可されていないことを示しています。このメールの送信元IPが送信ドメインの許可リストに含まれていないため、高いスパムスコアがつけられています。

R_SPF_SOFTFAIL (2.5) [~all]: SPFレコードに「~all」(SoftFail)オプションが設定されているため、送信元IPが許可されていない可能性があるが、強制的に拒否はしない設定です。このため、スパムの可能性があると判定されます。

DMARC_NA (1) [31club.jp]: DMARCレコードが存在しないため、メールの整合性が検証できません。このため、スパムスコアが増加しています。

PHP_SCRIPT_ROOT (1): メール本文にPHPスクリプトのパスが含まれている可能性があります。これは、スパムメールがPHPスクリプトを利用している可能性があることを示唆しています。

こんな感じでスコアがプラスマイナスされ、最終的に一定値以上のスコアになるとスパムとして認識されます。はぇ~。

この他にフィルタを自分で追加したりもできるのでスパムを受信し始めたら設定してみたいです。

Gmailのようなエイリアス追加

gmailだと「[email protected]」「[email protected]」は「[email protected]」で受信できます。これと同様のことが行えます。

docker-mailserverではデフォルトで+区切りのエイリアスが有効になっています。特に設定しなくても+区切りでエイリアスの利用が出来ます。

また、これは記号を変更することもできます。「-」や「.」等にすると一見エイリアスとわかりづらくなるかも。

docker-data/dms/config/postfix-main.cfdocker-data/dms/config/dovecot.cfに下記のコードを追記します。

recipient_delimiter = -

記述できたらdockerコンテナを再起動します。

おわりに

さくらのレンタルサーバーが今月末で契約終了なのにメールを移行するのをすっかり忘れていたので、大慌てでメールサーバーを立ち上げました。間に合って良かったです。メールサーバーについても勉強になりました。なりすまし防止ってこんなことしてるのね…。

独自ドメインのメールが使えるのも割と嬉しいです。Google workspace契約の方とかも見ていますがやっぱりVPS代だけで終わるので有り難いです。やったね🎉

Docker,006edc