前回は、SPF/DKIM/Dmarcを使った送信メールの信頼度向上と、受信メールのフィルター実装をしました
今回は、Postfixの機能など使ったスパムメール対策と、fail2banを使ったアタック制御を実装していきます
今回のコンポーネント
コンポーネント | 利用しているもの |
---|---|
MTA | Postfix 3.4.13 |
POP/IMAPサーバ | Dovecot 2.3.7 |
メールボックス管理 | PostfixAdmin 3.2.1 |
SSL証明書 | Let's Encrypt |
DNS | Bind 9.16.1 |
データベース | MariaDB 10.3.25 |
DKIM | OpenDKIM 2.11.0 |
DMARC | OpenDMARC 1.3.2 |
グレーリスト管理 | postgrey 1.36 |
Log Report | Pflogsumm 1.1.5 |
SPAM管理 |
SpamAssassin 3.4.4 |
ウィルススキャン (当初導入するも、メモリ不足で無効化) |
Amavis 2.11.0 ClamAV 0.103.2 |
当初、ウィルススキャンとしてAmavis/ClamAVを導入しました。
メモリが2GBでは足りなかったため最終的には無効化していますが、導入手順はメモとして記載しています。
今回は、メールサーバ構築に関して理解しながら進めるために、段階的にステップを踏みながら構築を進めていきます。
- Postfixサーバの基本セットアップ
- TLS暗号化とDovecot IMAP/POP3サーバセットアップ
- PostfixAdminを使ってバーチャルメールボックス作成
- 信頼度向上のためのSPF/DKIMレコード作成
- ドメイン信頼性向上のためのDMARCセットアップ
- Postfixでのスパム受信ブロック
1ページでの記載には大きすぎたので記事を分割します
今回の記事では、スパムメール対策をSTEP6ではPostfixの機能を利用して実装していきます。
STEP6. Postfixでのスパム受信ブロック
まずPostfixで実装可能なSPAM対策方法を記載します。
全項目を実装する必要はなく、状況に応じてそれぞれの項目の適用を判断いただければと思います
Postfixで実装するSPAM対策としては以下のような方法があります。
- 接続を遅くする: ターピッティング(tarpitting)
- 接続元サーバ IP アドレスと DNS 逆引きサーバ名で制限: smtpd_client_restrictions で設定
- HELO メッセージのサーバ名で制限 : smtpd_helo_restrictions で設定
- MAIL FROM メッセージの差し出し人メールアドレスで制限 : smtpd_sender_restrictions で設定
- RCPT TO メッセージの宛先メールアドレスで制限 : smtpd_recipient_restrictions で設定
- DATA ヘッダ情報で制限 : header_checks で設定
- DATA 本文で制限 : body_checks で設定
- DATA コマンドで制限 : smtpd_data_restrictions で設定
Tip1. 接続遅延発生(tarpitting)
スパム送信者は送信先サーバーからの応答を待たずに、一方的にメール送信コマンドを送ることがあります。
tarpittingとは、スパムメールを排除するために、SMTPプロトコルの通信をわざと遅らせる手法です。
このような送信者を識別するため、応答をわざと遅らせておき、応答を送る前に相手が次のコマンドを送ってくるかを確認します。
もし相手がすぐに次のコマンドを送ってくるようであれば、スパム送信者として受信を拒否します。
Sample1. smtpd_error_sleep_timeによるエラー制御
本機能は現在のPostfixでは標準で実装されています。
パラメータをチューニングすることにより効果を上げることもできますが、サーバパフォーマンスに影響を与える可能性もあります。
仕組みとしては、SMTPセッションにおいて、smtpd_soft_error_limitで定義された回数より多くエラーが発生した際に、smtpd_error_sleep_timeで定義された時間ウェイトを発生させます。
エラー回数がsmtpd_hard_error_limitで定義された回数に達すると、SMTPセッションは切断されます。
要するに、smtpd_soft_error_limit < (接続中のエラー数) <= smtpd_hard_error_limit の場合,、SMTP コマンド毎に smtpd_error_sleep_time 分ウェイトを発生ですね。
チューニングを行う場合は、Postfixの設定ファイルmain.cfにパラメータを記載します
# vim /etc/postfix/main.cf
設定例 | コマンド解説 |
---|---|
smtpd_soft_error_limit = 5 |
smtpd_soft_error_limit (default: 10) smtpd_hard_error_limit (default: 20) smtpd_soft_error_limit (default: 1s) |
Sample2. smtpd_client_restrictions への遅延追加
このやり方は後述するsmtpd_client_restricitons、smtpd_helo_restricitons、smtpd_sender_restricitons、smtpd_recipient_restricitonsなどで適用可能です
これらの制限実装時は、記載した順番(要するに上から)に許可・不許可などのチェックが行われます。
休止の入る条件を調整できるので, 可能な限り 許可/不許可を振り分けたあとにsleepを入れます。
全制限に実装すると、それぞれの確認時にsleepが入りますので、どれか1か所で良いと思います。
例:
smtpd_client_restrictions =
permit_mynetworks
permit_sasl_authenticated
check_client_access hash:/etc/postfix/client_access
reject_unknown_reverse_client_hostname
sleep 10
TIP2. Postfixでのメールリレー時の制御
SMTP基本手順
SMTPの基本的な通信フローの図を作成しました。通常メッセージ送信時は下記のようなフローでSMTPサーバ間の通信が行われます
Postfixでの制限
Postfix SMTPサーバでは、それぞれのフェーズで制限をかけることが可能です
各フェーズでの制限をかけるパラメータを図示しています
Postfix SMTPサーバでは、メールリレー時に以下の順番でチェックを行います
設定パラメータ | タイミング |
smtpd_client_restricitons | Postfix SMTPサーバがクライアントからSMTP接続の要求を受けた際に適用 |
smtpd_helo_restricitons | Postfix SMTPサーバが SMTP HELO コマンドの場面で適用 |
smtpd_sender_restricitons | Postfix SMTPサーバが MAIL FROM コマンドの場面で適用 |
smtpd_recipient_restricitons | Postfix SMTPサーバが RCPT TO コマンドの場面で適用 |
header_checks | DATA受信時にヘッダ内容に適用 |
body_checks | DATA受信時にメール本文に適用 |
スパム対策に有効な制限方法例を記載していきます
Sample1. クライアント接続制限(smtpd_client_restrictions)
クライアントからPostfix SMTPサーバへの接続要求時に制限を行います
今回は、自身のネットワークからの接続、SMTP認証を経た接続に加えて以下を行います
- ホワイト/ブラックリストの適用
- RBL(Realtime Blackhole List)というブラックリスト管理サービス提供者のリストによる制限
この他に、接続元IPアドレスの逆引き可否や、逆引きしたIPアドレスチェックなどもあります
スパム対策としては非常に効果的な方法ではありますが、正当なメールサーバにおいても逆引き不可であることがあり、実装する際はホワイトリストのメンテナンスを考慮する必要があります(この懸念から私の環境では実装をあきらめていますが、設定方法を記載します)
設定ファイル編集
適用には、Postrix設定ファイル/etc/postfix/main.cfを編集します
# vim /etc/postfix/main.cf
下記項目を追加
設定例 | コマンド解説 |
---|---|
smtpd_client_restrictions = |
smtpd_sender_restrictions = permit_sasl_authenticated check_client_access hash:/etc/postfix/client_access reject_rbl_client xxx.xxx.xxx.xxx reject_unknown_client_hostname reject_unknown_reverse_client_hostname sleep seconds permit |
アクセスリスト作成
check_client_accessで指定した、/etc/postfix/client_accessに許可または拒否対象を記載するアクセスリストを作成します
# vim /etc/postfix/client_access
記載例を例示します
設定例(書式:pattern action) | 解説 |
12.34.56.78 OK 11.22.33 REJECT 22.33 REJECT cracker.com spammer.spam.com REJECT You are blacklisted |
pattern OK pattern REJECT pattern REJECT optional_text pattern書式 12.34.56.78 接続元IPアドレス(12.34.56.78) 11.22.33 接続元ネットワークアドレス(11.22.33.0/24) cracker.com 接続元ドメイン(cracker.com) spammer.spam.com 接続元FQDNホスト名(spammer.spam.com) |
アクセスリスト変換
postmapコマンドによりPostfixが参照できるよう変換を実施
# postmap /etc/postfix/client_access
設定反映
Postfixを再起動して反映します
# systemctl restart postfix
Sample2. SMTP HELO/EHLO接続制限(smtpd_helo_restrictions)
スパム送信者は、SMTP接続手順におけるHELOやEHLO(Extended Hello)コマンド送出時に正しいホスト名を示さない場合があります
今回の制限対象は以下となります
- 不正なホスト名(例:localhost)
- FQDN形式ではない場合
- DNS AレコードやMXレコードにホスト名が存在しない場合
適用には、Postrix設定ファイル/etc/postfix/main.cfを編集します
# vim /etc/postfix/main.cf
下記項目を追加
設定例 | コマンド解説 |
---|---|
smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks permit_sasl_authenticated check_helo_access hash:/etc/postfix/helo_access reject_invalid_helo_hostname reject_non_fqdn_helo_hostname reject_unknown_helo_hostname permit |
smtpd_helo_required = yes smtpd_helo_restrictions = permit_sasl_authenticated check_helo_access hash:/etc/postfix/helo_access reject_invalid_helo_hostname reject_non_fqdn_helo_hostname reject_unknown_helo_hostname permit |
アクセスリスト作成
check_helo_accessで指定した、/etc/postfix/helo_accessに許可または拒否対象を記載するアクセスリストを作成します
# vim /etc/postfix/helo_access
記載例を例示します
設定例(書式:pattern action) | 解説 |
va-massmail-02.rakutenmarketing.com OK spammer.test.com REJECT spammer.spam.com REJECT You are blacklisted |
pattern OK pattern REJECT pattern REJECT optional_text |
アクセスリスト変換
postmapコマンドによりPostfixが参照できるよう変換を実施
# postmap /etc/postfix/helo_access
設定反映
Postfixを再起動して反映します
# systemctl restart postfix
Sample3. SMTP MAIL FROM接続制限(smtpd_sender_restrictions)
スパム送信者は、SMTP接続手順におけるMAIL FROMコマンド送出時に正しいホスト名を示さない場合があります
今回の制限対象は以下となります
- FQDN形式ではない場合
- MAIL FROMで提示されるドメイン部のDNS AレコードやMXレコードにホスト名が存在しない場合
適用には、Postrix設定ファイル/etc/postfix/main.cfを編集します
# vim /etc/postfix/main.cf
下記項目を追加
設定例 | コマンド解説 |
---|---|
smtpd_sender_restrictions = |
smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/rbl_override reject_non_fqdn_sender reject_unknown_sender_domain reject_rhsbl_sender xxx.xxx.xxx.xxx permit |
アクセスリスト作成
check_helo_accessで指定した、/etc/postfix/helo_accessに許可または拒否対象を記載するアクセスリストを作成します
# vim /etc/postfix/rbl_override
記載例を例示します
設定例(書式:pattern action) | 解説 |
va-massmail-02.rakutenmarketing.com OK spammer.test.com REJECT spammer.spam.com REJECT You are blacklisted |
pattern OK pattern REJECT pattern REJECT optional_text |
アクセスリスト変換
postmapコマンドによりPostfixが参照できるよう変換を実施
# postmap /etc/postfix/rbl_override
設定反映
Postfixを再起動して反映します
# systemctl restart postfix
Sample4. SMTP RCPT TO接続制限(smtpd_recipient_restrictions)
スパム送信者は、SMTP接続手順におけるRCPT TOコマンド送出時に正しいホスト名を示さない場合があります
今回の制限対象は以下となります
- FQDN形式ではない場合
- MAIL FROMで提示されるドメイン部のDNS AレコードやMXレコードにホスト名が存在しない場合
適用には、Postrix設定ファイル/etc/postfix/main.cfを編集します
# vim /etc/postfix/main.cf
下記項目を追加
設定例 | コマンド解説 |
---|---|
smtpd_recipient_restrictions = check_policy_service unix:private/policyd-spf, reject_unauth_destination, permit |
smtpd_recipient_restrictions =
check_policy_service protocol:service permit |
設定反映
Postfixを再起動して反映します
# systemctl restart postfix
Sample5. メールヘッダ/ボディ制限(header_checks/body_checks)
スパム送信者は、SMTP接続手順におけるRCPT TOコマンド送出時に正しいホスト名を示さない場合があります
今回の制限対象は以下となります
- FQDN形式ではない場合
- MAIL FROMで提示されるドメイン部のDNS AレコードやMXレコードにホスト名が存在しない場合
適用には、Postrix設定ファイル/etc/postfix/main.cfを編集します
# vim /etc/postfix/main.cf
下記項目を追加
設定例 | コマンド解説 |
---|---|
smtpd_recipient_restrictions = check_policy_service unix:private/policyd-spf, reject_unauth_destination, permit |
smtpd_recipient_restrictions =
check_policy_service protocol:service permit |
設定反映
Postfixを再起動して反映します
# systemctl restart postfix
Tip3. グレイリストの導入
SMTPプロトコルでは、正当なSMTPクライアントはメール送信失敗時に再送することが要求されています
例えば、Postfixの標準構成ではメッセージが送信できない際は以下のような挙動を行います
- 送信失敗した際はdeferredに格納
- queue_run_delay(default:100秒)毎にdeferredをチェック
- minimal_backoff_time(default:300秒)を超えるメールがあれば再送
また失敗した場合は2倍(300 x 2 = 600秒)後に再送
またまた失敗したら4倍(300 x 4 = 1200秒)後に再送 - maximal_backoff_time(default:4000秒)を超えるまで繰り返す
また失敗したらこの時間で再送 - maximal_queue_lifetime(default:5日)を超えたら再送をあきらめる
- bounce_queue_lifetime(default:5日)を超えたら送信元にエラーメールを返す
標準設定だと112回も再送を行います
しかし、多くのスパム送信者はメール送信は1回のみで再送を行いません
※そりゃそうですよね、送信先もわからず五月雨で送信するのに送信できなかったメッセージをキューにためていたらどれだけのサイズが必要なのか・・・
Postgreyというグレーリストを導入すると、次のような動作が可能となります。
- 初めて受信するメールサーバからの要求はグレイリストに登録して、受信拒否(code=450)
- 再送時に一定時間(default: 300秒)以上間隔があいていれば受信
- 送信元ドメイン、受信アドレス単位でホワイトリストの作成が可能
postgreyインストール
Ubuntu20ではパッケージ(apt)でのインストールが可能です
# apt install postgrey
サービスを起動します
# systemcrl start postgrey
恒久的に利用する場合は再起動時も自動起動するよう設定します
# systemcrl enable postgrey
起動パラメータの調整
デフォルトパラメータでは再送してきたメールの受け入れには300秒以上かかります
これを短くするには起動スクリプトで引用するパラメータを修正します
Ubuntu20では/etc/default/postgreyを変更します
# vim /etc/default/postgrey
今回は受信ディレイを60秒に変更します(下記赤字部分を追加)
# postgrey startup options, created for Debian # you may want to se POSTGREY_OPTS="--inet=10023 --delay=60" # the --greylist-text commandline argument can not be easily passed through |
ホワイトリストの調整
Postgreyでは以下の2ファイルがホワイトリストとして標準でインストールされます
設定ファイル | 説明 |
---|---|
/etc/postgrey/whitelist_client |
受信を許可するドメインを記載 |
/etc/postgrey/whitelist_recipients | 受信を許可するアドレスを許可 標準では「abuse@」と「postmaster@」が追加されています |
必要に応じて編集を行います
設定の反映
設定変更後は再起動します
# systemcrl restart postgrey
起動確認
LocalhostにてTCP10023ポートでPostgreyが起動していることを確認します
# ss -lnpt | grep postgrey
LISTEN 0 4096 127.0.0.1:10023 0.0.0.0:* users:(("postgrey --pidf",pid=47362,fd=5))
Postfix設定変更
# vim /etc/main.cf
Postfixのsmtpd_recipient_restrictionsにpostgreyを参照するようポリシー(下記赤字部分)を追加します
smtpd_recipient_restrictions = check_policy_service unix:private/policyd-spf, check_policy_service tcp:127.0.0.1:10023, reject_unauth_destination, permit |
設定反映
Postfixを再起動して反映します
# systemctl restart postfix
動作確認
whitelistに追加されていないドメインから自ドメインにメールを送信します
/var/log/maillogにpostgreyの動作が記録されればOKです。
以下、サンプルです
Apr 15 01:28:37 indigo postgrey[890]: action=greylist, reason=new, client_name=mta.email.vans.com, client_address=13.111.30.30/32, sender=bounce-2292_HTML-155312860-340997-10960531-0@bounce.email.vans.com, recipient=231990@your-domain.com |
1つ目はpostgreyによるアクション(greylist)、2つ目はPostfixによるReject、3つ目はpostgreyによるアクション(pass)です
グレイリストに入り、最終的にはtriplet (Client IP / Sender / Recipient)が登録と合致したためパスしていることが確認できました
Tip4. Fail2banによるアタック制御
メールだけではないのですが、アタッカーは繰り返し接続を試みます。
今回は、SSH、Postfix、Dovecotを対象にfail2banをセットアップしていきます。
fail2banとは
fial2ban はログファイルをスキャンし、悪意のある攻撃や兆候を元に、攻撃元の IP アドレスを自動で遮断(ban)するソフトウェアです。
fail2ban はクライアント・サーバ型のシステムでPython で書かれています。fail2ban-serverはサーバ内に常駐し、対象のログファイルを監視します。このサーバに対して設定や操作をするのが、fail2ban-client(クライアント)コマンドです。
遮断に関しては、Ubuntu20でパッケージインストールした際はiptableが標準ですが、ufwなども使えますし、CloudFlareなど外部サービスへのAPIキックなども可能です。
fail2banインストール
Ubuntu20ではfail2banはパッケージ(apt)を使ってのインストールが可能です
# apt install fail2ban
Actionをiptablesからufw利用に変更
インストール時はfilter適用時の制限にiptableを利用します。
Ubuntu20では標準的なFirewallポリシー管理としてufwを利用していますので、ufwを利用するよう変更します。
/etc/fail2ban/jail.confが標準設定ファイルですが、jail.localを作成するとconfigを上書きできますのでcopyして編集します
# cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# vim /etc/fail2ban/jail.local
banaction及びbanaction_allports をufwに変更
# banaction = iptables-multiport |
Postfix Flood Attack対策
PostfixへのFlood Attack対策用のポリシーを記載
/etc/fail2ban/jail.d/以下に設定ファイルpostfix-flood-attack.confを作成
# vim /etc/fail2ban/jail.d/postfix-flood-attack.conf
[postfix-flood-attack] enabled = true findtime = 600 bantime = 3600 filter = postfix-flood-attack action = ufw[name=postfix, port="http,https,smtp,submission,pop3,pop3s,imap,imaps,sieve", protocol=tcp] logpath = /var/log/mail.log |
追加ポリシーの適用(dovecot / postfix)
適用するポリシーの設定は/etc/fail2ban/jail.d以下に設定ファイルを設置します
インストール時はdefaults-debian.confというファイルがあり、フィルタルール[sshd]が有効になっています
追加で、事前定義されたfilterに基づく設定ファイルを設置します
dovecot
# vim /etc/fail2ban/jail.d/dovecot.conf
最大リトライを3回、探索時間10分(600秒)、遮断時間1時間(3600秒)としています
[dovecot] enabled = true maxretry = 3 findtime = 600 bantime = 3600 filter = dovecot logpath = /var/log/mail.log |
postfix
# vim /etc/fail2ban/jail.d/postfix.conf
最大リトライを3回、探索時間10分(600秒)、遮断時間1時間(3600秒)としています
[dovecot] enabled = true maxretry = 3 findtime = 600 bantime = 3600 filter = postfix logpath = /var/log/mail.log |
設定適用
jail2banを再起動し、設定を反映させます
# systemctl restart jail2ban
# systemctl status jail2ban
動作確認
jail2ban-clientコマンドを利用して動作を確認します
# fail2ban-client status
Status
|- Number of jail: 4
`- Jail list: dovecot, postfix, postfix-flood-attack, sshd
適用した4つのポリシーが出れば完成です。
各ポリシー毎の詳細を見る場合は、fail2ban-client status policyで確認ができます
# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 74
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 0
|- Total banned: 5
`- Banned IP list:
動作結果については、/var/log/fail2ban.logで確認ができます
# cat /var/log/fail2ban.log
failedとなるイベントを発見した際はINFO、ban/unbanなどのアクションの結果はNOTICEとして記載されます
以下はsshの不正試行の記録と対応のサンプルです
2021-05-17 22:39:43,911 fail2ban.filter [51778]: INFO [sshd] Found 168.205.138.186 - 2021-05-17 22:39:43 2021-05-17 22:39:51,923 fail2ban.filter [51778]: INFO [sshd] Found 168.205.138.186 - 2021-05-17 22:39:51 2021-05-17 22:39:59,515 fail2ban.filter [51778]: INFO [sshd] Found 168.205.138.186 - 2021-05-17 22:39:59 2021-05-17 22:39:59,995 fail2ban.actions [51778]: NOTICE [sshd] Ban 168.205.138.186 2021-05-17 23:39:59,079 fail2ban.actions [51778]: NOTICE [sshd] Unban 168.205.138.186 |
banが実施されているタイミングのufwステータスは以下のように見えます
# ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
Anywhere REJECT IN 168.205.138.186
Tip5. Postfix Log Report導入
Postfixのログ解析ツールであるるPflogsummを導入します。
メール受信状況や、各種対応によるreject状況などが確認できます。
pflogsummインストール
Ubuntu20ではパッケージ(apt)があるため、こちらでインストールを行います
# apt install pflogsumm
インストールできましたら、コマンドで動作確認を行います
動作確認
昨日分のログを作成してみます
# pflogsumm -d yesterday /var/log/mail.log
下記がサンプル(抜粋)となります。
# pflogsumm -d yesterday /var/log/mail.log Grand Totals 16 received 553k bytes received |
定期レポート送信設定
cronおよびmuttを利用して、日時でレポートメールを送信します
muttインストール
テキストメーラであるmuttを利用します
# apt install mutt
cronへの登録
cronへの登録は、/var/log/mail.logへのアクセス権があれば、rootユーザでなくとも構いません
# crontab -e
0 16 * * * /usr/sbin/pflogsumm -d yesterday /var/log/mail.log --problems-first --rej-add-from --verbose-msg-detail -q | mutt -s "Postfix log summary" your@email.address
今回は、Postfixの機能とPostgreyやfail2banのセットアップを進めてきました。
SpamAssassinの導入まで書こうと思いましたが、長いので次回以降にまわします