意図せずオープンリレーサーバーが爆誕していた話

本記事は、[本番環境などでやらかしちゃった人 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/yarakashi-production)の20日目の記事です。

今や生活に欠かせない電子メール。(とは言っても僕は電子メールが無い時代を知りませんが。)
あなたも、一度は「メールサーバーを自分で建てたい！」と思ったことがあるのではないでしょうか。
今回は、そんなメールサーバーの運用で2年ほど前（当時15歳）にやらかしてしまった話です。

:::note info
このやらかしは普通なら起こりません。
セキュリティや設定などの有用な情報を求めてこの記事に辿り着いた方にとっては時間の無駄になるかもしれません。
:::

# はじめてのメールサーバー
当時は丁度ドメイン (awayume.jp) を取りたてで、またRaspberry Pi 4Bも入手したので、折角だからメールサーバーでも建ててみようと思い立ち、早速やってみることにしました。

## 構成
- OS: Ubuntu Server 22.04
- [Postfix](https://www.postfix.org/) + [Dovecot](https://www.dovecot.org/) (+ [Cyrus SASL](https://ryuichi1208.hateblo.jp/entry/2024/01/02/121849))
- メールアカウントは[PostgreSQL](https://www.postgresql.org/)で管理
- 外部へのメール送信は[GmailのSMTPサーバーを経由](https://www.chuken-engineer.com/entry/2019/11/08/193631) (OP25B対策)

設定方法については割愛します。

さらに、セキュリティ対策として[SELinux](https://www.tohoho-web.com/ex/selinux.html), [Fail2ban](https://zenn.dev/uchidaryo/books/ubuntu-2204-server-book/viewer/fail2ban), [Tripwire](https://tracpath.com/works/development/how-to-build-intrusiondetection-system-with-tripwire/), [Snort](https://www.snort.org/), [rkhunter](https://www.server-world.info/query?os=Ubuntu_22.04&p=rkhunter), [ClamAV](https://zenn.dev/gladevise/articles/clamav-usage), [Amavis](https://wiki.archlinux.jp/index.php/Amavis)などを設定。
なんとなく「ぼくのかんがえたさいきょうのセキュリティ」感がありますが、一旦おいておくとして。

また、[SPF, DKIM, DMARC](https://ent.iij.ad.jp/articles/172/)も設定。DKIM署名には[OpenDKIM](http://www.opendkim.org/)を使用しました。
余談ですが、その約2年後(今年)の秋に受けた[情報処理安全確保支援士試験](https://www.ipa.go.jp/shiken/kubun/sc.html)の[午後試験](https://www.ipa.go.jp/shiken/mondai-kaiotu/m42obm000000afqx-att/2024r06a_sc_pm_qs.pdf)でSPF, DKIMに関する問題が出題され、この経験がかなり役に立ちました。
2024/12/29追記: 無事合格しました！

## 「名案」
さて、それでは先程のセキュリティ云々の話は全く関係無いので忘れてください。

メールサーバーをホストするためには、MXレコードにホスト名を、それに対応するA(あるいはAAAA)レコードにサーバーのIPアドレスを設定する必要があります。
普段はCloudflareのプロキシを通して自宅サーバーのIPアドレスを秘匿しているのですが、CloudflareはSMTP通信の面倒までは見てくれません。従ってプロキシを解除する必要があります。こればかりはどうしようもありません[^1]。

しかし、赤裸々にIPアドレスを開示するAレコードの姿がやはりどうしても気になります。思案を続け、食事も喉を通り、夜に眠る日々が続く中でふと思いつきます。

***そうだ、VPSに通信を中継させよう———***

この余計な思いつきこそが諸悪の根源。
「VPSでメールサーバーをホストしよう」ではなく「VPSに通信を中継させる」と考えたのです。

その理由は単純。
「メールのデータが急に無くなると困るから、もし万が一いきなりVPSアカウントを消し飛ばされたとしても大丈夫なようにデータは全部自分のサーバーに置こう！」
という発想でした。
また、前述したようなセキュリティの構成やメールサーバーの設定を移す手間をケチるため、という理由もあります。
割合としては7:3くらいです。

今考えれば、PostfixをVPSで、[Dovecot LMTP](https://doc.dovecot.org/2.3/configuration_manual/protocols/lmtp_server/)を自宅サーバーで動かせばよかったのではと思います。
その手間を惜しまないでいれば、恐らくこの問題は起こらなかったでしょう。

### 通信を中継しよう！
その肝心な通信中継の方法には[SSHポートフォワーディング](https://zenn.dev/gentoopng/articles/6b063e937734de)を採用しました。
詳細な設定方法は割愛しますが、自戒を込めて使用したコマンドを以下に記しておきます。

```shell
ssh -fNR 25:localhost:25 user@host
```

このコマンドではVPSの25番ポートに来た通信を自宅サーバーの25番ポートに転送しています。

ここで、Telnetコマンドを使い通信できるか試してみると[^2]、狙い通り自宅サーバーから返事が返ってきた！
これでAレコードに自宅サーバーのIPアドレスを書く必要がなくなった！！ 万歳！！！
めでたしめでたし。

…とは、ならなかったわけで。

# 発覚
ふとGmailを見たところ、バウンスメールが届いています。
それを開いたところ、送信先には見知らぬ中国のメールアドレス。

明らかに、そんなものを送った覚えは、ありません。

`送信済み` タブを見てみましょう。

「Login Go! `VPSのIPアドレス`」
「ｅｍａｉｌ代發，ｅｍａｉｌ裙發軟件，實力见证，趕緊加QQ：⒌⒏⒊⒊⒍⒌⒌0.⒐」
「研究对象[@$@]`VPSのIPアドレス`[@$@],郵建裙發，郵建代發ｑｑ:３１２３８２７８０６」
「关于第四季度个人劳动补贴,请查看附件!2023-01-05」

中国語のオンパレード。

…何やら大変なことが起こったらしい

## 現場検証
一先ずPostfixを止め、ログを精査してみましょう。
送信先のメールアドレスで文字検索をかけ、送信ログを絞り込み。その上にある接続ログを確認すると…

なんとそこには、***localhostからの接続ログが！***

ここで少し振り返ってみましょう。

> VPSの25番ポートに来た通信を自宅サーバーの25番ポートに転送しています

あっ………

# 原因
SSHポートフォワーディングで接続を転送すると、接続元がlocalhostになってしまいます。
そして、利便性のためにlocalhostからのアクセスには認証をかけていませんでした。

結果として、全ての接続がlocalhostからの接続に変換された結果、**全ての通信に対する認証が無効化**されてしまったのです。

localhostからの接続に認証を要求していなかったのは、ローカルからの通知メールなどを受け取るためでした。このような設定をしている方は少なくないと思います。
普通なら問題にはならないでしょう。しかし、他ホストから通信を転送するなどというエキセントリックなことをしたばかりにこのようなことになってしまいました。

そもそもlocalhostからの接続にも認証を要求した方がいいですね。
サーバー内からの通知メールを送受信したいなら、専用のメールアカウントを作り、それに対する認証だけを無効化して、かつ外部送信を禁止するといったような運用が適しているでしょう。

## 余談
こちらは去年のアドベントカレンダーで書いた本環やらかしの記事です。

https://qiita.com/Awayume/items/fcfd12531b49e987b36a

去年の記事のやらかしは2021年、この記事（今年の記事）のやらかしは2022年（から2023年の始め）です。
それぞれ2年経過してから書いているわけですが、なんとめでたいことに来年書く本環やらかしはありません！ そして、今のところは再来年書くこともありません！！

実にめでたいことです。
願わくは、明々後年に書くことが生まれませんように。

[^1]: 「Cloudflare Email Routingを使えよ」なんて言わないでください。そうだけどそうじゃないので。
[^2]: 25番ポートに直接通信する術は持ち合わせていなかった(OP25B)ので、この検証の時に限りSMTP Submissionを使用しました。