OpenWRT上でPostfixとDovecotのメールサーバを立てる

投稿者: | 12月 12, 2023

目次

はじめに

前回でメールを保存する用の領域をRAIDで作成することができたので、今回はついにメールサーバを立ち上げます。
かなり大変でした。
環境はURoad-Home2+にOpenWRTを入れたものです。

目標

SMTP、SMTPs、サブミッションポートで送受信し、IMAPsでメールを配信するメールサーバです。メールは外付けHDDに保存します。
また、Gmail等に迷惑メールと認識されないようにするために、SPF、DKIMの設定も行います。

参考文献

CentOSで自宅サーバー構築「メールサーバー構築(Postfix+Dovecot)」
Qitta「自ドメインのDNSとPostfixをSPF/DKIM対応させてみた」

事前準備

外部ストレージの接続

OpenWRTはルータ向けのOSでルータはROMがもちろん少ないので、外付けストレージをつけないとどう考えても足りません。自分は、前回記事のOpenWRTでmdadmを使用したソフトウェアRAIDを組むでRAID1でHDDを接続しています。マウントも適当な場所にしておいてください(例/mnt/md0)。

ソフトウェアのインストール

Postfix、dovecot、dovecot-utils、acmeをインストールして下さい。

OpenWRT上でPostfixとDovecotのメールサーバを立てる
postfixのインストール
OpenWRT上でPostfixとDovecotのメールサーバを立てる
dovecotのインストール

ディレクトリの設定

postfix用のディレクトリを作成します。

mkdir /mnt/md0/postfix

証明書の準備

すでに証明書がある場合はそれを使用して下さい。自分はなかったので、OpenWRTのACMEを使用しました。

ACMEを使用する条件として80ポートと443ポートが開放されている必要があります。ローカルネットワークにサーバを置いてゲートウェイでポートフォワーディングを使用してメールサーバを公開しようとしている場合は注意が必要です。その場合は、ローカルネットワーク無いからSSHやLuci(80ポート)にアクセスできるようにするためにファイアーウォールを無効or80ポートを開けていると思いますがそれだと外部からLuciが見えてしまいます。それを回避するためにLuciのポートを変更します。

Luciポート変更は/etc/config/uhttpdを開いてhttpのポートが定義されている部分を変更し、

        option listen_http '0.0.0.0:8080 [::]:8080'

みたいな感じで8080にしました。/etc/init.d/uhttpd restartやLuci(システム→スタートアップ)からuhttpdを再起動して下さい。これ以降、Luciへの接続は:8080をつけて、8080ポートでアクセスしてください。

ACME自体はluci-i18n-acme-jaをインストールするとLuciから設定できます。証明書の期限が来た時に通知してくれるメールアドレスと、証明書設定で、ドメイン名を設定し、有効化すれば自動で証明書が発行されます。パスは下みたいな感じです。

証明書: /etc/acme/ドメイン名/fullchain.cer
鍵: /etc/acme/ドメイン名/ドメイン名.com.key

OpenWRT上でPostfixとDovecotのメールサーバを立てる
ACME証明書
ACMEの設定

Postfixの設定

/etc/postfix/main.cf

ドメイン、ホスト名周りの設定

myhostname = サーバのホスト名
mydomain = 使用するメールアドレスのドメイン
myorigin = $mydomain

外部からのアクセスを有効にします。

inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

Maildir形式で保存します。

home_mailbox = Maildir/

メールサーバソフトを非公開に

smtpd_banner = $myhostname ESMTP unknow

最後の部分には、今まで設定してきたことと同じ内容が書かれている部分があります。適当にコメントアウトしてください。あと、data_directory、queue_directory、queue_directoryは外付けディスク(下の例では/mnt/md0)にして下さい。

inet_protocols = ipv4
default_database_type = cdb
config_directory = /etc/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
shlib_directory = /usr/lib/postfix
manpage_directory = no
data_directory = /mnt/md0/postfix
queue_directory = /mnt/md0/postfix
mail_spool_directory = /mnt/md0/postfix
# myhostname = OpenWRT 先程定義したためコメントアウト
# mydomain = lan 同じくコメントアウト
mynetworks_style = host

