AWS
EC2
postfix
postfixadmin

EC2にメールサーバを構築(複数ドメイン)

More than 1 year has passed since last update.

要件

  • 複数ドメインのメールが受信できる。
  • メールアドレス毎にUNIX Userは作成しない。
  • SMTP,POP3,IMAPで外部ネットワークのMUAから送受信可能。
  • メールの容量制限をユーザ毎に設定可能にする。
  • MUAでの送信、受信は認証必須。認証はメールアドレス+パスワード
  • STARTTLSで送受信は暗号化する
  • MUAでの送信と受信のパスワードは同じパスワードを使用できる。

概要

  • MTAはsendmailからpostfixに変更
  • メール配送はMaildir方式にする。
  • postfixにバーチャルドメインを設定して、各ドメインからの受信を可能にする。
  • ドメインとメールアドレスの管理用UIにpostfix Adminを採用
  • メールアドレス、パスワードの管理はMySQL
  • POP3,IMAPでの受信はdovecotを使用する。
  • OB25対策をして、通常のプロバイダ接続でも送信可能にする。

構築準備

環境

  • メールサーバにする予定のインスタンスにElastic IPを割り当てておく。
  • メールサーバのドメインを決めておく。
  • メールサーバ上で、webサーバとphp5以上が動くようにしておく
  • メールサーバからMySQLサーバにアクセス可能にする

メールサーバのドメイン:mail.example.jp
PostfixAdminのURL: http://mail.example.jp
データベースサーバ: localhost

として作成したとする。構築に使用したバージョンは、

  • postfix 2.6.6
  • dovecot 2.0.9
  • postfixAdmin 2.3.7
  • MySQL 5.6
  • Apache 2.4
  • PHP 5.5

メール送信制限の解除とDNS逆引き申請

標準ではEC2インスタンスからの1日あたりのメール送信数は制限されているのと、
Elastic IPで割り当てたIPアドレスを逆引きした場合、アマゾンのドメインとなるためスパム判定される事がある。
制限解除兼、逆引き設定の依頼を行うフォームがあるのでそこから申請する。

Request to Remove Email Sending Limitations
https://portal.aws.amazon.com/gp/aws/html-forms-controller/contactus/ec2-email-limit-rdns-request

申請手順については、Amazon日本公式のドキュメント
http://www.slideshare.net/AmazonWebServicesJapan/aws-42885668
で確認できる

サーバの使用用途は、自社用メールサーバ等、素直に書けばOK。ただし英語で記載しないと無視される。

Elastic IP Address : 123.123.123.123 (使用する Elastic IP)
Reverse DNS Record for EIP 1 : mail.example.jp (メールサーバのドメイン)

を送信。数営業後に返答が決ます。

sendmailからpostfixへの差し変え

postifxインストール

# yum install postfix

MTAの切り変え

# alternatives --config mta
現在インストールされているMTA一覧が出るので、postfixを選択

sendmailの停止と、postfixの起動

# service sendmail stop
# chkconfig sendmail off
# service postfix start
# chkconfig postfix on

この時点では、外部からのメールはすべて拒否される状態。
動作が確認できるまで拒否設定のままにしておく。
sendmailは削除してもOK

dovecotのインストール

postfixAdminをインストール前に必要。pop3,imapのポートは閉じたままにしておく。
メールアドレス、パスワード管理にMySQLを使用するので、mysql backendも導入。
# yum install dovecot dovecot-mysql

postfix Admin のインストールと設定

postfixAdminは、ドメイン、メールアドレス、パスワード、メールボックス名をDBで管理するためのWebアプリ。
MTAにはpostfix、pop3,imapサーバはdovecotの利用が想定されている。postfixAdmin自体は、postfixとdovecotの設定は行わないので、自分で設定する。

まず、postfixAdminを使えるようにして、ドメインとメールアドレスをデータベースに登録できる状態にする。

postfix Adminのダウンロード

パッケージはないので公式よりダウンロード。
postfixadmin-2.3.7を使用した。

