壊れるほど送っても1/3も伝わらない(1)

MEGAZONE 株式会社 のテック陣「MEGAZONEのゆかいな仲間たち」がおくる、Megazone Japan Advent Calendar 2023 の9日目のエントリーです。

## 本記事のサーバについて
EC2インスタンスはAmazon Linux 2を前提に記載しています。

## AWSに移行したらメールが届かない？
今まで運用していたサーバをAWSのEC2へマイグレーションしたら、サーバからのメールが届かなくなった！
Postfixは入っているし、はたしてメール送信処理はできているのだろうか？

```
$ echo -e "Subject: Test Mail\n\nTest" | sendmail ryo.kawana@example.com
```
とりえあえずシンプルにメール送信。
移行前のサーバで送信したメールは届いているが、EC2インスタンスからのメールは届いていない。

```
$ sudo less /var/log/maillog
-----------------------------------------------
Dec 13 03:59:53 ip-10-0-21-216 postfix/pickup[7493]: 129067ECA0: uid=0 from=<root>
Dec 13 03:59:53 ip-10-0-21-216 postfix/cleanup[7685]: 129067ECA0: message-id=<20231213035953.129067ECA0@ip-10-0-21-216.ap-northeast-1.compute.internal>
Dec 13 03:59:53 ip-10-0-21-216 postfix/qmgr[2258]: 129067ECA0: from=<root@ip-10-0-21-216.ap-northeast-1.compute.internal>, size=376, nrcpt=1 (queue active)
Dec 13 03:59:53 ip-10-0-21-216 postfix/smtp[7687]: connect to aspmx.l.google.com[2404:6800:4008:c06::1a]:25: Network is unreachable
Dec 13 04:00:23 ip-10-0-21-216 postfix/smtp[7687]: connect to aspmx.l.google.com[64.233.189.27]:25: Connection timed out
Dec 13 04:00:53 ip-10-0-21-216 postfix/smtp[7687]: connect to alt2.aspmx.l.google.com[142.250.115.27]:25: Connection timed out
Dec 13 04:01:23 ip-10-0-21-216 postfix/smtp[7687]: connect to alt2.aspmx.l.google.com[2607:f8b0:4023:1004::1b]:25: Network is unreachable
Dec 13 04:01:23 ip-10-0-21-216 postfix/smtp[7687]: 129067ECA0: to=<ryo.kawana@example.com>, relay=none, delay=90, delays=0.02/0.01/90/0, dsn=4.4.1, status=deferred (connect to alt2.aspmx.l.google.com[2607:f8b0:4023:1004::1b]:25: Network is unreachable)
-----------------------------------------------
```

ログを見るとNetwork is unreachableとConnection time outが発生している。
Network is unreachableはIPv6なのでいいとして、Connection time outの部分は他のサーバで接続できている。

どうもTCP25番ポートでメールサーバへ接続する際にタイムアウトしているようだ……

## 外部へのTCP25番ポート通信が制限されている
> ポート 25 を使用した E メール送信の制限
すべてのインスタンスで、Amazon EC2 はデフォルトでポート 25 を介したパブリック IP アドレスへのアウトバウンドトラフィックを制限します。この制限の解除をリクエストできます。

[AWSのドキュメント](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-resource-limits.html)によるEC2は外部へのTCP25番ポート通信を制限しているらしい。
この制限は制限解除リクエストはできるものの、このままでは従来のようにサーバからメールが送信できない。

さて、どうするべきか……

## 解決策
思いつくのは以下の3つの方法。

* 制限解除
* 外部のメール送信サーバを利用
* Amazon SESを利用

