Postfix の reject_authenticated_sender_login_mismatch の設定方法

postfix の設定で [smtpd_recipient_restrictions](http://www.postfix.org/postconf.5.html#smtpd_recipient_restrictions) という項目があるのですが、この設定項目に [reject_authenticated_sender_login_mismatch](http://www.postfix.org/postconf.5.html#reject_authenticated_sender_login_mismatch) を追加することによって、各ユーザーごとに使用することの出来るメールアドレス（メールヘッダーのfromの部分）を制限する事ができます。これによって自鯖から送信元を偽装したメールを送られる事を防ぐことが出来ます。しかし、意外とこの設定がドキュメント見ても分かりづらかったので、ここに記しておきます。

# reject_authenticated_sender_login_mismatch について

まず、ドキュメントによりますと [reject_authenticated_sender_login_mismatch](http://www.postfix.org/postconf.5.html#reject_authenticated_sender_login_mismatch) は、認証されたユーザーのみに対して [reject_sender_login_mismatch](http://www.postfix.org/postconf.5.html#reject_sender_login_mismatch) を適用するという制限です。そして、この [reject_sender_login_mismatch](http://www.postfix.org/postconf.5.html#reject_sender_login_mismatch)というのが、メールアドレス所有者以外のメール送信を禁止するという制限です。

ここで、なんで [reject_sender_login_mismatch](http://www.postfix.org/postconf.5.html#reject_sender_login_mismatch)を使わないのという疑問が出て来る人がいると思います。私の場合 localhost からのメール送信は認証無しで行えるようにしているのですが、その際に自由にメールアドレスが使えたほうが嬉しいからという理由でこちらの設定を採用しています。何があっても、From ヘッダーは正しいメールアドレスであって欲しいという人は、[reject_sender_login_mismatch](http://www.postfix.org/postconf.5.html#reject_sender_login_mismatch) を使ったほうが良いでしょう。

先程、「メールアドレスの所有者以外のメール送信を禁止」と書きましたが、じゃあメールアドレスの所有者はどうやって決められるのかというと、[$smtpd_sender_login_maps](http://www.postfix.org/postconf.5.html#smtpd_sender_login_maps) に設定されたファイルを参照して決定されます。対応しているファイル形式は色々と存在していて、[postfixのドキュメント](www.postfix.org/DATABASE_README.html#types)にごちゃごちゃと書いてあります。とんでもない数があるのですが、今回の場合は hash, pcre, regexp あたりが使えれば困ることはないと思います。

# hash を用いた設定方法

まず hash の使い方について確認していきます。例えば hoge@example.com というメールアドレスはユーザー hoge が所有しているとしましょう。この場合 hash ファイル ```login_map.hash``` に、以下のように記述します。

```text:login_map.hash
hoge@example.com hoge
```

この形式が基本です。他にユーザー fuga が fuga@example.com というメールアドレスを使うならば、

```text:login_map.hash
hoge@example.com hoge
fuga@example.com fuga
```

の様に新しい行にどんどん記述していきます。[$smtpd_sender_login_maps](http://www.postfix.org/postconf.5.html#smtpd_sender_login_maps) の[ドキュメント](http://www.postfix.org/postconf.5.html#smtpd_sender_login_maps)を見ると分かるのですが、先の記法に比べて優先度は低くなっているのですが、第二優先度の記法として、

```text:login_map.hash
hoge hoge
fuga fuga
```
の様にドメイン部分を省略した記法が存在します。この記法で書いたときメールアドレスのドメイン名は \$myorigin, \$mydestination, \$inet_interfaces もしくは \$proxy_interfaces にマッチしている必要があります。なので ```main.cf``` ファイルに、

```main.cf
...
mydestination = example.com, localhost
...
```

などと記述されてれば、メールアドレスを完全に記述した場合と同等の効果を得ることが出来ます。最後に最も優先度が低い記法としてドメイン部だけを記述する方法があります。

```text:login_map.hash
hoge@example.com hoge
fuga@example.com fuga
@example.com piyo
```

例えばこのように記述すると、hoge@example.com と fuga@example.com 以外の @example.com で終わるメールアドレスは全て piyo さんが持っていると解釈されることになります。

以上の方法で生成した ```login_map.hash``` ファイルを postmap コマンドで hash 形式に変換すれば利用できるようになります。```/etc/postfix/login_map.hash``` にファイルがあったとすれば、

```bash
cd /etc/postfix
sudo postmap hash:login_map.hash
```

とすることで ```/etc/postfix/login_map.hash.db``` というファイルが生成されます。後は ```main.cf``` ファイルに

```main.cf
...
smtpd_sender_login_maps = hash:/etc/postfix/login_map.hash
...
```

の様に記述してあげればOKです。最後に postfix の設定を反映してテストしてあげましょう。

```bash
postfix reload
```

# 正規表現を用いた設定方法
hash を使う方法は分かりやすいのですが、ユーザー数が増えてくると管理だけで死にたくなってくることでしょう。普通は、ユーザー1人に対して発行するメールアドレスは1つのことが多いはずです。そうでなくても何かしらの規則性があったりするものです。そういった場合は正規表現を使って書くと便利です。

正規表現は POSIX の記法と Perl の記法が使えるのですが、ビルドによっては使えない場合があります。```postconf -m``` コマンドで pcre や regexp が現れるかを確認して、使えるものを使ってください。以降では POSIX 記法で話を進めていきます。

例えば、全てのユーザーは自分のユーザー名を user とした時、 ```user@example.com``` というメールアドレスを持てるものとします。このような場合は以下のように ```/etc/postfix/login_map.regex``` を作成し、

```text:login_map.regex
/^(.*)@example.com$/ $1
```

```/etc/postfix/main.cf``` に、

```main.cf
...
smtpd_sender_login_maps = regexp:/etc/postfix/login_map.regex
...
```

の様に記述します。pcre の場合は regexp の部分を pcre に置き換えます。これで hoge さんは hoge@example.com を使えますし、 piyo さんも piyo@example.com を使うことが出来ます。

# あわせ技での設定
今まで紹介した二つの方法を合わせることも出来ます。基本的には正規表現の時と同じような動作をさせたいが、webmaster@example.com というメールアドレスだけ hoge さんから送信できるようにしたいとします。このときは、

```text:login_map.hash
webmaster@example.com hoge
```

と hash 用のファイルを作っておいて、 ```main.cf``` のでの設定を、

```main.cf
...
smtpd_sender_login_maps = hash:/etc/postfix/login_map.hash, regexp:/etc/postfix/login_map.regex
...
```

の様にしてあげると実現できます。postfix は最初のファイルから順番にメールアドレスのマッチングを行っていくので、 webmaster@example.com の所有者は hoge さんということになります。

# 参考

* [Block sender address spoofing with SMPT AUTH](https://blog.felipe-alfaro.com/2006/02/19/block-sender-address-spoofing-with-smpt-auth/)
* [How to enforce sender address to be &quot;logged-in-user@example.org&quot; in Postfix? - Server Fault](http://serverfault.com/questions/318334/how-to-enforce-sender-address-to-be-logged-in-userexample-org-in-postfix)