ダウンロードしたpostfixadminをwebサーバから見える所に展開する。設定が完了するまでWeb側にアクセス制限をつけておく。展開したファイルにあるINSTALL.txtを参照して設定

データベースの作成

mysqlに接続し、postfixのデータベースとユーザを作成。パスワードはhogehoge
CREATE DATABASE postfix CHARSET utf8
CREATE USER 'postfix'@'%' IDENTIFIED BY 'hogehoge'
GRANT ALL PRIVILEGES ON postfix.* TO postfix@%
FLUSH PRIVILEGES

postfixadminの設定ファイル変更

config.local.phpを新規作成する。
config.local.phpは、config.inc.phpの設定内容を上書きする仕組みになっているので、
デフォルトから変更する値のみをconfic.local.phpへ記載する。

config.inc.phpをコピーして使用する場合、下部にあるconfig.local.phpの読み込み部分を消さないと無限ループする。

config.local.php
// 設定完了フラグ
$CONF['configured'] = true;
// postfixAdminのURL
$CONF['postfix_admin_url'] = 'http://mail.example.jp';
//日本語表示にする
$CONF['default_language'] = 'ja';
// データベース接続情報
$CONF['database_type'] = 'mysqli';       // mysqlからmysqliに変更
$CONF['database_host'] = 'localhost';    // mysqlのホスト名
$CONF['database_user'] = 'postfix';      // postfixAdminで使用するデータベースのユーザ
$CONF['database_password'] = 'hogehoge'; // パスワード
$CONF['database_name'] = 'postfix';      // データベース名

// 管理者メールアドレス
$CONF['admin_email'] = 'postmaster@example.jp';

// postfixが稼動しているホストとポート
// メールアドレス作成時にwelcomeメールを送信するのに使う。
// welcomeメールを送っておかないとmailboxが作成されないため、pop3でエラーになる。
$CONF['smtp_server'] = 'localhost';
$CONF['smtp_port'] = '25';

//標準の管理者メールアドレス
$CONF['default_aliases'] = array (
    'abuse' => 'abuse@example.jp',
    'hostmaster' => 'hostmaster@example.jp',
    'postmaster' => 'postmaster@example.jp',
    'webmaster' => 'webmaster@example.jp'
);

// username@domain.tldのメールの配送を、domain.tld/username にする。
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';

// 自動応答ドメイン。DNSに設定しなくてもよい
$CONF['vacation_domain'] = 'autoreply.example.jp';

//mainメニューへのリンク
$CONF['user_footer_link'] = "http://mail.example.jp/main.php";

// ページ下部にトップへ戻るリンク設定
$CONF['footer_text'] = 'Return to mail.example.jp';
$CONF['footer_link'] = 'http://mail.example.jp';

システム管理者の登録

http://mail.example.jp/setup.php にブラウザでアクセスする。初回アクセス時に管理用テーブルが作成される。
動作に必要なモジュールが足りない場合画面に表示されるので、インストール後リロードしてチェック。
エラーが表示されなくなったら、画面に従い管理者を登録。セットアップパスワードが表示されるので、
config.local.phpに以下の行を追加する。

config.local.php
$CONF['setup_password'] = '画面に表示されたセットアップパスワード'

http://mail.example.jp にアクセスし、ログインできる事を確認したらsetup.phpは削除するかパーミッションを落としてアクセス不可にしておく。

ドメインとメールアドレスの登録

http://mail.example.jp に管理者でログインし、画面に従ってテスト用のドメインとメールアドレスを作成する。作成したドメインのMXレコードを設定し、メールサーバへメールが送信されるようにしておく。

postfixの設定

postfixAdminの設定に合わせる。
バーチャルホスト宛のメールは /var/spool/virtual/ 以下に配送し、user@domain.ltdのメール配送のディレクトリは、/var/spool/virtual/domain.ltd/user/ にする

MailDir形式への変更

/etc/postfix/main.cf
home_mailbox = Maildir/ 

