Ref.

メールの仕組み

  • https://blog.denet.co.jp/ec2-postfix-dovecot-mail-server-setup/
    • メールサーバ構築手順をとてもわかり易く解説した記事
  • https://blog.denet.co.jp/mailserverwords/
    • メールシステムの用語をとてもわかり易く解説した記事

Postfix

  • https://www.postfix-jp.info/trans-2.2/jhtml/BASIC_CONFIGURATION_README.html
  • https://zenn.dev/uchidaryo/books/ubuntu-2204-server-book/viewer/postfix-dovecot
  • https://www.rem-system.com/mail-postfix01/#3_postfix

Postfixを導入

インストール

$ sudo apt install postfix

tmux

tmux

バージョンを確認

$ postconf | grep mail_version
mail_version = 3.6.4
milter_macro_v = $mail_name $mail_version

基本設定

設定ファイル /etc/postfix/main.cf

※ 以下の出力は本文の mail_version = 3.6.4( Ubuntu 22.04 )とは別の環境のものです。 compatibility_level = 2smtpd_use_tls=yes は Ubuntu 20.04 以前( Postfix 3.4 系 )の内容と思われます。22.04 では compatibility_level = 3.6 になり、TLS は smtpd_tls_security_level で指定します( smtpd_use_tls は Postfix 2.3 以降 非推奨 )。22.04 の内容は後述の「作業例」を参照してください。 ※ smtp_host_lookup = native は Debian / Ubuntu のデフォルトではなく、手動で追加したものです。 ※ この出力の myhostname はパブリック DNS 名( ec2-….compute.amazonaws.com )ですが、後述の「主要なパラメータ」に記載の通り EC2 の既定はプライベート DNS 名( ip-….compute.internal )です。この環境では既定から変更されていたものと見られます。 ※ myhostname の値は実在の IP を含んでいたため、ドキュメント用アドレス( RFC 5737 TEST-NET-3 )に置き換えています。

デフォルトの main.cf( Ubuntu 20.04 以前 ) ``` # appending .domain is the MUA's job. append_dot_mydomain = no # Uncomment the next line to generate "delayed mail" warnings #delay_warning_time = 4h readme_directory = no # See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on # fresh installs. compatibility_level = 2 # TLS parameters 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 # See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for # information on enabling SSL in the smtp client. smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination myhostname = ec2-203-0-113-10.ap-northeast-1.compute.amazonaws.com alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases myorigin = $myhostname mydestination = localhost relayhost = mynetworks_style = host # mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = localhost inet_protocols = all smtp_host_lookup = native ```

主要なパラメータ

メールサーバが mail.example.com の場合を例に記載します。 あくまで参考までの設定例であり環境に応じて変わります。

myhostname

  • mail.example.com

まずはmyhostnameという設定を探しましょう。 ドキュメントにはPostfixをインストールしたマシンの完全修飾ドメイン名(いわゆるFQDN)を指定する、とあります。

ref. https://tech-blog.rakus.co.jp/entry/20220815/postfix

  • hostname コマンドの値ではなくFQDNを設定する
  • EC2 ではapt install した際に変更しなければデフォルトでプライベートな FQDN を表すホスト名のタイププライベート IP DNS名(IPv4のみ)と同じ)の値になる

ref.

mydomain

  • example.com

myorigin

  • example.com

myorigin パラメータにはローカルで 投函されたメールがどのドメインから来るように見えるかを指定します。 デフォルトではローカルマシン名、すなわちマシン名がデフォルトになっている $myhostname を使います。非常に小さな サイトを運営しているのでなければ、マシン名の親ドメインがデフォルトに なっている $mydomain に変更したく なるでしょう。

ref. https://www.postfix-jp.info/trans-2.2/jhtml/BASIC_CONFIGURATION_README.html

mydestination

mydestination パラメータには、 このマシンが他のマシンに転送せずにローカルに配送するドメインを指定します。 デフォルトではマシン自身に対するメールを受け取ります。 ホスティングしているドメイン 用に Postfix を設定する方法は VIRTUAL_README ファイルを参照してください。

ref. https://www.postfix-jp.info/trans-2.2/jhtml/BASIC_CONFIGURATION_README.html

mynetworks / mynetworks_style

Postfix が「信頼するクライアント(リレーを許可する送信元)」を決めるパラメータです。 ドメイン名ではなく ネットワークアドレス( CIDR ) を指定します。