追加で、認証時のユーザ名を隠すために

# hide user
disable_vrfy_command = yes

認証方式であるSASLの設定です。dovecotの認証を利用します。

# setting for sasl
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions =
    permit_mynetworks
    permit_sasl_authenticated
    reject_unauth_destination

SMTPの設定です。SSL周りの設定を行っています。

# SMTP setting
smtpd_tls_security_level = may
smtpd_tls_loglevel = 1
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_received_header = yes

メールのサイズを制限を設定します。10MBあたりが一般的だと思います。

# Mail size limit
message_size_limit = 10485760

SSLの証明書、秘密鍵のパスの設定
ACMEを使用した場合は以下のパスです。

# pem path
smtpd_tls_cert_file = /etc/acme/ドメイン名/fullchain.cer
smtpd_tls_key_file = /etc/acme/ドメイン名/ドメイン名.com.key

メールヘッダにUnicodeの使用を可能とするSMTPUTF8を無効にします。これをしないと
postsuper: warning: smtputf8_enable is true, but EAI support is not compiled in
と言われます。

# bypass warning: smtputf8_enable is true, but EAI support is not compiled in
smtputf8_enable = no

/etc/postfix/master.cf

こんな感じに設定すればSMTP、SMTPs、Submissionポートとかが使用できるようになります。よくわかってないですが動作してるのでヨシ!

smtp      inet  n       -       n       -       -       smtpd
#smtp      inet  n       -       n       -       1       postscreen
#smtpd     pass  -       -       n       -       -       smtpd
#dnsblog   unix  -       -       n       -       0       dnsblog
#tlsproxy  unix  -       -       n       -       0       tlsproxy
submission inet n       -       n       -       -       smtpd
#  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_tls_auth_only=yes
  -o smtpd_tls_security_level=encrypt
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       n       -       -       smtpd
#  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING

あとは、Postfixを開始させます。

postfix start

実行時に様々なメッセージが出るので、適宜修正して下さい。多分、ディレクトリの権限や所有者についてのエラーが出ると思います。

Dovecotの設定

/etc/dovecot/dovecot.conf

使用するプロトコルをimapsだけにしたかったので変更しました。

# Protocols we want to be serving.
protocols = imaps

/etc/dovecot/conf.d/10-master.conf

IMPAsの設定を有効化します。

