Ubuntuでメールサーバー(Postfix+Dovecot)の構築と設定

==GitLab==構築時にPostfixをインストールすることになり、メールサーバーであることは知ってはいたが使ったことなかったので、これを機に構築したときの備忘録を残しておく。

どうも旧来からある==sendmail==は、設定の難しさやセキュリティ・速度の問題で、このPostfixへ徐々に移行しているとのこと。ただし、メール不正中継防止として、後述するDovecotと組み合わせて利用するのが一般的らしい。

Postfixインストール

> sudo apt install postfix

 いきなりインストールでつまずいたのは、/etc/init.dに起動スクリプトを作成した後にチェックが走ってエラーになってしまった。

 どうも手動で追加した別のスクリプトに、お約束のヘッダが追加されてなかったため、チェックでエラーになってインストーラが異常終了していた。 以下のテンプレートを各スクリプトに追加したところ、完了できた。

#!/bin/bash
### BEGIN INIT INFO
# Provides :          script name
# Required-Start :    xxx.sh start
# Required-Stop :     xxx.sh stop
# Default-Start :     2 3 4 5
# Default-Stop  :     0 1 6
# Short-Description : Some info
# Description :       Some more info
### END INIT INFO

Postfix 基本設定

インストールが完了すると、コンフィグレーション設定に移行するが、 なにもせずに終了して手動で設定ファイルを編集していく。

> sudo vi /etc/postfix/main.cf
:

メールサーバーのホスト名(完全修飾名)を設定する

myhostname = hoge.com

ドメイン名の設定

mydomain = hoge.com

myhostnameのドメイン部分

myorigin = $mydomain

メール受信の設定

inet_interfaces = all

IPアドレスのプロトコル

IPV4のみ

inet_protocols = ipv4

ローカルに配送するドメインのメールかどうかの判断

ここに記載していないドメインのメールアドレスはDNSで引き当ててほかへ転送される

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

全てのメールを配送する信頼されたネットーワークを指定する

ローカルマシンからのメールのみ転送

mynetworks = 127.0.0.0/8, 192.168.0.0/24

ユーザのメールボックスの場所を設定する

"/home/mail"を指定すると、"/home/mail/<user>"がメールボックスとなる

"/"で終わる値を設定すると Maildir形式のメールボックスになる

home_mailboxを有効にする場合はこちらをコメントアウトする

mail_spool_directory = /home/mail

各ユーザディレクトリ以下にメールボックスを作成する場合は以下で指定する

"/"で終わる値を設定すると Maildir形式のメールボックスになる

mail_spool_directoryを有効にする場合、こちらをコメントアウトする

home_mailbox = Maildir/

メールボックスの上限

mailbox_size_limit = 51200000

メール1件あたりの上限サイズ(もちろんメールボックスの上限を超えてはいけない)

message_size_limit = 10240000

外部からきたメールの中で転送するドメイン名を指定する

外部からのメールを受け取らない

relaydomain =

拡張メールアドレスの区切り文字

ここで指定した区切り文字を付与するとすべて同じメールボックスに届く

hoge@mail.domain.comだと、hoge+abc@mail.domain.comやhoge+123@mail.domain.com

が同じメールボックスに届く

recipient_delimiter = +

aliasで別ユーザ宛のメールを受信するときの参照先

alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

構築方法や設定方法、操作方法が書かれたPostfix READMEファイルの場所

readme_directory = no

ローカルメールで、".domain" のないアドレスに対して、

".$mydomain" を自動で付与する

append_dot_mydomain = yes
append_at_myorigin = yes

指定時間以内に配送できない場合は送信者に通知が行く

指定しないと通知しない

delay_warning_time = 4h

新着メール通知を送信する

biff = no

smtp_helo_name = $myhostname

SMTP グリーティングバナー

先頭が$myhostnameは必須のルール

smtpd_banner = $myhostname ESMTP unknown

Postfixで、SMTPで認証を行い任意のIPアドレスからメール中継を可能にする設定

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination

main.cfの内容をチェックする。以下を実行すると、 現在の設定の内容すべてがダンプされて、末行に問題箇所があれば出力される。

> postconf -d
> postconf -n

エイリアスを更新

>  sudo newaliases

Postfixを再起動する

> sudo /etc/init.d/postfix restart
[ ok ] Restarting postfix (via systemctl): postfix.service.

メールコマンドを使えるように==mailutils==をインストールする

> sudo apt install mailutils

