はじめに

こんにちは!ミルディアでインフラエンジニア見習いをしている齊藤です!
最近、SMTPリレーの学習のため、Postfixを使用して社内サーバーからのメール送信をSES経由にする設定を行いました。
その際の作業内容を簡潔にまとめます。

なぜSESなのか

実践的な学習のため、実際の運用に近い環境で設定やトラブルシューティングを行いたく、SESを選択しました。

環境

  • AmazonLinux2023(t2.large)
  • Postfix v3.7.2

設定手順

SESの本番稼働

SESはAWSアカウントが初期状態でサンドボックスにあり、以下制限がかかった状態となっております。

  • E メールの送信先は、検証済み E メールアドレスおよびドメイン、または Amazon SES メールボックスシミュレーターに制限されます。
  • 最大で 24 時間あたり 200 メッセージを送信できます。
  • 最大で 1 秒あたり 1 メッセージを送信できます。
  • 送信承認については、ユーザーも代理送信者も、検証されていない E メールアドレスに E メールを送信することはできません。
  • アカウントレベルのサプレッションでは、サプレッションリスト管理に関連する一括アクションと SES API コールが無効になります。

(本稼働アクセスのリクエスト (Amazon SES サンドボックスからの移行) より)

制限の内容をご確認いただいた上で、必要に応じて、SESを本番稼働させてください。
今回は制限付きの運用で十分なことから、本番稼働はさせておりません。

方法については AWS公式のデベロッパーガイド をご参照ください。

ブラウザでコンソール上から行う方法と、コマンドラインツールでAWS CLI を使用して行う方法の2つが説明されています。
(デベロッパーガイド 本稼働アクセスのリクエスト (Amazon SES サンドボックスからの移行))

SESの認証情報準備

SMTPクレデンシャルを発行しましょう。
SMTP設定を開きます。

SMTP認証情報の作成をクリックします。

IAMユーザーの作成画面が開かれるので、メールの送信権限があるか確認して、ユーザーの作成をクリックします。

ステートメントの内容

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": "ses:SendRawEmail",
			"Resource": "*"
		}
	]
}

ユーザーの作成が完了すると、SMTPクレデンシャルの秘匿情報が表示されます。
次の Postfixの設定 で使用するので保存しておきましょう。
必要な情報は以下2つです。

  • SMTP ユーザー名
  • SMTP パスワード

Postfixの設定

postfixをインストールします。

$ sudo yum install postfix

バージョンを確認しておきましょう。

$ postconf | grep mail_version
mail_version = 3.7.2

Postfixを起動し、自動起動を有効化します。

$ sudo systemctl start postfix
$ sudo systemctl enable postfix

システムデフォルトのMTA(Mail Transfer Agent)がPostfixになっているか確認します。
なっていない場合は、ここで設定してください。

$ alternatives --config mta

There is 1 program that provides 'mta'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/sbin/sendmail.postfix

Postfixの設定を行います。
設定内容については、後述の「Tips ~main.cf 設定パラメータ詳細~」をご参照ください。

$ sudo vim /etc/postfix/main.cf

設定内容は以下のとおりです。

# メールサーバーの情報を記載(環境に合わせて適宜修正してください。)
myhostname = mail.example.com
mydomain = example.com
mydestination =

