CentOS 7へメールサーバー(Postfix/Dovecot)をインストールしよう

 CentOS 7でメールサーバーを構築するため、PostfixとDovecotをインストールおよび設定します。

 PostfixおよびDovecotをインストールする上で色々なサイト、および仕事先サーバーの設定を参照させていただきました。情報の渦に感謝。設定が多岐に渡っているので未経験者が行おうとすると混乱してしまいます。まずは動いている環境を参考にカスタマイズと理解を進めるがよさそうです。

 改めて書くことでもありませんが、Postfixはメールを送信するための転送エージェント(MTA)でCentOS 7には標準で組み込まれています(触れたVPSでは。一からだと違うのかもしれませんが)。
Dovecot(ダヴコット、私にはドベコットとしか読めませんが)はIMAPとPOP3のサーバーで、両者でメールの送信と受信が行われます。

インストール前の環境

 それぞれ次の状況となっています。MySQLでバーチャルホストおよびメールアカウントを管理するためMariaDBを使用します。

  • CentOS 7: 7.7.1908 (Core)
  • MariaDB: 10.4.12-1
  • PHP: 7.4.4
  • Postfix: 2.10.1-7 (VDAパッチ有り インストール記事

パケットフィルターおよびファイアウォールの変更

 メール配信およびメールクライアント接続のため、VPS側のパケットフィルターとCentOS 7で設定のファイアウォールを変更します。

VPS側のパケットフィルターはApacheと同じくVPSコントロールパネルからパケットフィルタの編集で「メール」を選択すると必要なポートが開放されます。

CentOS 7側はfirewall-cmdコマンドでメール配送に必要となる各ポートを指定します。なお、本運用ではSMTPs、POP3s、IMAP4sのみ利用するというのであれば、ポート110や587、143(IMAP4)は閉じてもよいと思います(後で閉じていることを忘れないように)。

$ sudo firewall-cmd --add-port=25/tcp --permanent
$ sudo firewall-cmd --add-port=110/tcp --permanent
$ sudo firewall-cmd --add-port=143/tcp --permanent
$ sudo firewall-cmd --add-port=465/tcp --permanent
$ sudo firewall-cmd --add-port=587/tcp --permanent
$ sudo firewall-cmd --add-port=993/tcp --permanent
$ sudo firewall-cmd --add-port=995/tcp --permanent
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: dhcpv6-client http https ssh ssh-spec
ports: 25/tcp 110/tcp 143/tcp 465/tcp 587/tcp 993/tcp 995/tcp
protocols:

メール配信のためのアカウントとディレクトリを作成

 届いたメールをMaildir形式で管理します。そのためのサーバーアカウントして、vmailbox というアカウントを準備します。UIDは、Postfixでmaildir 所有者のUID下限を1000とするのでそれより大きくします。ディレクトリのPermission設定についてはそれぞれの環境の都合もありますね。

$ sudo groupadd -g 10000 vmailbox
$ sudo useradd -g vmailbox -u 10000 vmailbox
$ ls /home
foo vmailbox
$ sudo chmod 755 -R /home/vmailbox

メール配信のためのDNSレコードの登録

 

メールサーバー用のTLS証明書の取得

 昨今はメールサーバー間通信路の暗号化、メールサーバーとMUA(Outlookなどのメールソフト)間の暗号化が必須のようです。こちらで(CentOS7へTLS/SSL(Let's Encrypt)を導入しよう)取得しているものとします。

データベースの作成

 メールアカウントなどを管理するためのデータベースを作成します。データベース名および操作するアカウント名を postfix で作成します。パスワードは置き換えてください。
データベースの文字コードは指定しなければデフォルト(ここではutf8mb4)となります。Emojiが入るわけでもないのでutf8としています。

$ mysql -u root -p

MariaDB [(none)]> create database postfix default character set utf8 collate utf8_general_ci;

MariaDB [(none)]> create user 'postfix'@'localhost' identified by 'パスワード';

MariaDB [(none)]> grant all privileges on postfix.* to 'postfix'@'localhost' identified by 'パスワード';

MariaDB [(none)]> flush privileges;

Dovecotをインストール

 Dovecotおよび関連モジュール(DBおよび認証関連)をインストールします(モジュールは参照サイトより)。

$ sudo yum install dovecot dovecot-mysql cyrus-sasl libdb-devel openldap-devel cyrus-sasl-devel

Postfixの設定

 Postfixの設定ファイル "main.cf"、"master.cf"を編集します。

Postfixでは多くのパラメータが初期値で設定されていて、postconf -d で確認できます。

設定ファイル "/etc/postfix/main.cf"のパラメータを編集します。
(参考: Postfix 設定パラメータ http://www.postfix-jp.info/trans-2.1/jhtml/postconf.5.html

設定ファイルの文法チェックは、"sudo postfix check"で行えます。エラーが無ければ何も返しません。

/etc/postfix/main.cf

myhostname = mail.exsample.com
# (デフォルト: /etc/hostname 参照) このメールシステムのインターネットホスト名

mydomain = exsample.com
# (デフォルト: localdomain) このメールシステムのインターネットドメイン名。デフォルトでは $myhostname から最初の要素を引いたものを使います。

myorigin = $myhostname
# (デフォルト: $myhostname) ドメイン名で、ローカルで投函されたメールはそこから来たように見え、またローカルで投かんされたメールはそこに配送されます。

inet_interfaces = all
# (デフォルト: all)

inet_protocols = ipv4
# (デフォルト: all) ネットワーク接続を張る際および受ける際に使うプロトコル

mydestination = $myhostname
# (デフォルト: $myhostname, localhost.$mydomain, localhost) メール配送transportを使って配送されるドメインのリスト(/etc/aliasの受信者を含むならデフォルト値で)。バーチャルドメインは指定しない。

local_recipient_maps = $alias_maps
# (デフォルト: proxy:unix:passwd.byname $alias_maps) ローカル受信者の全ての名前もしくはアドレスを持つ検索テーブル(昔はログインアカウント=メールアカウントでしたが)

mynetworks_style = host
# (デフォルト: subnet) mynetworks パラメータのデフォルト値を生成する方法。ローカルマシンのみを"信頼する"のであれば、"host" を指定

home_mailbox = Maildir/
# (デフォルト: 空) メール保管形式。Maildir形式の場合、"/"で終わらせる

smtpd_banner = $myhostname ESMTP unknown
# (デフォルト: $myhostname ESMTP $mail_name) SMTP グリーティングバナーで 220 状態コードの後に続くテキスト。デフォルトはPostfixを表示。外部へ知らせる必要は特にないので多くはunknownの文字列を入れている模様。

"main.cf"の追加パラメータ(バーチャルホスト関連)。ドメインやメールボックスはMySQL(MariaDB)で指定
http://www.postfix-jp.info/trans-2.3/jhtml/VIRTUAL_README.html
 http://unixservermemo.web.fc2.com/sv/postfix-maincf-vmailbox.htm

/etc/postfix/main.cf

virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
# 指定されたドメインのリストの最終配送先。指定したドメインがバーチャルメールボックスドメインであると宣言

virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
# 指定されたドメインのリストの最終配送先(配送先メールディレクトリ)。受信者アドレスを確認し、存在しない受信者宛のメールを拒否

virtual_mailbox_base = /home/vmailbox
# $virtual_mailbox_mapsに付けるプレフィックス。結果ここでは /home/vmailbox/ドメイン名/アカウント名/へ配信される

parent_domain_matches_subdomains =
# 後方互換性パラメータ。空白を設定

virtual_minimum_uid = 1000
# maildir所有者のUIDの下限を指定

virtual_uid_maps = static:10000
# メールボックスへの書き込みに使用するユーザID。ここでは10000固定

virtual_gid_maps = static:10000
# メールボックス配送に使うグループID。ここでは10000固定

virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
# 特定のメールアドレスやドメインを他のローカルまたはリモートアドレスにエイリアスする、検索テーブル


"main.cf"の追加パラメータ(quota メールボックス容量制限)

/etc/postfix/main.cf

virtual_mailbox_limit = 0
# バーチャルドメインでの1つのメールボックスの最大容量(バイト単位)。0は無制限、0以外はpostfixadminでメールボックスで指定できる最大値

virtual_mailbox_limit_override = yes
# バーチャルドメイン毎のメールボックスのサイズ指定を有効

virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
# メールアドレス毎のquotaを指定する、検索テーブル

virtual_overquota_bounce = yes
# yesで、quota制限の場合すぐにエラーメールを返す

virtual_maildir_extended = yes
# メールボックスのmaildirsize

"main.cf"の追加パラメータ(SMTPクライアントおよびサーバーのTLS関連)。私の環境ではTLSv1は未だ切れなさそう
http://www.postfix-jp.info/trans-2.3/jhtml/TLS_README.html

/etc/postfix/main.cf

smtp_tls_security_level = may
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
smtp_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_security_level = may
smtpd_tls_key_file = /etc/letsencrypt/live/証明書ドメイン名/privkey.pem
smtpd_tls_cert_file = /etc/letsencrypt/live/証明書ドメイン名/fullchain.pem
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_protocols = !SSLv2, !SSLv3

"main.cf"の追加パラメータ(その他)

/etc/postfix/main.cf

disable_vrfy_command = yes
# SMTP VRFY コマンドを無効にします

mailbox_size_limit = 0
# mboxの最大サイズ(Maildirでは無関係?)

message_size_limit = 20971520
# エンベロープ情報を含む、バイト単位の1メッセージの最大サイズ(例では20MB)

queue_run_delay = 300s
# 遅延されたキューがキューマネージャによってスキャンされる時間間隔

minimal_backoff_time = 300s
# 遅延メッセージの配送を試行する最小の時間間隔

maximal_backoff_time = 3600s
# 遅延メッセージの配送を試行する最大の時間間隔

maximal_queue_lifetime = 24h
# 配送できないものとして送り返すまでに、メッセージがキューに入っている最大の時間

bounce_queue_lifetime = 24h
# 配送できないと見なすまでに、バウンスメッセージがキューに入っている 最大の時間

smtpd_helo_required = yes
# リモートSMTPクライアントがSMTPセッションの最初でHELOまたはEHLOコマンドで自己紹介することを要求

smtpd_sasl_auth_enable = yes
# SASL認証を有効

smtpd_sasl_type = dovecot
# 認証に使うSASLプラグインの種類

smtpd_sasl_path = private/auth
# Dovecot認証デーモンソケットの場所を指定

smtpd_sasl_security_options = noanonymous
# SMTPサーバーがクライアントに提供する認証メカニズムを制限(noanonymous 匿名ログインを許可しない)

broken_sasl_auth_clients = yes
# 古いバージョンの AUTH コマンド (RFC 2554) を実装したSMTPクライアントとの相互運用性を有効にします(Outlook Expressの時代らしいので無効にしても問題なし?

"main.cf"の追加パラメータ(アクセス制限関係)

/etc/postfix/ip_check および /etc/postfix/sender_checkは、用意するデータが無ければ空ファイルを作成しpostmapコマンドで/etc/postfix/ip_check.dbおよび/etc/postfix/sender_check.dbを作成しておく。

/etc/postfix/main.cf

# SMTPサーバーがクライアントからSMTP接続の要求を受けた際に適用するアクセス制限
# check_client_access check_sender_access はrblでアクセス制限を受けたとき回避できる
smtpd_client_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_client_access hash:/etc/postfix/ip_check,
check_sender_access hash:/etc/postfix/sender_check,
reject_rbl_client bl.spamcop.net,
reject_rbl_client zen.spamhaus.org,
reject_unauth_pipelining,
permit

# SMTPサーバーが SMTP HELOコマンドの場面で適用する制限
smtpd_helo_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_invalid_helo_hostname,
permit

# SMTPサーバが MAIL FROMコマンドの場面で適用する制限
smtpd_sender_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_non_fqdn_sender,
reject_unknown_sender_domain,
permit

# Postfixが受け取ったメールを他のサーバーへリレーさせるポリシーを規定
smtpd_relay_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
defer_unauth_destination

# SMTPサーバーが RCPT TOコマンドの場面で適用する制限
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
defer_unauth_destination,
reject_unlisted_recipient,
reject_non_fqdn_recipient,
reject_unknown_recipient_domain

上記設定で参照する検索テーブルは、hash: の代わりに mysql: でMySQLデータベースに接続します。各テーブルは postfixadmin で作成します。
http://www.postfix-jp.info/trans-2.3/jhtml/MYSQL_README.html

各テーブル検索用の設定ファイルは次の形式です。

user = mysql ユーザー名 (postfix)
password = mysqlパスワード
hosts = localhost
dbname = データベース名 (postfix)
query = SELECT 検索結果 FROM テーブル名 WHERE 検索名='%s' AND active = '1'

mysql_virtual_domains_maps.cf

user = postfix
password = postfixパスワード
hosts = localhost
dbname = postfix
query = SELECT domain FROM domain WHERE domain = '%s' AND active = '1'

mysql_virtual_mailbox_maps.cf

user = postfix
password = postfixパスワード
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username = '%s' AND active = '1'

mysql_virtual_alias_maps.cf

user = postfix
password = postfixパスワード
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias WHERE address = '%s' AND active = '1'

mysql_virtual_mailbox_limit_maps.cf

user = postfix
password = postfixパスワード
hosts = localhost
dbname = postfix
query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'

 

設定ファイル"master.cf"は、smtpなどのサービス実行有無を設定します。デフォルトではsmtpのみ有効となっていて、それにsubmissionやsmtpsなどを追加します。
赤色文字の行をコメントアウトします。この設定ではsubmissionはSMTP認証です。

/etc/postfix/master.cf

# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
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_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=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=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING

Dovecotの設定

 dovecotの設定は、設定ファイル"/etc/dovecot/local.conf"を作成し記述します。IMAPでメールボックスの容量ワーニングを行いたいときは、"/etc/dovecot/conf.d/90-quota.conf"でquota_ruleを設定するようですが、私はPOP3で受けて数日間分をメールサーバーに残すだけなので、試していません。

/etc/dovecot/local.conf

protocols = imap pop3
listen = *

log_path = /var/log/dovecot_log
auth_verbose = yes
auth_debug_passwords = yes
auth_debug = yes
# 認証失敗等の参考情報を出力

disable_plaintext_auth = no
# 暗号化されていない認証を無効を無効、つまり許可(POP3で)

auth_mechanisms = plain login
# 認証時のパスフレーズの送信方法。plainは平文。

mail_location = maildir:/home/vmailbox/%d/%n
# メールの保管場所

first_valid_uid = 1000
first_valid_gid = 1000
mail_plugins = quota
login_greeting = ready.

ssl = yes
ssl_cert = </etc/letsencrypt/live/ドメイン名/fullchain.pem
ssl_key = </etc/letsencrypt/live/ドメイン名/privkey.pem
ssl_protocols = !SSLv2 !SSLv3
# local_name ドメイン名 { 証明書パス } とすると、POP3Sでバーチャルドメイン毎に設定できるが、PostfixがSNIに対応しないらしい

protocol imap {
imap_client_workarounds = delay-newmail tb-extra-mailbox-sep
mail_plugins = $mail_plugins imap_quota
mail_max_userip_connections = 30
}
protocol pop3 {
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
mail_max_userip_connections = 30
}
passdb {
driver = sql
args = /etc/dovecot/dovecot-mysql.conf
}
userdb {
driver = sql
args = /etc/dovecot/dovecot-mysql.conf
}

# PostfixがSASL認証するときのソケット
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
plugin {
quota = maildir:User quota
}

passdbおよびuserdbで索引するデータベースの設定ファイル"dovecot-mysql.conf"を作成。

quota_ruleを使用する場合に必要となるキーはこの辺りを参照
(https://doc.dovecot.org/configuration_manual/authentication/user_databases_userdb/)

/etc/dovecot/dovecot-mysql.conf

driver = mysql
connect = host=localhost dbname=postfix user=postfix password=postfixのmysqlパスワード
default_pass_scheme = SHA512-CRYPT
password_query = SELECT password FROM mailbox WHERE username = '%u' AND active = '1'
user_query = SELECT concat('/home/vmailbox/', maildir) AS home, 10000 AS uid, 10000 AS gid FROM mailbox WHERE username = '%u' AND active = '1'

PAM認証が有効だと、認証に余分な時間がかかるので無効に設定。
conf.d/10-auth.confの終端付近を編集。赤の行をコメントアウト。

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

#!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-vpopmail.conf.ext
#!include auth-static.conf.ext

 

Dovecotの起動

 PostfixおよびDovecotの設定を終えたら、Dovecotを起動します。dovecotの設定ファイルのチェックは、"dovecot -n"でできます。

$ systemctl start dovecot
$ systemctl enable dovecot

Postfixadminのインストール

 メールアカウントのGUI管理ツールpostfixadminを /usr/share/へインストールします。

$ cd ~/  あるいは 適当な作業ディレクトリ
$ curl -OL https://sourceforge.net/projects/postfixadmin/files/postfixadmin/postfixadmin-3.2/postfixadmin-3.2.tar.gz
$ tar xzf postfixadmin-3.2.tar.gz
$ sudo mv ./postfixadmin-3.2 /usr/share/postfixadmin

 Apacheでpostfixadminを実行するパスおよびディレクトリを設定します。RequireALLディレクティブ内はアクセス制限の為に設定します。使用しなければ、 Require all granted を設定します。

/etc/httpd/domain.d/ポート443で設定したファイル等

(中略)
Alias /postfixadmin/ "/usr/share/postfixadmin/public/"
<Directory /usr/share/postfixadmin/public>
AddDefaultCharset UTF-8
AllowOverride All

<RequireALL>
AuthUserFile ベーシック認証ファイルのパス
AuthName "Please user name."
AuthType Basic
Require valid-user
Require host リモートホストのドメイン部分
</RequireALL>
</Directory>

 postfixadminのセットアップを実行する前に次の設定ファイル"config.local.php"を作成します。

/usr/share/postfixadmin/config.local.php

<?php
$CONF['configured'] = true;
$CONF['default_language'] = 'ja';
$CONF['database_password'] = 'mysql postfixのパスワード';
$CONF['encrypt'] = 'dovecot:SHA512-CRYPT';
$CONF['aliases'] = '0';
$CONF['mailboxes'] = '0';
$CONF['maxquota'] = '0';
$CONF['domain_quota_default'] = '0';
$CONF['quota'] = 'YES';
$CONF['used_quotas'] = 'YES';
$CONF['emailcheck_resolve_domain'] ='NO';
$CONF['show_footer_text'] = 'NO';
?>

 postfixadmin 3.2では次のディレクトリ "templates_c" を作成する必要がありました。

sudo mkdir /usr/share/postfixadmin/templates_c
sudo chmod 777 /usr/share/postfixadmin/templates_c

Postfixadminのセットアップ

 Webブラウザで、https://ドメイン名/postfixadmin/setup.phpを開きます。

202004-postfixadmin-setup.png

次のワーニングを表示したときは、IMAP用のモジュールが不足しています。IMAP使用時はインストールしたPHPのバージョンに合わせてインストールします。

202004-warning-php-imap.png

私の環境ではPHP7.4をインストールしたので。

$ sudo yum install --enablerepo=remi,remi-php74 php-imap

postfixadminのセットアップパスワードを入力します。

202004-postfixadmin-setup-password.png

"Generate password hash"ボタンをクリックすると、config.local.phpへ追加する $CONF['setup_password']の行を表示するので、config.local.phpへ追加します。

202004-add-setup-password.png

先程のセットアップパスワードおよび、postfixadminの管理者メールアドレスおよびパスワードを設定すると、セットアップは終了です。

/usr/share/postfixadmin/public/setup.php はセットアップ以降は使用しないので、削除あるいは、上位ディレクトリへ移動などしてアクセスできないようにします。

Webブラウザで、https://ドメイン名/postfixadmin/ を開き、次のように表示すればメールアカウントを作成できます。

202004-postfixadmin-login.png

dovecot_logのローテート

追補

  1. SSHクライアントを用意しよう
  2. さくらのVPSコントロールパネルからCentOS 7をインストールしよう
  3. CentOS7を初期セットアップしよう
  4. SSHログインで公開鍵認証を使おう
  5. CentOS7へWebサーバー(Apache)をインストールしよう
  6. CentOS7へTLS/SSL(Let's Encrypt)を導入しよう
  7. CentOS7へPHP(7.4)をインストールしよう
  8. CentOS7へMariaDBをインストールしよう
  9. CentOS7へメールサーバー(Postfix/Dovecot)をインストールしよう

前へ

CentOS 7.8.2003 (Core)にアップデート

次へ

MovableTypeをインストール