### [1] 制限解除
[AWSナレッジセンター](https://repost.aws/ja/knowledge-center/ec2-port-25-throttle)によると申請自体は特に問題なさそうだけども、EC2インスタンスごとに申請と解除をしてもらう必要があるので、メール送信サーバを運用するならともかく、サーバからメールを送信したいだけに実施するのはあまりスマートではない気がする。

### [2] 外部のメール送信サーバを利用
パソコンでメールクライアントを利用するのと同じように、EC2インスタンスも外部のメール送信サーバを指定すればこの制限には引っかからないはず。[SendLayer](https://sendlayer.com/)や[SMTP.com](https://www.smtp.com/)のようなメール送信サービスの他、[さくらのメールボックス](https://rs.sakura.ad.jp/mail/)や一般的な共有レンタルサーバはメール送信サーバとして利用することができる。

EC2インスタンスの制限のためだけに利用するのは違和感を覚えるかもしれないが、AWS以外のサーバやシステムで共用するのであればアリかも。

### [3] Amazon SESを利用
Amazon SESはAWSのメール送信サービス。従量だけども非常に低価格。EC2インスタンスからのメール送信のことだけを考えるのであればSESが最適となるはず。

## あえて外部のメール送信サーバを使ってみる
「ならばAmazon SESを使うのだな？」という流れを断ち切って、外部のメール送信サーバを使ってみよう。ちょうど契約していた[ConoHa Wing](https://www.conoha.jp/wing/)の契約があるので試してみる。

はたしてうまくいくのだろうか……

## メールアドレス(メールアカウント)の作成
メール送信サーバでは認証が必要となるので、ConoHa Wing側でメールアドレスを作成しておく。また[契約情報](https://manage.conoha.jp/Wing/Server)で「メール/FTP/ネームサーバ情報」をクリックするとSMTPサーバのFQDNが表示されるので控えておこう。

## EC2インスタンス内の設定
初めからPostfixがインストールされているので、その設定を変更し、ConoHa Wingのメール送信サーバを利用してみる。

```
$ sudo vi /etc/postfix/main.cf
===============================================
relayhost = [mailxxx.conoha.ne.jp]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_use_tls = yes
smtp_tls_security_level = encrypt
smtp_tls_note_starttls_offer = yes
===============================================
```
「mailxxx.conoha.ne.jp」の部分は先ほど控えたConoHa WingのSMTPサーバ。その右側にある「587」はTCP587番ポートに接続することを示している。

```
$ sudo vi /etc/postfix/sasl_passwd
===============================================
[mail1xxx.conoha.ne.jp]:587 conoha-mail-address:password
===============================================
```
| 設定値 | 概要 |
|:-:|:-:|
| mail1xxx.conoha.ne.jp  | ConoHa WingのSMTPサーバを指定  |
|  conoha-mail-address | 作成したメールアドレス(@の後ろのドメインも含める)  |
|  password |  作成したメールアドレスのパスワード |

```
$ sudo chmod 600 /etc/postfix/sasl_passwd
```
sasl_passwdのパーミッション変更。

```
$ sudo postmap hash:/etc/postfix/sasl_passwd
$ ll /etc/postfix/ |grep "sasl_passwd.db"
-----------------------------------------------
-rw------- 1 root root 12288 Dec 13 07:21 sasl_passwd.db
-----------------------------------------------
```
ハッシュファイルの作成。

```
$ sudo postconf -e 'smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt'
```
CA証明書を指定。

```
$ sudo systemctl reload postfix
$ sudo systemctl status postfix
```
Postfixサーバをリロード+起動確認。

## メール送信確認
```
$ echo -e "Subject: Test Mail\n\nTest" | sendmail ryo.kawana@example.com
```
先ほど失敗したメール送信コマンドを改めて実行。

```
$ sudo less /var/log/maillog
-----------------------------------------------
Dec 13 05:37:24 ip-10-0-21-216 postfix/pickup[8062]: D1BAE7ECA2: uid=0 from=<root>
Dec 13 05:37:24 ip-10-0-21-216 postfix/cleanup[8113]: D1BAE7ECA2: message-id=<20231213053724.D1BAE7ECA2@ip-10-0-21-216.ap-northeast-1.compute.internal>
Dec 13 05:37:24 ip-10-0-21-216 postfix/qmgr[8061]: D1BAE7ECA2: from=<root@ip-10-0-21-216.ap-northeast-1.compute.internal>, size=368, nrcpt=1 (queue active)
Dec 13 05:37:25 ip-10-0-21-216 postfix/smtp[8115]: D1BAE7ECA2: to=<ryo.kawana@example.com>, relay=mail1xxx.conoha.ne.jp[160.251.148.44]:587, delay=0.38, delays=0.02/0.01/0.2/0.16, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 204BE24042688)
Dec 13 05:37:25 ip-10-0-21-216 postfix/qmgr[8061]: D1BAE7ECA2: removed
-----------------------------------------------
```

ログを見るとどうやら送信は成功した模様。しばらくして宛先のメールアドレスで該当のメールが届くことを確認できた。

これでサーバ内で動いているチェックスクリプトやらなんやらでメールが送信できるぞ！

## おわりに
理由があってcronで動かしている秘伝のシェルスクリプトの結果メールが届かなくなった！や、Webサイトのフォームメールが届かなくなった！というケースはそれなりにあるような気がします。

今回はEC2の制限を回避するための例として外部のメールサーバ利用をしてみましたが、EC2以外でも利用できることなので、VPSやオンプレミスのサーバで信頼できるメール送信サーバを利用したい、といった場合などにご参考下さい。