メールの配送方法をmbox形式からMailDir形式に変更する。
ついでに、/etc/skel へMaildirを作成し、新規ユーザでも自動作成されるようにする。

バーチャルドメインの設定

Postfix バーチャルドメインホスティング Howtoを参考に作成。

バーチャルドメイン用のユーザとメール用ディレクトリの作成

バーチャルドメインで受信したメールの所有者と保存先のディレクトリを作成。
ユーザはuid:10000で作成しておく。

# adduser -u 10000 vmailuser
# mkdir /var/spool/virtual
# chmown 10000.10000 /var/spool/virtual

DBへのアクセス用クエリ設定

postfixadminのDOCUMENTS/POSTFIX_CONF.txtを参考に、postfixAdminで登録したメールアドレス関連の情報を、postfixからMySQLに接続して取得するクエリを作成する。 /etc/postfix/sql ディレクトリを作成し、以下のファイルを新規作成

/etc/postfix/sql/mysql_virtual_domains_maps.cf
user = postfix
password = hogehoge
hosts = localhost
dbname = postfix
query          = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
#query          = SELECT domain FROM domain WHERE domain='%s'
#optional query to use when relaying for backup MX
#query           = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
#expansion_limit = 100
/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
# handles catch-all settings of target-domain
user = postfix
password = hogehoge
hosts = localhost
dbname = postfix
query  = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf
user = postfix
password = hogehoge
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf
user = postfix
password = hogehoge
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
/etc/postfix/sql/mysql_virtual_alias_maps.cf
user = postfix
password = hogehoge
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
#expansion_limit = 100
/etc/postfix/sql/mysql_virtual_mailbox_maps.cf
user = postfix
password = hogehoge
hosts = localhost
dbname = postfix
query           = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
#expansion_limit = 100

メール容量制限取得。容量制限を行わないなら不要

/etc/postfix/sql/mysql_virtual_mailbox_limit_maps.cf
user = postfix
password = hogehoge
hosts = localhost
dbname = postfix
query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'

バーチャルドメイン用メールボックスの設定

以下の設定を追記し、バーチャルドメインのメールを配送できるようにする

/etc/postfix/main.cf
# Virtual mailbox 基本設定
virtual_mailbox_base = /var/spool/virtual
virtual_minimum_uid = 100
virtual_uid_maps = static:10000
virtual_gid_maps = static:10000

# メールアドレス関連情報の取得
virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
virtual_alias_maps =
   proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf,
   proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf,
   proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
virtual_mailbox_maps =
   proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf,
   proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf

# quota(容量制限)サポート設定。容量制限をしないなら不要
# 容量制限を越えた場合、送信元にエラーメールを返信する。
virtual_create_maildirsize = yes
virtual_mailbox_extended = yes
virtual_mailbox_limit_maps = mysql:/etc/postfix/sql/mysql_virtual_mailbox_limit_maps.cf
virtual_mailbox_limit_override = yes
virtual_maildir_limit_message = Sorry, the user's maildir has overdrawn his diskspace quota, please try again later.
virtual_overquota_bounce = yes 

この時点でpostfixを再起動し、mailコマンドでテスト用に作成したドメイン宛てにメールを送信してチェック。user@domain.ltdに送信したメールが、/var/spool/virtual/domain.ltd/user/new 以下に配信されていればOK

dovecotの設定

postfixAdminで登録した情報を取得するためのクエリを作成。以下の名前で新規作成する。
connect = の部分は改行するとダメ。

/etc/dovecot/dovecot-sql.conf.ext
#
# for postfixadmin
#
connect = host=localhost dbname=postfix user=postfix password=hogehoge
driver = mysql

# Default password scheme.
# depends on your $CONF['encrypt'] setting:
# md5crypt  -> MD5-CRYPT
# md5       -> PLAIN-MD5
# cleartext -> PLAIN
default_pass_scheme = MD5-CRYPT