気をつける点として、main.cfで、home_mailboxを有効にした場合、 mailコマンドでメールボックスを参照するときは-fでメールボックス を指定して実行する。これを指定しないと、デフォルトパスの /var/mail/<usrname>を確認して、=="no mail for xxx=="と なってしまうので注意する。これでかなり悩んだ。

とりあえず、自分宛にメールを送信して、正しく受信できることをまず確認する。

> mail <user-name>@hoge.com
CC:
Subject: test mail
test !
(Ctrl+D)

>mail -f ~/Maildir

"/home/<user-name>/Maildir": 1 message 1 new
>N 1 Hoge 13/429 test mail
? 1
Return-Path: <hoge@hoge>
X-Original-To: hoge@hoge.com
Delivered-To: hoge@hoge.com
Received: by usagi1975.com (Postfix, from userid 1000)
id A08CF381CC6; Tue, 7 Feb 2017 08:29:22 +0900 (JST)
To: <hoge@hoge.com>
Subject: test mail
X-Mailer: mail (GNU Mailutils 2.99.99)
Message-Id: <20170206232922.A08CF381CC6@hoge.com>
Date: Tue, 7 Feb 2017 08:29:22 +0900 (JST)
From: hoge@hoge (Hoge)

test !
?

Dovecotの設定

POP3またはIMAPによるメール受信ができるようにするために Dovecotをインストールする。

> sudo apt install dovecot-core dovecot-pop3d dovecot-imapd

設定ファイルを編集する

> sudo vi /etc/dovecot/dovecot.conf
# IPv4のみListenする
listen = *
> sudo vi /etc/dovecot/conf.d/10-auth.conf
# 平文テキストでも認証可能とする
disable_plaintext_auth = yes
> sudo vi /etc/dovecot/conf.d/10-mail.conf
# メールボックスの保存先を指定する(Postfixのhome_mailboxと同じ場所)
mail_location = maildir:~/mailbox
> sudo vi /etc/dovecot/conf.d/10-master.conf 
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
  mode = 0666
  user = postfix
  group = postfix
}

main.cfも併せて修正する。


# 以下SMTP-Auth用(Dovecotを使う設定)
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
smtpd_recipient_restrictions = permit_mynetworks,permit_auth_destination,permit_sasl_authenticated,reject

Postfix SMTP Submission SMTP_AUTH有効化

smtpポート(25番)はOP25B対策により、事実上メール送信で使用 できなくなっている。代替案として、メールの送信を行うための送信専用 のポート(587番)をサブミッションポート(Submission)と呼ばれる。 このポートとSMTP認証(SMTP Auth)を利用する設定を行う。

master.cfをオープンして、以下の行のコメントを解除する。

>sudo vi /etc/postfix/master.cf

submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject

一旦Postfixを再起動して、ポートが利用可能になっているか確認する。

> sudo netstat -anp | grep "master" | grep "0.0.0.0"
tcp        0      0 0.0.0.0:587             0.0.0.0:*               LISTEN      10514/master    
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      10514/master

telnetコマンドで、ポート587に接続し、ehlo localhostと入力。 250-AUTH PLAIN LOGINという項目があればOK. (quitで終了する)

>telnet localhost 587
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.example.com ESMTP
ehlo localhost
250-mail.example.com
:
250-AUTH PLAIN LOGIN
:
quit

つづいて、==SMTP認証==の設定を行う。 証明書やサーバ用の秘密鍵は既存のものを利用する。 一応有効期限は、2027年までになっていた。

> sudo vi /etc/postfix/main.cf

Postfix SMTPサーバRSA証明書関連の設定

smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

master.cfファイルに対しても以下をコメント解除する。

> /etc/postfix/master.cf
-o smtpd_tls_security_level=encrypt

smtps inet n - y - - smtpd
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject

Postfixを再起動して、Listenしているポートを確認する

> sudo netstat -anp | grep "master" | grep "0.0.0.0"
tcp        0      0 0.0.0.0:587             0.0.0.0:*               LISTEN      10823/master    
tcp        0      0 0.0.0.0:465             0.0.0.0:*               LISTEN      10823/master    
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      10823/master

再度587ポートに接続し、250-STARTTLSになっていればOK

telnet localhost 587
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.example.com ESMTP
ehlo localhost
250-mail.example.com
:
250-STARTTLS
:

トラブル備忘録

  • 外部からメールが受信されない

    smtp_helo_nameを設定していなかった。

    > /etc/postfix/main.cf
    smtp_helo_name = $myhostname
    
  • mailコマンドで自身宛にメールしても届かない

    home_mailboxでMaildir形式を設定していたため、 mailコマンドのデフォルトで参照するメールボックスの場所 と異なっていた。mailコマンド起動時に-fオプションで メールボックスの場所を指示するようにした。

    > /etc/postfix/main.cf
    

    /home/(username)/Maildirにメールボックスを作成

    home_mailbox = Maildir/

    > mail
    no mail for xxxx
    > mail -f ~/Maildir

  • 外部へメール送信できない

    いわゆるOP25B(メール送信規制)で送信できなかった。 デフォルトでは25番ポートを使ってメール送信されるわけだが、 メジャーなメールサーバーはすでにこのポートは塞いで別のポート でしかメールを受け付けていない。

    以下は==/var/log/mail.err==の抜粋。

    Feb  7 20:14:52 saba postfix/smtp[7949]: 8GTY7399CFB: to=<xxx@xxx.co.jp>, relay=none, delay=3401, delays=3340/0.01/61/0, dsn=4.4.1, status=deferred (connect to xxxx.xxx.com[203.198.122.09]:25: Connection timed out)
    

    対応としては、Gmailアカウントを利用して、GmailのSMTPサーバを 中継先として使用するようにPostfixの設定を変更する。

    > sudo vi /etc/postfix/main.cf
    

    外部へのメールを送るメールサーバーを指定する

    OP25B対応(Gmail Smtp)

    relayhost = [smtp.gmail.com]:587
    smtp_sasl_auth_enable = yes
    smtp_sasl_mechanism_filter = plain
    smtp_sasl_password_maps = hash:/etc/postfix/gmail_passwd
    smtp_sasl_security_options = noanonymous
    smtp_sasl_tls_security_options = noanonymous
    smtp_use_tls = yes

    上記で指定したファイルに以下のフォーマットでGmailのパスワードを 記録する。(userとpasswordをアカウントのものに置き換える)

    >sudo vi /etc/postfix/gmail_passwd
    

    [smtp.gmail.com]:587 user@gmail.com:password

    > sudo chmod 600 gmail_passwd

    ちなみにほかのSMTPサーバーとリレーする場合の書式は以下 が一般的。また先ほど作成したファイルに追記しておくことも可能。

    [smtp.hoge.com]:587 user:password
    

    以下のコマンドでdbファイルを作成する。postfixを再起動して 送信できるか確認する。

    > sudo postmap hash:/etc/postfix/gmail_passwd
    

    注意点として、gmailアカウントでgmailのメールボックスを確認し、 ロックされてないか確認する。

  • メールログを見ると、"Diagnostic-Code: smtp; 554 5.4.0 Error: too many hops"と表示されて外部からのメールが受信できない。

    外部からメールが送信されたときに発生する。 SMTPサーバーは自分宛じゃないと判断されると、 メールが==たらい回し==にされて次のサーバーに転送される。 ここで解決できなくて、永久ループを避けるために"たらい回し"の回数 を制限しており、この上限に達するとこのエラーが送信元に通達される。

    ログをみていると、大量にログが流れたあとにエラーになるのがわかる。 確認すべきポイントとしては、誰宛にメールが来ているのかを確認し、 その宛先アドレスのドメイン名(@の後ろ)が、postfixの==main.cf== 設定ファイルの==mydestination==に含まれていなかったのが問題だった。

    # 送信されていたメールアドレス
    # hoge@server.hoge.com
    # 誤:mydestination = server, hoge.com
    mydestination = server, hoge.com, server.hoge.com
    
  • OP25B問題の回避策として、gmailのsmtpサーバー経由で送信したところ、 Outlookで受信すると、==「XXXの代理で送信」==と表示されてしまう。

    ネットでこの問題を検索すると、「アドレスを追加して、gmailの設定で fromを指定できる」ような記述がたくさんヒットしたが、 この情報は古いと思われる。

    確かにアドレスは追加できて、送信元の自前のsmtpサーバーの FQDNとユーザIDパスワードを指定すれば、転送してくれる。 が、依然として==「XXXの代理で送信」は解消しなかった。==

    どうも、gmailの仕様で、メールヘッダに代理で送信した情報が送信した メールに追記されてしまうみたいで回避できないんじゃないか と思っている。(Fromは自前のサーバー、SenderにGmailサーバーが 表示されている)

    回避した方法としては、smtp.gmail.comの利用はあきらめて、加入している プロバイダのsmtpサーバーをrelayhostで指定することで解決とした。