# SESを経由させる設定を記載
relayhost = [email-smtp.ap-northeast-1.amazonaws.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_use_tls = yes
smtp_tls_security_level = encrypt
smtp_tls_note_starttls_offer = yes
smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt

設定が反映されているか確認してください。(以下記載は該当箇所のみ抜粋したもの)

$ postconf -n
mydestination =
mydomain = example.com
myhostname = mail.example.com
relayhost = [email-smtp.ap-northeast-1.amazonaws.com]:587

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt
smtp_tls_note_starttls_offer = yes
smtp_tls_security_level = encrypt
smtp_use_tls = yes

作成したSMTPクレデンシャルを設定します。

$ sudo vim /etc/postfix/sasl_passwd

設定内容は以下のとおりです。
ご自身のSESリージョンと認証情報に合わせて記載を更新してください。

[email-smtp.ap-northeast-1.amazonaws.com]:587 ****(SMTPユーザーネーム):****(SMTPパスワード)

ハッシュ化します。

$ sudo postmap hash:/etc/postfix/sasl_passwd

ファイルの権限を更新します。

$ sudo chown root:root /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
$ sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db

再起動して、設定内容を反映させてください。

$ sudo systemctl restart postfix

※ 認証情報の取り扱いについて

本番環境ではサーバーに認証情報を直置きしてはいけません。
本番環境で認証情報をサーバーに直接保存すると、サーバーが侵害された際に認証情報が漏洩し、不正にSESを利用されるリスクがあります。

今回は検証環境での構築であり、簡単のため認証情報をサーバーに直置きしています。

本記事のように、サーバーがEC2上にある場合は AWS IAMロールや、AWS Secrets Manager を使用します。

そうでない場合も、安全な認証情報ストレージを使い、アクセス制御を行いましょう。

テスト

実際にメールを送信し、SES経由になっているか確認しましょう。
mailコマンドでテストメールを送信します。

$ mail -s "SES test mail" -r origin@example.com destination@example.com
test
.
EOT

届いたメールを確認します。
SES経由になっていることが確認できました。

Tips main.cf 設定パラメータ詳細

/etc/postfix/main.cfに設定したパラメータの詳細について記載します。
※適宜、お手元の環境の設定値として正しいか、公式ドキュメントの日本語訳と照らし合わせて設定してください。
(Postfix設定パラメータ)

myhostname

SMTP サーバーの FQDN を指定します。
デフォルト値: "postconf -d" の出力を参照します。

mydomain

myhostname のドメイン部分を指定します。
デフォルト値: "postconf -d" の出力を参照します。

mydestination

他のマシンに転送するのではなく、 メールをローカルで受信するドメイン名を指定します。
デフォルト値: mydomain, localhost

relayhost

next-hop配送先(中継サーバー)を指定します。
デフォルト値: empty
SMTP の場合、ドメイン名、ホスト名、hostname:port、[hostname]:port、 [hostaddress] または [hostaddress]:port を指定します。

smtp_sasl_auth_enable

Postfix SMTPクライアントの SASL 認証を有効化します。
デフォルト値: no

smtp_sasl_security_options

リレー先のTLS暗号化で使うセキュリティオプションを指定します。
デフォルト値: noplaintext, noanonymous
以下のオプションがあります。

  • noplaintext
    • 平文パスワードを使う方法を許可しない
  • noactive
    • active (非辞書) 攻撃を受けるような方法を許可しない。
    • active 攻撃とは、攻撃者が認証プロセスに割り込み、パスワードを盗み取る手法のこと。
  • nodictionary
    • passive (辞書) 攻撃を受けるような方法を許可しない。
    • 辞書攻撃とは、攻撃者が一般的なパスワードのリストを使って認証を試みる手法のこと。
  • noanonymous
    • 匿名認証を認めるような方法を許可しない。
  • mutual_auth
    • 相互認証を提供する方法のみを許可する。

smtp_sasl_password_maps

リレー先のTLS暗号化で使う認証情報が記載されたファイルの場所を指定します。
デフォルト値: empty

smtp_use_tls

リモートSMTPサーバがSTARTTLSサポートを案内したら TLSを使い、案内がなければ平文でメールを送ります。 (Postfix 2.2以降)
SES では STARTTLS がサポートされているので TLS を使うために有効化します。
デフォルト値: no

smtp_tls_security_level

Postfix SMTPクライアントでのSMTP TLSセキュリティレベル を設定します。
デフォルト値: empty
以下、設定値

  • may
    • 暗号化必須ではないが、可能であればする。
  • encrypt
    • 暗号化必須。規格に沿った証明書であればすべて許容(S/MIMEなど)。
  • verify
    • 暗号化必須。証明書のCAが信用できるかも合わせて検証。
  • secure
    • 暗号化必須。さらに、「証明書のSubjectAlternativeNameかCommonNameが接続先サーバ名と一致しているか」まで検証。

smtp_tls_note_starttls_offer

TLSが有効になっていない場合、STARTTLSを提供するリモートSMTPサーバのホスト名をログ出力させます。(Postfix 2.2以降)。
デフォルト値: no
以下のようなログが出るようになります。

postfix/smtp[pid]:  Host offered STARTTLS: [name.of.host]

smtp_tls_CAfile

Postfix SMTPクライアント証明書を発行した認証局 (CA) の証明書を持つファイルの場所を指定します。(Postfix 2.2以降)
(Postfixが送信先のSMTPサーバーの正当性を確認するために必要です。)
デフォルト値: empty

さいごに

今回の作業を通して、SMTPリレーの仕組みやSESの利用方法について理解を深めることができました。特に、Postfixの設定で各パラメータの役割を理解するのに苦労しましたが、先輩のご助力や、公式ドキュメントを参照することで解決できました。

今後は、SESとCloudWatchと連携させて、メール送信の監視体制を構築してみたり、社内サーバへ導入したウイルスソフトからのアラートメールを振り分けられるようにしたり、知識を発展させていきたいと考えております。

最後までお読みいただき、ありがとうございました。この記事が、SMTPリレーやSESについて学習されている方の参考になれば幸いです。