service imap-login {
  inet_listener imap {
    #port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }

Postfix用のSASL認証を有効にします。data_directory = /mnt/md0/postfixとしたため、それに合わせて、authファイルのパスも変更して下さい。

  # Postfix smtp-auth
  unix_listener /mnt/md0/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }

/etc/dovecot/conf.d/10-mail.conf

Maildir形式を設定します。~はユーザディレクトリを表しています。

mail_location = maildir:~/Maildir

/etc/dovecot/conf.d/10-auth.conf

SSLを有効化します。

disable_plaintext_auth = yes

ユーザ名@ドメイン名が付属した状態でログインを可能とします。これを有効にしないと、ユーザ名のみでなければログインできなくなってしまいます。

auth_username_format = %n

それ以外は多分もとから設定されていますが、一応載せておきます。

auth_mechanisms = plain
#!include auth-deny.conf.ext
#!include auth-master.conf.ext

!include auth-system.conf.ext
#!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-static.conf.ext

/etc/dovecot/conf.d/auth-system.conf.ext

設定する選択肢が2つあります。1つ目は、PAMをインストールして認証システムとして使用する方法です。もう一つは、passwd、shadowファイルを直接読み取り認証に使用する方法です。セキュリティとしてはPAMのほうが優れていますが、PAM自体のインストールと設定が必要です。それが手間だったので、今回はpasswd、shadowを直接読み取る方法にしました。

ディフォルトで有効となっているPAMを利用したpassdbを無効にします。

#passdb {
#  driver = pam
  # [session=yes] [setcred=yes] [failure_show_msg=yes] [max_requests=<n>]
  # [cache_key=<key>] [<service name>]
  #args = dovecot
#}

passdbをshadowベースにします。

passdb {
  driver = shadow
  # [blocking=no]
  #args =
}

userdbはそのままです。今回はpasswdでホームディレクトリを外付けドライブの/mnt/md0に指定しているので問題ありませんが、場合によっては、override_fields = home=/mnt/md0/%uとかにしたほうが良いかもしれません。

/etc/dovecot/conf.d/10-ssl.conf

SSLでの通信を必須とします。

ssl = required

証明書と秘密鍵のパスを指定します。ACMEを使用した場合

ssl_cert = </etc/acme/ドメイン名/fullchain.cer
ssl_key = </etc/acme/ドメイン名/ドメイン名.key

こんなもんです。あとは、dovecotを開始させます。

dovecot

エラー等は

logread

で確認できます。

ユーザの追加

メールのユーザを追加します。ユーザIDが小さいアカウントは動作しません。ホームディレクトリ下のMaildir/下にメールが配信されるので、ホームディレクトリは外付けドライブ(例/mnt/md0)にする必要があります。また、ホームディレクトリを作成する必要もあります。面倒なので、スクリプトを作成しました。これを使用すればメールユーザが簡単に作成できます。ただし、/etc/groupにmailuserを追加してください。
外付けドライブのマウントディレクトリは/mnt/md0となっています(4箇所)が、適当なものに変えて下さい。

#!/bin/ash

# enter new username
echo "Enter new username:"
read username

# check username
if grep -q "^$username:" /etc/passwd; then
    echo "Error: User $username already exists."
    exit 1
fi

# detect uid in passwd
uid=1000
while grep -q "^.*:x:$uid:" /etc/passwd; do
    uid=$((uid + 1))
done

# add user to /etc/passwd
echo "$username:x:$uid:1000:mailuser:/mnt/md0/$username:/bin/false" >> /etc/passwd
echo "$username:x:0:0:99999:7:::" >> /etc/shadow

# set passwd
passwd $username

# make dir
echo "make dir /mnt/md0/$username"
mkdir -p /mnt/md0/$username
chown $username:1000 /mnt/md0/$username

chmod 775 addmailuser.shとかで実行権限を与えて、実行して指示に従って入力すればユーザが作成されます。uidは1000から開いている順に割り当てられます。

mailuser:x:1000:mailuser

ポート開放

もちろんして下さい。
直接インターネットに接続されている場合は、Luciでネットワーク→ファイアウォール→ポートフォワーディングで設定できます。
ローカルネットワーク内の場合は、ゲートウェイでポートを解放してください。
ポートですが、IMAPsの993、SMTPの25、SMTPsの465、SMTP SubmissonPortの587が必須です。ACMEで定期的に自動で証明書を更新する場合は80、443ポートも解放してください。

OpenWRT上でPostfixとDovecotのメールサーバを立てる
ポート開放
解放すべきポート

動作確認

ここまでできたらとりあえず動作確認します。適当なメーラでIMAPでログインできます。メールアドレスも、ユーザ名も、パスワードも、ポート番号も間違っていないのにログインできない場合は、logreadを使用してログを確認して下さい。/etc/dovecot/conf.d/10-logging.congのauth_verbose = yesを有効にすると、詳細なログイン試行のログが見れます。

MXレコード

こっから先はDNS周りの設定です。

まず初めにMXレコードです。これは、メール用のDNSレコードみたいな感じです。すでに登録済みのAコードと同じ場合は、同じIPアドレスを登録するか、mail.unagidojyou.comみたいなCNAMEレコードを作って、それを参照するみたいな感じでも大丈夫です。

SPFの設定

SPFはメールの送信元IPアドレスと、DNSからのIPアドレスが等しいかどうかで正しい送信元か判定するものです。お使いのドメイン管理サイトでTXTレコードとして設定します。mxレコードを参照する場合は以下のような感じです。

"v=spf1 mx -all"

mxコード以外の指定の仕方もあります。各自で調べてみて下さい。

DKIMの設定

これが難しくて他のLinux機が必要です。一応Rubyとモジュールをいくつかインストールすれば動くようですが、どのモジュールをインストールすればよいのかわからなかったので他のLinux機で鍵と証明書を生成しました。

パッケージとして、opendkimをインストールしてください。

OpenWRT上でPostfixとDovecotのメールサーバを立てる
OpenDKIM
opendkimのインストール

Postfixで追加の設定が必要です。以下を追加して下さい。
/etc/postfix/main.cf

# DKIM
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = inet:localhost:8891
milter_default_action = accept

鍵の発行ですが、適当なLinuxにて同じくopendkimをaptやyumでインストールします。その後、

sudo mkdir /etc/opendkim/key/ドメイン名
sudo opendkim-genkey -D /etc/opendkim/key/ドメイン名/ -d ドメイン名

で公開鍵(.txt)と秘密鍵(.private)を作成します。セクタの入力を求められたら、適当に今日の日付とかにします。これができたら、scpなどでOpenWRT機に転送して下さい。
OpenWRTでも、鍵の場所はmkdir /etc/opendkim/key/ドメイン名で作成し、その中に格納して下さい。

続いて、OpenDKIMの設定を行います。
/etc/opendkim.conf

ドメインの設定をします。

# A set of domains whose mail should be signed by this filter.
# Mail from other domains will be verified rather than being signed
domain                  使用するメールアドレスのドメイン

セクタの指定、秘密鍵の指定を行います。秘密鍵は多分、セクタ.privateって感じになっていると思います。

# Defines the name of the selector to be used when signing messages
Selector                セクタ
KeyFile                 /etc/opendkim/key/ドメイン名/.privateのファイル

Postfixのホストの指定をします。DKIMサーバとPostfixのサーバが同一機なので、次IPアドレスと、ループバックIPアドレスを指定しておけば問題ありません。

## Hosts to sign email for - 127.0.0.1 is default
## See the OPERATION section of opendkim(8) for more information
#
#InternalHosts          192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12
InternalHosts           自機のIPアドレス, 172.0.0.1

あとは

opendkim

でスタートさせます。

続いて、レコードの設定です。

cat /etc/opendkim/key/ドメイン名/.txtのファイル

でファイル中身を表示させます。そしたら、ドメイン管理サイトでtxtレコードを追加し、ドメインは

セクタ名._domainkey.ドメイン名

レコードの内容は

“v=DKIM1; h=sha256; k=rsa;
p=*********”
“*******”

みたいに少し変えて登録します。

ADSPレコードの登録

追加でADSPレコードも登録します。txtレコードで、ドメイン名は

_adsp._domainkey.ドメイン名

レコードの内容はdkim=unknown(DKIMで署名されていないものも送信)か、dkim=all(すべて署名済み)、dkim=discardable(DKIMで署名されていないor署名が無効の場合破棄)のいずれから選びます。特に深く考えずにdkim=unknownを設定しました。

再起動時の設定

機種によると思いますが、外付けHDDがかなり遅れてマウントされることがあります。こうなるとPostfixがHDDがマウントされるよりも早く実行されてしまい、マウンタポイントにディレクトリが作成されてしまったりして、面倒なことになります。そのため、別で起動時のシェルスクリプトを作成すると良いと思います。

自分の場合は、mdadmを使用したRAID1を使用しており、スタートアップ時にRAIDの構成用にシェルスクリプト(マウントまで行う)を使用していたため(詳細はこの記事)、このシェルスクリプトを実行したあとにpostfixとdovecotを実行するようにしました。

OpenWRT上でPostfixとDovecotのメールサーバを立てる
スタートアップ
スタートアップ設定

おわりに

メールサーバの立ち上げ(2週間)も、この記事の作成(1.5週間)も大変でした。Googleで検索をかけてもOpenWRTでメールサーバを構築している人がいなかったのでOpenWRT固有のエラーが出た時は手こずりました。また、自分のメールサーバではVPNでの接続も行っているので、メモリが足りなくて落ちるなんてこともありました。メールサーバを立ててから記事を書き終わるまで時間が空いてしまったので掻き落としがあるかもしれません。気をつけて下さい。メインのメールアドレスを移行するつもりなので、落ちないようにメンテナンスを頑張ります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)