owned this note
owned this note
Published
Linked with GitHub
---
tags: NA, Network, NCTU
---
# NA-hw3 Postfix
[HW3 spec](https://nasa.cs.nctu.edu.tw/na/2021/slides/HW3.pdf)
## Create virtual machine
### mail server
os: CentOS 8.3
username: cychen
passwd:
interfaces:
1. enp0s3: Intranet(get IP addr 10.113.40.30 from DHCP)
2. enp0s8: Host-Only(only for ssh)
設置主機名稱:
```
hostname mail.40.nasa
```
修改 `/etc/hosts`:
```
127.0.0.1 localhost
10.113.40.30 mail.40.nasa
10.113.40.30 mail
```
#### 新增使用者:
```
$ useradd -d -g mail -s /sbin/nologin ta
$ useradd -d -g mail -s /sbin/nologin cool-ta
```
```
$ passwd ta
Enter New UNIX password:
Retype New UNIX password:
$ passwd cool-ta
Enter New UNIX password:
Retype New UNIX password:
```
## DHCP Server
Spec 有說明:You are required to redirect any DNS query within .nasa to this DNS server(10.113.0.254),但這句話講的非常的爛。
你在 judge 的時候要和 judge 機器互相送 mail 來測試,judge 機是 54.nasa,意味著你必須要能解析 54.nasa 這個 domain name 的 records,包括 A、MX、SPF⋯⋯,但依照 Hw2 的 DNS Server,你是沒辦法的。所以需要讓 DHCP 在告知你的電腦們 DNS Server 要是 10.113.0.254,之後你去查詢例如 40.nasa,他就會去遞迴的查詢,所以此時你在 Hw2 架設的 DNS Server 是作為 Authoritative DNS Server 用。
作法在 Hw2 有講過了。
## DNS - Add MX Record
你必須要新增 MX record 來告訴別人信件應該要轉發給哪台主機:
```
@ IN MX 10 mail.40.nasa.
```
Spec 強迫我選擇讓它發給 mail.40.nasa. 這個主機,而這裡的 10 意味著 Priority,此值越低表示有越高優先度。接下來我必須要讓 mail.40.nasa 指向到我的 Mail Server:
```
mail IN A 10.113.40.30
```
## Mail Server - Postfix 和 Dovecot
Postfix 負責信件轉發、收件的服務,就是 Mail Server(MTA),負責 SMTP。
Dovecot 專門負責給使用者查詢信件的服務,也就是 Mail Receive Agent(MRA),負責 IMAP。
而在這裡 Dovecot 擔任的角色比 MRA 多一點,就是 Postfix 可以直接使用 Dovecot 的認證模塊。SASL(簡單認證與安全層)的設計把認證機制從程式中分離開,所以我們可以把 Postfix 的認證部分交給其他程式來做,這邊因為 Dovecot 本來就必須要對使用者進行認證才能讓他們檢索郵件,所以就一石二鳥,讓 Postfix 使用 Dovecot 的認證機制。
:::danger
所以 Debug 的時候如果發現 SMTP 無法登入,可能是 Dovecot 爛了。
:::
### 防火牆設定:
你必須允許 SMTP 所需要的 25 port 和 IMAP 所需要的 143 port
先關掉 SELINUX,由於在 Hw2 被他坑了之後,我現在都會先關閉 SELINUX:
```
vim /etc/selinux/config
```
```
SELINUX=disabled
```
再關閉防火牆:
```
systemctl disable firewalld.service
systemctl stop firewalld.service
```
### Postfix 的安裝、設定:
```
$ dnf install postfix
```
:::info
dnf(Dandified Yum),顧名思義就是拿來取代 yum 的,是一套效能比較好的套件管理程式,把他當作 yum 的升級版就好。
:::
```
$ vim /etc/postfix/main.cf
```
修改下面項(在 main.cf 對應項的附近都有比較詳細的參數的參數介紹):
```
myhostname = mail.40.nasa
mydomain = 40.nasa
myorigin = $mydomain
inet_interfaces = all
inet_protocols = all
mydestination = $myhostname, $mydomain, localhost
mynetworks = 10.113.40.0/24, 127.0.0.0/8
```
添加到開機啟動項以及啟動它:
```
systemctl enable postfix
systemctl restart postfix
```
### Dovecot 的安裝:
```
dnf install dovecot
```
讓 Dovecot 為 Postfix SMTP 做 Auth:
```
vim /etc/dovecot/conf.d/10-master.conf
```
```
unix_listener auth-userdb {
#mode = 0666
#user =
#group =
}
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
mode = 0666
}
```
為認證機制做設定:
```
vim /etc/dovecot/conf.d/10-auth.conf
```
```
auth_mechanisms = plain login
```
允許 IMAP 登入:
```
vim /etc/dovecot/dovecot.conf
```
```
protocols = imap
```
還要設置讓 Dovecot 能有讀取 MailBox 的權限:
```
mail_location = mbox:~/mail:INBOX=/var/mail/%u
mail_access_groups=mail
```
:::info
plain 在登入的時候會把帳號和密碼依照特定格式組合成一行,再做 base64 一併傳送。
login 則會在登入的時候分開傳遞帳號的 base64 編碼 和密碼的 base64 編碼。
這邊同時允許這兩種認證方式,實際上大同小異。
[詳見 REF](https://www.samlogic.net/articles/smtp-commands-reference-auth.htm)
:::
### 讓 Postfix 使用 Dovecot 做 Auth
```
vim /etc/postfix/main.cf
```
添加如下:
```
# Dovecot Auth
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous
```
### 設定 Mailbox 的讀寫權限
```
chmod 600 /var/mail/*
```
給 Dovecot 讀取 Mailbox 的權限
```
vim /etc/dovecot/conf.d/10-mail.conf
```
```
mail_location = mbox:~/mail:INBOX=/var/mail/%u
mail_privileged_group = mail
```
添加到開機啟動項以及啟動它:
```
systemctl enable dovecot
systemctl restart dovecot
```
### SSL 設定
首先你要會如何使用 openssl 生成私鑰和憑證:
```
openssl req -newkey rsa:2048 -nodes -sha512 -x509 -days 365 -nodes -out public_cert.pem -keyout private_key.pem
```
這邊的參數都很簡單:
```rsa:2048```:RSA 演算法,金鑰長度為 2048 bits。
```sha512```:選定雜湊演算法來產生憑證。
```nodes```:代表使用時不需要輸入密碼
```x509```:使用 X.509 這個公鑰憑證的格式標準。
#### Postfix SSL 設定:STARTTLS
```
vim /etc/postfix/main.cf
```
追加:
```
smtp_use_tls = yes
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_tls_security_level = may
smtpd_tls_key_file = 私鑰位置
smtpd_tls_cert_file = 憑證位置
smtpd_tls_loglevel = 1
```
#### Dovecot SSL 設定
```
vim /etc/dovecot/conf.d/10-ssl.conf
```
```
ssl = yes
ssl_cert = <證書位置
ssl_key = <私鑰位置
```
:::warning
這個 < 是必要的,我猜測他的意思是在程式啟動的時候從這兩個位置直接讀檔進來。
:::
### 測試 SMTP 寄件和 IMAP 收件
由於有些資料是用 Base64 編碼傳遞的,所以要先知道怎麼編碼解碼
```
$ echo -n "ta" | base64
dGE=
$ echo -n "dGE=" | base64 -d
ta
```
:::danger
這個 -n 代表 echo 不要換行,如果換行了,你的 base64 後的結果就會錯掉(多一個 \n 會被加進去編碼內)
```
$ echo "ta" | base64 | base64 -d | wc -c
3
echo -n "ta" | base64 | base64 -d | wc -c
2
```
```wc -c```:計算輸入了多少個字符。
:::
#### 用 telnet 測試 SMTP:
##### 登入
```
$ telnet mail.40.nasa 25
220 mail.40.nasa ESMTP Postfix
EHLO mail.40.nasa
250-mail.40.nasa
250-PIPELINING
250-SIZE 102400000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING
AUTH LOGIN
334 VXNlcm5hbWU6
dGE=
334 UGFzc3dvcmQ6
K0JIeFd2NUFxM0xxSjcranNuYkIyTFJUMzVZTmNYZEs2QUJXcVJLaGNtOD0=
235 2.7.0 Authentication successful
```
```EHLO mail.40.nasa```:ECHO HELLO,和伺服器說 HELLO 以及你是哪位。
他回傳了:
```
250-mail.40.nasa
250-PIPELINING
250-SIZE 102400000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING
```
```AUTH LOGIN```:告訴他說我現在要登入,然後使用 LOGIN 這種機制,意味著我要分開打帳號與密碼。
伺服器回傳:```334 VXNlcm5hbWU6```,```VXNlcm5hbWU6``` 用 Base64 解碼後是用戶名稱的意思,所以輸入 Base64 後的用戶名稱。 ```334 UGFzc3dvcmQ6``` 告訴我們輸入密碼。
分開輸入後,就得到結果:```235 2.7.0 Authentication successful```。
##### 寄信
```
MAIL FROM: ta@40.nasa
250 2.1.0 Ok
RCPT TO: cychen@40.nasa
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
This is a test mail.
.
250 2.0.0 Ok: queued as 6C7B610DA8E4
```
```MAIL FROM: ta@40.nasa```:寄件者是 `ta@40.nasa`。
```RCPT TO: cychen@40.nasa```:收件者是 `cychen@40.nasa`。
```DATA```:接下來開始是信件內容。
```.```:單獨一行 `.` 代表資料結束了。
```quit```:請求結束連線。
#### 用 telnet 測試 IMAP:
##### 實際使用
```
$ telnet mail.40.nasa 143
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ STARTTLS AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
A01 login ta <plaintext-password>
A01 OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE SNIPPET=FUZZY PREVIEW=FUZZY LITERAL+ NOTIFY SPECIAL-USE] Logged in
A02 list "" *
* LIST (\HasNoChildren) "/" INBOX
A02 OK List completed (0.004 + 0.000 + 0.003 secs).
A03 SELECT INBOX
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permitted.
* 32 EXISTS
* 29 RECENT
* OK [UNSEEN 1] First unseen.
* OK [UIDVALIDITY 1620023446] UIDs valid
* OK [UIDNEXT 33] Predicted next UID
A04 SEARCH ALL
* SEARCH 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
A04 OK Search completed (0.002 + 0.000 + 0.001 secs).
A05 FETCH 32 FULL
* 32 FETCH (FLAGS (\Recent) INTERNALDATE "04-May-2021 17:12:49 -0400" RFC822.SIZE 1828 ENVELOPE ("Tue, 4 May 2021 17:12:30 -0400 (EDT)" {6}
陽交 ((NIL NIL "ta" "40.nasa")) ((NIL NIL "ta" "40.nasa")) ((NIL NIL "ta" "40.nasa")) NIL NIL NIL NIL "<20210504211234.339FB10DA8E4@mail.40.nasa>") BODY ("text" "plain" ("charset" "us-ascii") NIL NIL "7bit" 0 0))
A05 OK Fetch completed (0.101 + 0.000 + 0.100 secs).
A06 LOGOUT
```
##### 純指令:
```
A01 LOGIN ta +BHxWv5Aq3LqJ7+jsnbB2LRT35YNcXdK6ABWqRKhcm8=
A02 LIST "" *
A03 SELECT INBOX
A04 SEARCH ALL
A05 FETCH 32 FULL
A06 LOGOUT
```
##### 指令格式:
```
COMMAND_NAME COMMAND PARAMETER1, ...
```
##### 指令列表:
```LOGIN NAME PASSWORD```:登入某使用者。
```LIST "" *```:列出所有收件箱。
```SELECT INBOX```:選擇收件箱 `INBOX`。
```SEARCH ALL```:列出所有信件。
```FETCH 32 FULL```:下載第 32 號信全部。
```LOGOUT```:登出。
#### 用 openssl 測試 SSL 連線:
```
$ openssl s_client -connect mail.{ID}.nasa:25 -starttls smtp
$ openssl s_client -connect mail.{ID}.nasa:143 -starttls imap
```
建立連線後和 telnet 中的使用方式相同,openssl 會幫你加密解密。
## SPF、DKIM 和 DMARC
先知道 SPF、DKIM 和 DMARC 是什麼: [為郵件系統安全把關,新增 SPF, DKIM 和 DMARC 設定以避免有心人士的釣魚攻擊](https://www.richesinfo.com.tw/index.php/mxmail/mxmail-faq/267-dkim-dmarc)。
這邊設定 **Outgoing Mails** 的 Policy,如果設爛了你的信會被當垃圾信。
:::info
這邊基本上完全參考
[某一篇文章](https://www.linuxbabe.com/mail-server/setting-up-dkim-and-spf)
[另一篇文章](https://blog.tiger-workshop.com/ubuntu-postfix-mail-server-mta-outgoing-spf-dkim-rdns-dmarc/)
他們寫的很好,如果設定不起來可以去看他的。我僅針對 Spec 做了一些調整。
:::
### Mail Server - 安裝、配置 OpenDKIM
OpenDKIM 是一隻很方便的程式,他可以幫我們:
1. 產生 DKIM Record
2. 簽署 Outgoing Mail
3. 檢查 Incoming Mails 的 DKIM(後面再設)
安裝 OpenDKIM:
```
dnf install opendkim opendkim-tools
```
給予 OpenDKIM 的程式權限:
```
gpasswd -a postfix opendkim
```
配置 OpenDKIM
```
vim /etc/opendkim.conf
```
```
# Selects operating modes -> s (sign) and v (verify)
Mode sv
UserID opendkim:opendkim
Socket inet:8891@localhost
Domain 40.nasa
KeyTable /etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts
```
這兩個文件 `KeyTable`、`SigningTable` 是用來管理你對不同 Domain 的 DKIM 資料。
我現在要針對 `40.nasa` 和 `mail.40.nasa` 這兩個 domain name 來生 DKIM 的 Records 和 Key:
```
$ mkdir /etc/opendkim/keys/mail.40.nasa
$ cd /etc/opendkim/keys/mail.40.nasa
$ opendkim-genkey -t -s mail -d mail.40.nasa
$ mkdir /etc/opendkim/keys/40.nasa
$ cd /etc/opendkim/keys/40.nasa
$ opendkim-genkey -t -s mail -d 40.nasa
```
設定 Permissions:
```
chown -R opendkim:opendkim /etc/opendkim
```
修改(若不存在則新增)`/etc/opendkim/KeyTable`:
```
mail._domainkey.40.nasa 40.nasa:mail:/etc/opendkim/keys/40.nasa/mail.private
mail._domainkey.mail.40.nasa mail.40.nasa:mail:/etc/opendkim/keys/mail.40.nasa/mail.private
```
:::warning
這裡的 mail 必須要和上面 `opendkim-genkey` 的 `-s mail` 的參數相同。
:::
修改(若不存在則新增)`/etc/opendkim/SigningTable`:
```
40.nasa mail._domainkey.40.nasa
mail.40.nasa mail._domainkey.mail.40.nasa
```
啟動並且加入開機啟動項:
```
systemctl start opendkim
systemctl enable opendkim
```
### Mail Server - 讓 OpenDKIM 為 Postfix 的信件做簽名
```
vim /etc/postfix/main.cf
```
```
# milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = $smtpd_milters
# DKIM: inet:localhost:8891
```
### DNS - SPF Policy
在 DNS Server 增加此兩條 Records:
```
@ IN TXT "v=spf1 a mx ipv4:10.113.40.30 -all"
mail IN TXT "v=spf1 a mx ipv4:10.113.40.30 -all"
```
意思就是允許我這個 domain name 的 a records、mx records 和 10.113.40.30 這個IP 使用這個 domain name 來寄信,其他全部 REJECT。
### DNS - DKIM Records
```
$ cat /etc/opendkim/keys/*/*.txt
```
會得到
```
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; t=y; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBaohjhJh73YFC6EE9gzPH6MvkFTltrf4ZLs/22AO3Lhhphr18VLeaBxbWdHMDXmfovqDnMIm0jME30c3AG+cuo50vWFWiLUBXY3GTaiRTVxi2LwVSkUZCdHgTR9nFyY9PXG/h4QwINCRHN1wEnorUqBrGBImTpeDbxXi16bVELQIDAQAB" ) ; ----- DKIM key mail for 40.nasa
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; t=y; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzQ+eVqmFI+KBsCaCqqmWDQiyu7RDumA2/7M966tE/iMTKHaZvnyidQAueoVuTad0K812PU9iRqSMvBFpk1Mcz4Lz7YXeQ2Y5UhqSMl3jiJhpRw1Ccr4LZIpeM0spMBAdePDjLUefAQ6nxQS5SIynmafnNPYUzheyevbdM81RyzQIDAQAB" ) ; ----- DKIM key mail for mail.40.nasa
```
我們要修改其中 `mail.40.nasa` 的 DKIM Key Record,滑到行末可以看到,在這裡是下面那一筆。 我們要改成這樣:mail.\_domainkey.mail,因為是 mail.40.nasa 底下的,原因是因為我們並未額外 mail.40.nasa 寫一個 zonefile。
:::danger
沒改你會爛掉。
:::
所以最後變成這樣,放到 DNS Server 上就好了:
```
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; t=y; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBaohjhJh73YFC6EE9gzPH6MvkFTltrf4ZLs/22AO3Lhhphr18VLeaBxbWdHMDXmfovqDnMIm0jME30c3AG+cuo50vWFWiLUBXY3GTaiRTVxi2LwVSkUZCdHgTR9nFyY9PXG/h4QwINCRHN1wEnorUqBrGBImTpeDbxXi16bVELQIDAQAB" ) ; ----- DKIM key mail for 40.nasa
mail._domainkey.mail IN TXT ( "v=DKIM1; k=rsa; t=y; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzQ+eVqmFI+KBsCaCqqmWDQiyu7RDumA2/7M966tE/iMTKHaZvnyidQAueoVuTad0K812PU9iRqSMvBFpk1Mcz4Lz7YXeQ2Y5UhqSMl3jiJhpRw1Ccr4LZIpeM0spMBAdePDjLUefAQ6nxQS5SIynmafnNPYUzheyevbdM81RyzQIDAQAB" ) ; ----- DKIM key mail for mail.40.nasa
```
### DNS - DMARC Policy
DMARC 就是看如果 SPF 或 DKIM 的檢查 REJECT 掉一封信之後,收到這封信的郵件伺服器應該做什麼事情,按照 spec,直接 DROP 掉就好。
```
_dmarc IN TXT "v=DMARC1; p=reject"
_dmarc.mail IN TXT "v=DMARC1; p=reject"
```
### 測試 OpenDKIM 是否有成功的為 Postfix 寄出的郵件簽名
重啟 OpenDKIM 和 Postfix 後,寄一封信給自己,然後查看(可直接用 ```cat /var/mail/user``` 來看):
```
From ta@40.nasa Tue May 4 17:12:49 2021
Return-Path: <ta@40.nasa>
X-Original-To: cychen@40.nasa
Delivered-To: cychen@40.nasa
Received: from localhost (localhost [127.0.0.1])
by mail.40.nasa (Postfix) with ESMTP id 9703C10DA8E5
for <cychen@40.nasa>; Tue, 4 May 2021 17:12:49 -0400 (EDT)
DKIM-Filter: OpenDKIM Filter v2.11.0 mail.40.nasa 9703C10DA8E5
Authentication-Results: mail.40.nasa;
dkim=pass (1024-bit key; unprotected) header.d=40.nasa header.i=@40.nasa header.a=rsa-sha256 header.s=mail header.b=Sgq3za4h
X-Virus-Scanned: amavisd-new at 40.nasa
X-Amavis-Alert: BAD HEADER SECTION, MIME error: error: unexpected end of
header
X-Spam-Flag: NO
X-Spam-Score: 2.093
X-Spam-Level: **
X-Spam-Status: No, score=2.093 tagged_above=2 required=6.2
tests=[ALL_TRUSTED=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1,
DKIM_VALID_AU=-0.1, FSL_BULK_SIG=0.001, MISSING_HEADERS=1.207,
PYZOR_CHECK=1.985] autolearn=no autolearn_force=no
Received: from mail.40.nasa ([127.0.0.1])
by localhost (mail.40.nasa [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id vol_chT6ODyA for <cychen@40.nasa>;
Tue, 4 May 2021 17:12:46 -0400 (EDT)
Received: from mail.40.nasa (localhost [IPv6:::1])
by mail.40.nasa (Postfix) with ESMTPA id 339FB10DA8E4
for <cychen@40.nasa>; Tue, 4 May 2021 17:12:30 -0400 (EDT)
DKIM-Filter: OpenDKIM Filter v2.11.0 mail.40.nasa 339FB10DA8E4
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=40.nasa; s=mail;
t=1620162766; bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
h=Subject:Date:From:From;
b=Sgq3za4hDGbMAnlX44D+NUoQVB4Oxulw3BAvWgEbyVwlt8IEz7sOfGOceOPyvTNn3
/A+IoF0BXYQJUL2uPn6ysPMHdSkH1Wa5bcoKqx/dsxYRdCwk4xtUiTGYf8oL8JOc5V
GVOpdnAtEKFi7bEaYVUvvqRfaGjQJF3l1J/93Rqs=
Subject: 陽交
Message-Id: <20210504211234.339FB10DA8E4@mail.40.nasa>
Date: Tue, 4 May 2021 17:12:30 -0400 (EDT)
From: ta@40.nasa
X-UID: 32
Status: O
```
發現的確是有 DKIM-Signature 這個 header field 的,有成功簽名。
## 進階的 Postfix 設定
### 防止冒名發信(avoid fake user)
修改 `/etc/postfix/main.cf`:
```
smtpd_sender_login_maps = regexp:/etc/postfix/sender_login_map
smtpd_sender_restrictions =
...
reject_sender_login_mismatch
...
```
:::warning
這邊 `smtpd_sender_restrictions` 的 `...` 只是讓你保留原有的資料,不要真的加 `...`。
:::
修改(若不存在新增)`/etc/postfix/sender_login_map`:
```
/^(.+)@(mail\.)?40\.nasa$/ $1
```
這個意思就是:
對於所有符合 `/^(.+)@(mail\.)?40\.nasa$/` 這個 regex pattern 的使用者,我把這個使用者視為 `$1`,而這個 `$1` 就是第一個括號,也就是 `$(.+)$` 所匹配到的內容。
:::info
`.` 在 regex 中代表任意字符,而 `+` 代表前面一個 pattern 出現 1 次及以上。所以 `(.)+` 就是一個可以匹配任意非空字串的正則。
:::
### 防止 Null 使用者(avoid mail from: <Empty>)
我們修改 `/etc/postfix/main.cf`:
```
smtpd_sender_restrictions =
...
check_sender_access hash:/etc/postfix/sender_check
...
```
接著修改 `/etc/postfix/sender_check`:
```
<> REJECT null users are not allowed
```
之後執行指令將文字檔變成資料庫:
```
postmap /etc/postfix/sender_check
```
### 防止 Open Relay
設置 `/etc/postfix/main.cf`:
```
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination
smtpd_sender_restrictions =
...
reject_non_fqdn_sender
reject_unknown_sender_domain
...
```
### Virtual alias
設置 `/etc/postfix/main.cf`:
```
virtual_alias_maps = hash:/etc/postfix/virtual regexp:/etc/postfix/virtual.regexp
```
為 ```/etc/postfix/virtual``` 追加一行: ```NASATA TA```
為 ```/etc/postfix/virtual.regexp``` 追加一行:```/^.+\|([^@]+)@(.+)$/ $1@$2```
```
postmap /etc/postfix/virtual
```
### Sender rewrite
設置 `/etc/postfix/main.cf`:
```
local_header_rewrite_clients = permit_mynetworks permit_sasl_authenticated
sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps
```
追加 `/etc/postfix/sender_canonical_maps` 兩行:
```
/cool-ta@(mail.)?40.nasa/ notcool-TA@40.nasa
/(.+)@(mail.)?40.nasa/ $1@40.nasa
```
## SPF、DKIM 和 DMARC 的 Incoming Check
[參考資料](https://www.linuxbabe.com/redhat/opendmarc-postfix-centos-rhel)
安裝 `opendmarc`: ```dnf install opendmarc```
修改 `/etc/postfix/main.cf`:
```
# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters =
...
inet:127.0.0.1:8893
```
設定 `/etc/opendmarc.conf`:
```
Socket inet:8893@localhost
SoftwareHeader true
SPFIgnoreResults true
SPFSelfValidate true
Syslog true
UMask 777
UserID opendmarc:mail
TrustedAuthservIDs mail.40.nasa
RejectFailures true
RequiredHeaders false
IgnoreAuthenticatedClients true
```
開啟並加入開機啟動項:
```
systemctl enable opendmarc
systemctl start opendmarc
```
## Anti Spam Mail
### Greylisting
Greylisting 假設正常信都是由 Mail Server 寄出, 所以它們都有著重寄的機制。故此機制會先將信件資料記錄後,拒絕收信,期待對方 mail server 重寄此信才要接受它。因為如果用腳本大量發送垃圾信件時,額外儲存被退件的並等一點時間之後再去寄件是不符合成本的,所以在廣發垃圾信的時候,最大收益將不會是重新寄信。因此 Greylisting 能起到不錯的防垃圾信的功效。
安裝 `portgrey`: ```dnf install postgrey```
設定 `portgrey` 的灰名單時間:
```
vim /etc/sysconfig/postgrey
```
```
POSTGREY_OPTS="--delay=30"
```
為 greylist 添加 whitelist:
```
vim /etc/postfix/postgrey_whitelist_clients.local
```
```
40.nasa
mail.40.nasa
```
修改 `/etc/postfix/main.cf`:
```
smtpd_recipient_restrictions =
...
check_policy_service unix:postgrey/socket
...
```
重啟 postgrey 並加入啟動項:
```
systemctl enable postgrey
systemctl restart postgrey
```
### Spam Filtering and Virus Detection
這裡使用了另外兩個工具:`clamav`、`amavis`
```
dnf install install clamav clamav-update amavisd-new clamav-scanner-systemd
```
:::danger
安裝完後需要重新啟動,否則可能會有奇怪的問題。
:::
```
sed -i -e "s/^Example/#Example/" /etc/freshclam.conf
freshclam
```
:::info
實務考量可能要設個 cronjob,定期 `freshclam` 來更新資料庫。
:::
編輯 `/etc/amavisd/amavisd.conf`:
```
$mydomain = '40.nasa';
$myhostname = 'mail.40.nasa';
$sa_spam_subject_tag = '*** SPAM *** ';
$sa_spam_modifies_subj = 1;
$final_virus_destiny = D_PASS;
$final_banned_destiny = D_PASS;
$final_spam_destiny = D_PASS;
$final_bad_header_destiny = D_PASS;
$subject_tag_maps_by_ccat{+CC_VIRUS} = [ '*** SPAM *** ' ];
```
這邊的 `D_PASS` 代表當他偵測到某個事項之後要做的事情,spec 要求我們讓他過,但是要在標題加一個 "*** SPAM ***"。
可以用這個指令檢查 amavisd 的設定檔:
```
amavisd -u amavis -c /etc/amavisd/amavisd.conf debug
```
而後編輯 `/etc/postfix/main.cf`:
```
content_filter=amavis:127.0.0.1:10024
```
再修改 `/etc/postfix/master.cf` 追加此內容:
```
amavis unix - - - - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
127.0.0.1:10025 inet n - - - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
```
啟用並且添加到開機啟動項:
```
systemctl enable clamd@amavisd amavisd spamassassin
systemctl restart clamd@amavisd amavisd spamassassin postfix
```
:::danger
如果你有開啟 SELINUX,可能需要先執行:
```
setsebool -P antivirus_can_scan_system 1
setsebool -P clamd_use_jit on
```
:::
### Outgoing Mail Filter
編輯 `/etc/postfix/main.cf`:
```
header_checks = regexp:/etc/postfix/header_checks
```
修改 `/etc/postfix/header_checks`:
```
/^Subject:.*陽交.*/ REJECT
/^Subject:.*=?UTF-8?B?6Zm95Lqk?=.*/ REJECT
/^Subject:.*6Zm95Lqk.*/ REJECT
/^Subject:.*NCTU.*/ REJECT
```
[參考資料](http://adminkk.blogspot.com/2014/01/postfixheadercheckscheck-httpwww.html)
## Debug
1. 如果這些東西裝不起來,你可能要加入 [milter-manager_repos](https://milter-manager.osdn.jp/reference/install-to-centos.html) 和 [EPEL_repo](https://www.tecmint.com/install-epel-repository-on-centos/)。
2. clamd@amavisd
:::danger
我原本是用 clamd@scanner 來做,但後來失敗了,我改用 amavisd。
但 clamd 一次僅能使用一種服務,所以我很理所當然的 disable/stop 了 scanner,又 enable/start 了 amavisd,但這還沒完。
你還必須要修改:`/usr/lib/systemd/system/clamd\@amavisd.service`:
```
[Service]
ExecStart = /usr/sbin/clamd -c /etc/clamd.d/amavisd.conf
```
這個垃圾 Bug 坑了我好久的時間= =。
[參考資料](https://serverfault.com/questions/842589/error-with-clamd-amavisd-centos-7)
:::