Postfix / Dovecot の組合せでメールサーバを用意
篠原 隆司
アフィリエイト広告を利用しています
このページの内容が役に立ったら X (旧twitter) でフォローして頂けると励みになります
挨拶や報告は無しで大丈夫です
さくらのVPSにAlmaLinux9.3をインストールした覚書です。
ここからはいよいよ本来の目的であるメールサーバの構築に入っていきます。
なお本番環境で利用される場合はここにある内容だけを鵜呑みにせずセキュリティ専門家に相談されることをお勧めします。
環境
実施日 | 2024-04-28 |
サーバ | さくらのVPS 2G |
OS | AlmaLinux9.3 |
cat /etc/redhat-release
AlmaLinux release 9.3 (Shamrock Pampas Cat)
設定の確認
順番が前後しますが、設定などの確認方法を先に載せておきます。
postfix check
postconf -n
dovecot -n
Postfixのインストール確認
postfixがインストールされていることを確認します。
postconf -d | grep mail_version
mail_version = 3.5.9
milter_macro_v = $mail_name $mail_version
まだの場合は下記よりインストールを行います。
AlmaLinux9.3にメールサーバのPostfixをインストールPCREサポートの確認
postconf -m
「pcre」が含まれているか確認し、なければインストールします。
dnf install postfix-pcre
Dovecotのインストール確認
Dovecotがインストールされていることを確認します。
rpm -qa dovecot
dovecot-2.3.16-10.el9.x86_64
main.cf の設定(変更)
postfixを設定していきます。
ここでは「mail.example.com」をメールドメインとして設定することにします。
「mail.example.com」を実際に使用するメールドメインに読みかえてください。
vi /etc/postfix/main.cf
項目自体は main.cf に既にあると思いますので、下記のように書き換えます。
# サーバの完全修飾ドメイン名(FQDN)
myhostname = mail.example.com
# サーバが属するドメイン名
mydomain = example.com
# メールの送信元アドレスに使用されるデフォルトのドメイン
myorigin = $mydomain
# Postfixがメールを受信するために待ち受けるインターフェース
inet_interfaces = all
# ローカルで受信し配送するメールの対象ドメイン
# = の右は何もなし = ローカル配送の対象ドメインは無し
mydestination=
# デフォルトですべてコメントになっているはずなのでそのまま
# デフォルトでローカルからのみ許可
# mynetworks で引っかかっても、あとで設定するSMTP認証が通ればOK
# mynetworks = ・・・
# このサーバがリレーを許可するドメイン
relay_domains = $mydestination
# ユーザーのメールを保存するフォーマットとディレクトリ
home_mailbox = Maildir/
# SMTP サーバが接続を受けた際にクライアントに送信するグリーティングメッセージ
smtpd_banner = $myhostname ESMTP unknown
main.cf には他にも設定することがあるのですが、まずはここまでで一区切りとします。
main.cf に設定(追記)
先ほどの内容は既にある項目への「書き換え(確認含む)」でした。
次は、デフォルトでは main.cf に無い項目を追加します。
vi /etc/postfix/main.cf
ファイルの末尾に書き足していきます。
省略してもデフォルトで同じ値になるものもありますが、理解のために明示的に書き記します。
# "user%domain" の形から "user@domain" への書き換えを有効にする
allow_percent_hack = yes
# "site!user" から "user@site" への書き換えを有効にする
swap_bangpath = yes
# 古い MicroSoft Outlook Express に対応
broken_sasl_auth_clients = yes
# Postfix SMTP サーバの SASL 認証を有効にする
smtpd_sasl_auth_enable = yes
# 許可しない認証方式
# noplaintext : 平文パスワードを使う認証方法を許可しない
# noactive : non-dictionary active 攻撃に脆弱な認証方法を許可しない
# nodictionary : passive dictionary 攻撃に脆弱な認証方法を許可しない
# noanonymous : 匿名ログインを許可しない
# smtpd_sasl_security_options = noanonymous,noplaintext
smtpd_sasl_security_options = noanonymous
# マルチドメイン環境では指定しない(コメントにしておく)
# smtpd_sasl_local_domain = $mydomain
# smtpd_sasl_local_domain = $myhostname
# 受信メールの制限
#smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination
# SMTPサーバがクライアントからSMTP接続の要求を受けた際の制限
smtpd_client_restrictions = permit_mynetworks,
# reject_rhsbl_client rhsbl.ahbl.org,
reject_rbl_client spamcop.net,
reject_rbl_client dynablock.wirehub.net,
reject_rbl_client sbl.spamhaus.org,
# reject_unknown_client,
permit
# Postfix SMTP サーバが MAIL FROM コマンドの場面で適用する制限
# smtpd_sender_restrictions = reject_unknown_sender_domain
# 仮想ユーザーのメールボックスへメールを配送する設定
local_transport = virtual
# virtualhostを使っているので mailbox_command ではなく virtual_transport を使う
# virtual_transport = virtual
virtual_transport = procmail
# virtual_alias_maps = hash:/etc/postfix/virtual
virtual_alias_maps = hash:/etc/postfix/virtual, pcre:/etc/postfix/virtual.pcre
virtual_alias_domains = $virtual_alias_maps
virtual_mailbox_base = /home/user_mails
virtual_mailbox_domains = /etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/etc/postfix/virtual_maps
virtual_minimum_uid = 499
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
transport_maps = hash:/etc/postfix/transport
message_size_limit = 20971520
fatal: no SASL authentication mechanisms
次のエラーになるときは smtpd_sasl_security_options を確認してみてください
postfix/smtpd[1590]: fatal: no SASL authentication mechanisms
postfix/master[1533]: warning: process /usr/libexec/postfix/smtpd pid 1590 exit status 1
postfix/master[1533]: warning: /usr/libexec/postfix/smtpd: bad command startup -- throttling
vi /etc/postfix/main.cf
dovecotでSMTP認証をするならnoplaintext があるとダメです
# smtpd_sasl_security_options = noanonymous,noplaintext
smtpd_sasl_security_options = noanonymous
サブミッションポート(587)を有効化
サブミッションは Dovecot で行うため、Postfix 側は触らない
ファイアーウォールやパケットフィルターで 587 が塞がっていたら許可します。
SASLの準備と自動起動設定
SASLを確認します。
入れた記憶がなくても postfix を入れたときに一緒に入っていると思います。
rpm -qa | grep sasl
cyrus-sasl-lib-2.1.27-21.el9.x86_64
この場合、lib だけインストールされています。
本体がないのでインストールします。
dnf install cyrus-sasl
rpm -qa | grep sasl
cyrus-sasl-lib-2.1.27-21.el9.x86_64
cyrus-sasl-2.1.27-21.el9.x86_64
これでOKです。
自動起動を有効
systemctl enable saslauthd
起動
systemctl start saslauthd
停止
systemctl stop saslauthd
ステータスを確認
systemctl status saslauthd
SASLの認証を変更する
SASLの認証方式を外部のプラグインを使用するように変更します。
ちなみにMySQLとPostfixの連携を考えていましたが、諸々を考えるとMySQLは使わない方が良さそうとなりました。(今回のケースではです)
dnf install cyrus-sasl-lib cyrus-sasl-plain
saslpasswd2 コマンドは後述する 「update_mailbox.php」に含まれます。
vi /etc/sasl2/smtpd.conf
pwcheck_method: auxprop
auxprop_plugin: sasldb
# pwcheck_method: saslauthd
mech_list: plain login
dovecotのインストールと設定
dovecotの準備をしていきます
dnf install dovecot
dovecot --version
2.3.16 (7e2e900c1a)
設定を変更する
vi /etc/dovecot/local.conf
submission_relay_host = smtp.example.com
protocols = imap pop3 lmtp submission
# SSL を使うとき (デフォルトではONになっている)
ssl_cert = </home/ssl/ssl-example.com.crt
ssl_key = </home/ssl/ssl-example.com-no-pass.key
ssl_ca = </home/ssl/ssl-example.com.ca
# mail_location = maildir:~/Maildir
mail_location = maildir:/home/user_mails/%d/%n/Maildir
passdb {
driver = passwd-file
args = /etc/dovecot/mail-password
}
userdb {
driver = passwd-file
args = /etc/dovecot/mail-password
}
起動
systemctl start dovecot
再起動
systemctl restart dovecot
自動起動
systemctl enable dovecot
状態
systemctl status dovecot
設定の確認
postconf -n
dovecot -n
virtual の確認
すべてコメントされていることを確認
vi /etc/postfix/virtual
設定内容を反映させる
postmap /etc/postfix/virtual
ヴァーチャルディレクトリを作成
ディレクトリの雛形を用意する
メールディレクトリの雛形を作成します。
mkdir -p /etc/skel/Maildir/{new,cur,tmp}
chmod -R 700 /etc/skel/Maildir/
仮想ユーザーディレクトリ
mkdir /home/user_mails
chmod 1777 /home/user_mails
procmailrc の設定
dnf install procmail
/etc/postfix/master.cf
次の内容を追記します。
# procmailrc
procmail unix - n n - - pipe
flags=R user=vmailuser argv=/usr/bin/procmail -t -m USER=${user} DOMAIN=${nexthop} /etc/procmailrc
/etc/procmailrc
procmail を設定していきます
vi /etc/procmailrc
SHELL=/bin/bash
PATH=/usr/bin:/bin
DROPPRIVS=yes
# MAILDIR=$HOME/Maildir
MAILDIR=/home/user_mails/$DOMAIN/$USER/Maildir
DEFAULT=$MAILDIR/
# ロックファイル
LOCKFILE=/home/user_mails/.procmail.lock
# ログ出力先
# LOGFILE=$MAILDIR/.procmail.log
# LOGFILE=/home/takashi/logs/.procmail.log
LOGFILE=/home/user_mails/.procmail.log
# 詳細ログ出力
VERBOSE=OFF
# 未承諾広告メール削除
:0
* ^Subject:.*iso-2022-jp
* ^Subject:\/.*
* ? echo "$MATCH" | nkf -mwZ2 | sed 's/[[:space:]]//g' | egrep '未承諾広告※'
/dev/null
vi /etc/postfix/main.cf
main.cf には先の工程で下記を追記しているので確認だけしておきます。
vi /etc/postfix/main.cf
virtual_transport = procmail
vmailuser ユーザーの作成
「vmailuser」ではなく名前はなんでも良いですが変える場合は master.cf など他の個所も統一します。
まずは 5000 のユーザーが作られていないことを確認します。
cat /etc/group | grep 5000
何もでてこなければ作られていません。
作りましょう。
groupadd -g 5000 vmailuser
useradd -u 5000 -g vmailuser -s /sbin/nologin vmailuser
ログのローテーション
procmail のログのローテーションを設定します。
vi /etc/logrotate.d/procmail
/home/user_mails/.procmail.log {
missingok
nocreate
notifempty
}
メールユーザースクリプトの準備
メールユーザーの管理はスクリプトを使って行うことにします。
次のファイルを作成します。
メールアカウント設定
/root/mail/config_mail_users.php
<?php
$config_mail_users = [
'real' => [
],
'virtual' => [
'example.com' => [
'sample1' => ['status' => 'use', 'password' => 'メールパスワード'],
'sample2' => ['status' => 'use', 'password' => 'メールパスワード'],
'sample3' => ['status' => 'use', 'password' => 'メールパスワード'],
],
'sub.example.com' => [
'sample' => ['status' => 'use', 'password' => 'メールパスワード'],
],
],
];
メールアカウント設定の更新スクリプト
メール設定ファイルをpostfix向けのファイルに変換します
/root/mail/update_mailbox.php
<?php
$config_mail_users = [];
include __DIR__ . '/config_mail_users.php';
$pathBase = '/home/user_mails';
if ( ! file_exists($pathBase)) mkdir($pathBase, 1777, true);
shell_exec('chmod 1777 ' . $pathBase);
$virtual_domains = '';
$virtual_maps = '';
$dovecot_passwd = '';
foreach($config_mail_users as $type => $domains){
foreach($domains as $domain => $accounts){
$useDomainAndVirtual = false;
foreach($accounts as $account => $setting){
$pathAccount = $domain . '/' . $account . '/Maildir';
$path = $pathBase . '/' . $pathAccount;
switch($setting['status']){
// 使用中
case 'use':
if ( ! file_exists($path)) mkdir($path, 0777, true);
$uidgid = '5000:5000';
if ($type == 'real'){
shell_exec('chmod 1777 '. $path);
$uidgid = shell_exec('id -u ' . $account) . ':' . shell_exec('id -g ' . $account);
} else if ($type == 'virtual'){
shell_exec('chown 5000:5000 ' . $path);
shell_exec('chmod 700 ' . $path);
$useDomainAndVirtual = true;
}
$virtual_maps .= $account . '@' . $domain . ' ' . $pathAccount . '/' . "\n";
$dovecot_passwd .= $account . '@' . $domain . ':{plain}' . $setting['password'] . ':' . $uidgid . ':::/home/user_mails/' . $domain . '/' . $account . ':/sbin/nologin:' . "\n";
shell_exec('echo "' . $setting['password'] . '" | /usr/sbin/saslpasswd2 -p -u ' . $domain . ' -c ' . $account);
break;
// 中断
case 'pause':
// 特に何もしない
// shell_exec('/usr/sbin/saslpasswd2 -d -u ' . $domain . ' ' . $account);
break;
// 削除
case 'delete':
// $path を rm -rf ですが、削除する場合は手動で行ってください
break;
}
}
if ($useDomainAndVirtual) {
$virtual_domains .= $domain . "\n";
}
}
}
file_put_contents('/etc/postfix/virtual_domains', $virtual_domains);
file_put_contents('/etc/postfix/virtual_maps', $virtual_maps);
file_put_contents('/etc/dovecot/mail-password', $dovecot_passwd);
メールアカウント設定の更新スクリプト
vi /root/mail/update_mailbox.sh
#!/bin/sh
/usr/bin/php /root/mail/update_mailbox.php
chmod 0600 /etc/postfix/virtual_maps
chown dovecot:dovecot /etc/dovecot/mail-password
chmod 0600 /etc/dovecot/mail-password
chgrp postfix /etc/sasl2/sasldb2
chmod 640 /etc/sasl2/sasldb2
/usr/sbin/postmap /etc/postfix/transport
/usr/sbin/postmap /etc/postfix/virtual
/usr/sbin/postmap /etc/postfix/virtual_maps
systemctl reload postfix
systemctl restart dovecot
systemctl reload postfix
systemctl restart dovecot
chmod 0700 /root/mail
chmod 0600 /root/mail/*
chmod 0700 /root/mail/update_mailbox.sh
更新の流れ
config_mail_users.php を編集して update_mailbox.sh を実行
vi /root/mail/config_mail_users.php
/root/mail/update_mailbox.sh
メールソフトの設定も見直し
次のように、POP3S、SMTPはTLSを使うように設定変更が必要になります。