mynetworks … 信頼するネットワークを明示する

mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128

mynetworks_stylemynetworks を明示しない場合に既定値をどう決めるか

信頼する範囲
host 自ホストの IP アドレスのみ
subnet 自ホストが属するサブネット全体
class 自ホストが属するクラス A/B/C ネットワーク全体(広すぎるため非推奨)
  • mynetworks を明示した場合 mynetworks_style は無視される
  • 既定値は postconf -d mynetworks_style で確認する
  • 範囲を広げるとオープンリレーになり得るため、設定後は必ず確認する
$ postconf -n | grep -E 'mynetworks|relay|inet_interfaces'

ref. https://www.postfix-jp.info/trans-2.2/jhtml/BASIC_CONFIGURATION_README.html

home_mailbox

新規に追加しました。

  • Maildir/

末尾の / が Maildir 形式を意味します。設定しない場合は mbox 形式( /var/mail/<ユーザー名> )に配送されます。

home_mailbox を設定していれば Postfix の local(8) が配送時に Maildir を自動生成するため、以下の /etc/skel の手順は必須ではありません。新規ユーザーのホームに最初から Maildir を用意したい場合に実施します。

$ sudo mkdir -p /etc/skel/Maildir/{new,cur,tmp}
$ sudo chmod -R 700 /etc/skel/Maildir/

設定値を確認

デフォルトとの差分表示。

$ sudo postconf -n

設定ファイルチェック

$ sudo postfix check

設定を反映

main.cf を編集しただけでは反映されません。

$ sudo systemctl reload postfix

inet_interfaces の変更と master.cf の変更は reload では反映されないため restart が必要です。

$ sudo systemctl restart postfix

送信確認

sendmailコマンド

  • 送信元:info@example.com
  • 送信先:info@example.org
$ sendmail -t <<'EOL'
From: info@example.com
To: info@example.org
Subject: test

test mail
EOL

※ RFC 5322 ではヘッダと本文を 空行 で区切る必要があります。空行がないと本文がヘッダとして解釈され、本文が消えることがあります。

mailコマンド

  • 送信元:info@example.com
  • 送信先:info@example.org
$ sudo apt install mailutils
$ echo "test mail" | sudo mail -s "test subject" -r "info@example.com" info@example.org

作業例

※ https://blog.denet.co.jp/ec2-postfix-dovecot-mail-server-setup/ がとてもわかり易いので参考に作業しました。

インストール

$ sudo apt install -y postfix
$ postconf | grep mail_version
mail_version = 3.6.4
milter_macro_v = $mail_name $mail_version
sudo systemctl status postfix.service
● postfix.service - Postfix Mail Transport Agent
     Loaded: loaded (/lib/systemd/system/postfix.service; enabled; vendor preset: enabled)
     Active: active (exited) since Mon 2023-09-11 15:33:35 JST; 2min 35s ago
       Docs: man:postfix(1)
    Process: 3398 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
   Main PID: 3398 (code=exited, status=0/SUCCESS)
        CPU: 1ms

Sep 11 15:33:35 xxxxxx systemd[1]: Starting Postfix Mail Transport Agent...
Sep 11 15:33:35 xxxxxx systemd[1]: Finished Postfix Mail Transport Agent.

設定ファイルを編集

バックアップを作成します。

$ sudo cp /etc/postfix/main.cf{,.$(date "+%Y%m%d")}

設定ファイル: /etc/postfix/main.cf

# See /usr/share/postfix/main.cf.dist for a commented, more complete version


# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

myorigin=example.com
myhostname=example.com
mydomain=example.com

# smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
smtpd_banner = $myhostname ESMTP unknown
biff = no

# appending .domain is the MUA's job.
# append_dot_mydomain = no
append_dot_mydomain = yes

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 3.6 on
# fresh installs.
compatibility_level = 3.6



# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_security_level=may

smtp_tls_CApath=/etc/ssl/certs
smtp_tls_security_level=may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache


smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
# myhostname = ip-xxxxx.ap-northeast-1.compute.internal
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
# myorigin = /etc/mailname
mydestination = $myhostname, ip-10-0-0-100.ap-northeast-1.compute.internal, localhost.ap-northeast-1.compute.internal, $mydomain, localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