password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'
user_query = SELECT CONCAT('/var/spool/virtual/', maildir) AS mail, 10000 AS uid, 10000 AS gid, CONCAT('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active='1'

認証

メールアドレス+パスワードでPOP3,IMAP認証可能にし、PAMでのユーザ認証は無効にする。
/etc/dovecot/conf.d/10-auth.confを変更する。

/etc/dovecot/conf.d/10-auth.conf
...
# STARTTLSで暗号化するので、plaintext認証を有効にする
disable_plaintext_auth = no
...

#コメントアウト
#!include auth-system.conf.ext

#コメントアウトを外す
!include auth-sql.conf.ext
...

/etc/dovecot/conf.d/auth-sql.conf.extを変更する

/etc/dovecot/conf.d/auth-sql.conf.ext
# Authentication for SQL users. Included from auth.conf.
#
# <doc/wiki/AuthDatabase.SQL.txt>

passdb {
  driver = sql

  # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
  # 先程作成したファイルを指定
  args = /etc/dovecot/dovecot-sql.conf.ext
}

# "prefetch" user database means that the passdb already provided the
# needed information and there's no need to do a separate userdb lookup.
# <doc/wiki/UserDatabase.Prefetch.txt>
#userdb {
#  driver = prefetch
#}

userdb {
  driver = sql
  # 先程作成したファイルを指定
  args = /etc/dovecot/dovecot-sql.conf.ext
}

# If you don't have any user-specific settings, you can avoid the user_query
# by using userdb static instead of userdb sql, for example:
# <doc/wiki/UserDatabase.Static.txt>
#userdb {
  #driver = static
  #args = uid=vmail gid=vmail home=/var/vmail/%u
#}

SSL/TLSを使用可能にする

/etc/dovecot/conf.d/10-ssl.conf
 # SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
 ssl = yes

ローカルメールの設定

postfixでのメール配送をMaidir形式にしたので、dovecotのデフォルトもMaidir形式にする。
mail_locationはローカルユーザ向けの設定なので、各ユーザのホームディレクトリを指定。

/etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:~/Maildir

ここまで設定すれば、pop3,imapは使用できるようになるが、
MUAがThunderBirdの場合、送信サーバの認証ができないとメールアカウント登録でエラーとなる。

Postfix用のSMTP認証用設定

PostfixでDovecotの認証を使用するための設定を記載。
設定後、dovecotを再起動し /var/spool/postfix/private/auth が作成されている事を確認する。

dovecot側の設定

/etc/dovecot/conf.d/10-master.conf
   # Postfix smtp-auth
   unix_listener /var/spool/postfix/private/auth {
      mode = 0666
      user = postfix
      group = postfix
   }

postfix側の設定

/etc/postfix/main.cf
myhostname = mail.example.jp
myorigin = $myhostname
// 外部からのメールを受信可能にする
inet_interfaces = all

#
# SASL(SMTP認証) 有効化
#
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination
# 認証にdovecotを使用
smtpd_sasl_type = dovecot
# 認証用ソケット。/var/spool/postfix からの相対パス
smtpd_sasl_path = private/auth
# 一部MUAもサポート
broken_sasl_auth_clients = yes

#
# TLS(STARTTLS) 有効化
#
smtpd_use_tls = yes
smtld_tls_loglevel = 1
# dovecotの証明書を流用.正式な証明書があるならそちらを指定する。
smtpd_tls_cert_file = /etc/pki/dovecot/certs/dovecot.pem
smtpd_tls_key_file = /etc/pki/dovecot/private/dovecot.pem
smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache
smtpd_tls_session_cache_timeout = 3600s

通常、メールを受信するドメインは、$mydestinationに指定するが、
バーチャルドメインで使用するドメインは、$mydestination に追加してはいけない

OB25対策

プロバイダによってはOB25により、25番ポートでのメール送信ができないのでサブミッションポートを使用可能にする。

/etc/postfix/master.cf
submission inet n       -       n       -       -       smtpd
#  -o smtpd_tls_security_level=encrypt
   -o smtpd_sasl_auth_enable=yes
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject

SASL認証を有効にし、サブミッションポートを利用しての送信は認証成功以外は送信拒否とする。