【Mail Server 系列文:第 7 篇】
在前幾篇文章中,我們已完成 Postfix、Dovecot、SpamAssassin、Piler 等重要元件。本篇將介紹 郵件安全鏈的核心中繼系統:Amavis,並整合:
- ClamAV(病毒掃描)
- SpamAssassin(垃圾郵件評分)
- DKIM 簽章
- Postfix inbound/outbound content-filter 流程
- 如何在 Docker 架構中部署 Amavis + ClamAV
本篇非常重要,因為它定義郵件的 安全流向(mail security pipeline)。
1. Amavis 的角色與架構
Amavis(A Mail Virus Scanner)是 Postfix 的內容過濾中繼,負責:
| 功能 | 說明 |
|---|---|
| Anti-Virus | 透過 ClamAV 掃描郵件附件與內容 |
| Anti-Spam | 呼叫 SpamAssassin 計算 spam 分數 |
| DKIM 驗證 | 針對 inbound mail 驗證寄件者 DKIM |
| DKIM 簽章 | 針對 outbound mail 對郵件簽章 |
| Policy | 根據 policy ID 分流不同網域的處理方式 |
| MIME / 解壓縮 | Amavis 會自動解壓 zip、rar、gzip 等檔案 |
2. 郵件在 Amavis 中的流向圖
Inbound(外→內)郵件流向
Internet → Postfix (port 25)
→ smtp-amavis (10024)
→ Amavis:病毒掃描 / SpamAssassin / DKIM 驗證
→ Postfix (10025)
→ Dovecot 投遞(LMTP)
Outbound(內→外)郵件流向
Client(587)→ Postfix submission
→ smtp-amavis (10026)
→ Amavis:SpamAssassin / DKIM 簽章
→ Postfix (10027)
→ Internet(外送)
Inbound(10024)與 Outbound(10026)應分開,因為:
- inbound 要做 DKIM 驗證
- outbound 要做 DKIM 簽章
- outbound 分數較寬鬆,避免誤掛 spam
- inbound 分數嚴格,保護使用者
本篇的設定已精準拆分。
3. Amavis Docker 容器架構
目錄結構:
/opt/docker/mail/amavis/
├── amavis.conf
├── 50-user.conf
├── policies/
├── dkim/
│ └── domain.key
├── log
└── amavis.sh
建立容器 image(以 Debian/Ubuntu 作 base):
docker run -dit --name amavis \
--restart=always \
--network intranet-net \
-e TZ=Asia/Taipei \
-v $PWD:/etc/amavis \
-v $PWD/log:/var/log/amavis \
nuface/amavis:1.0
4. ClamAV 與 Amavis 整合
Amavis 透過 local socket 呼叫 ClamAV:
/var/run/clamav/clamd.ctl
ClamAV 的 Docker 容器建議:
clamd:
image: clamav/clamav:latest
volumes:
- /opt/docker/mail/clamav:/var/lib/clamav
- /opt/docker/mail/clamav/run:/run/clamav
networks:
- intranet-net
Amavis 設定:
@av_scanners = (
['ClamAV-clamd',
\&ask_daemon, ["CONTSCAN {}","\Zclamdsock","/run/clamav/clamd.ctl"],
qr/\bOK$/m, qr/\bFOUND$/m,
qr/^.*?: (.*) FOUND$/m ],
);
5. Amavis + SpamAssassin 整合
Amavis 會自動呼叫 SpamAssassin,不需額外 daemon,只需:
$sa_tag_level_deflt = -999; # 全部加 spam 標頭
$sa_kill_level_deflt = 6.0; # 郵件分數 >= 6 直接標記 spam
$sa_dsn_cutoff_level = 10; # 太高直接退信
同時記得設定:
$spamassassin_tag_headers = 1;
表示要將 SpamAssassin 分數寫入郵件。
6. DKIM — 產生金鑰與設定
產生 DKIM key
以網域:it.demo.tw 為例:
amavisd-new genrsa /opt/docker/mail/amavis/dkim/it.demo.tw.key 2048
DNS TXT 記錄(selector: default):
default._domainkey.it.demo.tw IN TXT "v=DKIM1; k=rsa; p=xxxx"
Amavis 設定 DKIM 簽章
$enable_dkim_signing = 1;
dkim_key('it.demo.tw', 'default', '/etc/amavis/dkim/it.demo.tw.key');
Outbound policy(10026)強制簽章
$policy_bank{'OUTBOUND'} = {
originating => 1,
enable_dkim_signing => 1,
};
7. 內容過濾:Postfix ↔ Amavis 端口分工
Postfix master.cf(Inbound)
smtp inet n - n - - smtpd
-o content_filter=smtp-amavis:[amavis]:10024
Inbound 回投:
10025 inet n - n - - smtpd
-o content_filter=
Outbound(587 → Amavis)
submission inet n - n - - smtpd
-o content_filter=smtp-amavis:[amavis]:10026
Outbound 回投:
10027 inet n - n - - smtpd
-o content_filter=
8. Amavis 重要 Policy 分流
為分開 inbound/outbound 設定:
$inet_socket_port = [10024, 10026];
$policy_bank{'ORIGINATING'} = {
originating => 1,
enable_dkim_signing => 1,
spam_kill_level_maps => [7],
};
Inbound:
$policy_bank{'AMAVIS'} = {
enable_dkim_verification => 1,
};
Outbound:
$policy_bank{'ORIGINATING'} = {
enable_dkim_signing => 1,
allow_disclaimers => 1,
};
9. 日誌、除錯、常用指令
重新載入設定:
docker exec -it amavis amavisd debug
docker exec -it amavis amavisd reload
查看 Amavis log:
tail -f /opt/docker/mail/amavis/log/amavis.log
查看 DKIM 結果:
grep DKIM /opt/docker/mail/amavis/log/amavis.log
測試 SpamAssassin:
spamassassin -D < testmail.eml
10. 測試 Amavis 是否正確運作
(1)病毒檔案測試
下載 EICAR:
curl -O https://secure.eicar.org/eicar_com.txt
寄出即可看到:
FOUND Eicar-Test-Signature
Blocked
(2)SpamAssassin GTUBE 測試
郵件內加入:
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
結果會被標示為 spam。
(3)DKIM 簽章測試
寄到 Gmail:
Gmail header 應看到:
DKIM-Signature: v=1; a=rsa-sha256; d=it.demo.tw; s=default;
Authentication-Results: dkim=pass
結語:Amavis 是郵件安全鏈的中流砥柱
完成本篇後,你的郵件系統具備:
- 高品質的病毒偵測(ClamAV)
- 垃圾郵件分析(SpamAssassin)
- 郵件簽章(DKIM)
- 安全的 inbound / outbound 分流
- 高彈性的 Policy 規則
這部分是整個 Mail Server 架構中最核心的安全組件。