# 新規に追加(末尾の / が Maildir 形式を意味する)
home_mailbox = Maildir/

デフォルトから変更した箇所と、その注意点です。

  • home_mailbox = Maildir/ を新規に追加しています。設定しない場合は mbox 形式で /var/mail/<ユーザー名> に配送されるため、後述の Maildir/new にはメールが届きません
  • append_dot_mydomain = yes … Debian / Ubuntu のデフォルトは no です。yes にするとドメイン部のないアドレス( user )に .$mydomain が補完されるため、意図しない宛先へ送る事故のもとになります。設定ファイル中のコメントにもある通り本来は MUA の役割なので、理由がなければ no のままにしてください
  • myhostname = example.com … ここではドメイン名をそのまま指定していますが、「主要なパラメータ」に記載の通り myhostname は本来そのホストの FQDN( mail.example.com など )です。受信側では逆引き( PTR )との一致を確認されるため、実運用では PTR と一致する FQDN を設定してください
  • mydestination$mydomain を含めています … このサーバが example.com 宛のメールを全てローカル配送します。MX が別サービス( Google Workspace 等 )を向いている場合、そのドメイン宛のメールがサーバ内で止まり届かなくなります。この作業例のように同一サーバで受信する場合のみ含めてください

設定を反映します。

$ sudo postfix check
$ sudo systemctl reload postfix

ユーザーを追加

$ sudo mkdir -p /etc/skel/Maildir/{new,cur,tmp}
$ sudo chmod -R 700 /etc/skel/Maildir/
$ sudo adduser mail-example
  • ユーザー mail-example を追加
  • グループ mail-example を追加
  • ホームディレクトリを追加

※ Ubuntu(やDebian)は adduseruseradd は機能が異なります。
useradd はホームディレクトリの作成などをしません。 ※ Ubuntu(やDebian)はdeluseruserdel は機能が異なります。

$ userdel ユーザー名               # ユーザーを削除
$ userdel -r ユーザー名            # ユーザーのホームディレクトリも削除
$ deluser --remove-home ユーザー名  # ↑と同じ

sudo を有効化(メール用途では不要)

メールを受け取るだけのユーザーに sudo は不要です。 後述のパスワード認証と組み合わせると、インターネットに公開したサーバで管理者権限をパスワードのみで奪取できる状態になります。 検証などで管理作業をさせる必要がある場合に限り実行してください。

$ sudo gpasswd -a mail-example adm   # /var/log の閲覧
$ sudo gpasswd -a mail-example sudo  # sudo 権限

メール送信テスト

ubuntu でログイン

  • 送信元 ubuntu@example.com
  • 送信先 mail-example@example.com
echo "test mail" | sudo mail -s "test subject" -r "ubuntu@example.com" mail-example@example.com

/home/mail-example/Maildir/new にメールが届く。

sshd のパスワード認証を有効化(特定ユーザーのみ)

※ パスワード認証はブルートフォースの標的になります。本来は公開鍵認証を推奨します。有効化する場合も対象ユーザーを限定してください。

Ubuntu 22.04 の /etc/ssh/sshd_config は先頭で Include /etc/ssh/sshd_config.d/*.conf を読み込みます。 sshd_config は 最初に得られた値が優先 されるため、EC2 の Ubuntu では /etc/ssh/sshd_config.d/50-cloud-init.confPasswordAuthentication no が勝ち、/etc/ssh/sshd_config を編集しても反映されません。 そのため sshd_config.d 配下に設定ファイルを追加します。

$ sudo vim /etc/ssh/sshd_config.d/60-mail-example.conf
# 全体はパスワード認証を無効のまま維持する
# ( sshd の既定値は yes のため、no の記述を消すと全ユーザーで有効になる)
PasswordAuthentication no

# Match 以降は次の Match までブロック内の設定として扱われるため必ず末尾に置く
Match User mail-example
    PasswordAuthentication yes

構文をチェックしてから反映します。 現在の SSH セッションは接続したまま、別のターミナルからログインできることを確認してください。

$ sudo sshd -t
$ sudo systemctl reload ssh

実際に適用された値を確認します。

$ sudo sshd -T | grep passwordauthentication
passwordauthentication no
$ sudo sshd -T -C user=mail-example,host=localhost,addr=127.0.0.1 | grep passwordauthentication
passwordauthentication yes