我今天要來限制一個 Email 帳號一天只能寄 1000 封,超過了就會被擋掉無法再寄

Postfix 官網有提供幾個外掛使用,我拿 postfwd 來使用,postfwd 俗稱 postfix firewall daemon

另一個 policyd 可以參考 http://signalboxes.net/howto/policyd/

以下是 policyd 與 postfwd2 比較表

項目
Policyd v2 (cluebringer)
postfwd2
程式語言 Perl Perl
規則存放 Database FIle
參數調整 設定檔 程式參數
限制信件量 (per user, per domain) V V
ACL V V
Greylisting V V
Check HELO V
Support Amavis V
Check SPF V
WebUI V (沒有帳密驗證)
Date/time based rules V
DNSBL V
IPv6 出現格式錯誤 正常
文件 較為清楚 敘述較為模糊、複雜
安裝方式 RPM、手動 手動
設定 看似簡單,但需操作 DB 看似複雜,但邏輯容易理解
記錄檔 符合 Syslog 標準 符合 Syslog 標準
最後更新日期 2013-10-26 (2.014)
(與前一版幾乎沒有差異)
2013-04-18 (1.35)

 

postfwd 需要的 perl 套件

cpan -i Net::Server::Daemonize
cpan -i Net::Server::Multiplex
cpan -i Net::Server::PreFork
cpan -i Net::DNS
cpan -i IO::Multiplex

再來至 postfwd 下載套件,裡面包含 v1 與 v2 ,我要用 v2 版

解開後放到 /usr/local/postfwd (裡面就有 bin doc etc man plugins sbin tools 等目錄)

編輯 /usr/local/postfwd/bin/postfwd-script.sh,這是啟動檔

# 用 postfwd2
#PFWCMD=/usr/local/postfwd/sbin/postfwd
PFWCMD=/usr/local/postfwd/sbin/postfwd2
# rulesetconfig file 改名
PFWCFG=/etc/postfix/postfwd2.cf
# pidfile 改名
PFWPID=/tmp/postfwd2.pid
# 使用者換成 postfix
PFWUSER=postfix
PFWGROUP=postfix
# port 改成 10045
#PFWPORT=10040
PFWPORT=10045
# --shortlog 拿掉,因為 v2 不支援,加入 --keep_rates --save_rates /tmp/postfwd2.cache,才能有計數器功能,並額外記錄於 syslog
PFWARG="--summary=600 --cache=600 --cache-rbl-timeout=3600 --cleanup-requests=1200 --cleanup-rbls=1800 --cleanup-rates=1200 --keep_rates --save_rates /tmp/postfwd2.cache --logname postfwd2 --facility local0"
# 在 reload 的地方,把 -- reload 改成 --reload

放到 init.d 裡啟動

ln -s /usr/local/postfwd/bin/postfwd-script.sh /etc/init.d/postfwd2

編輯 /etc/postfix/main.cf,整合到 postfix 裡

# 如果有其它參數,這個一定要放在最前面
smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10045

編輯 /etc/postfix/postfwd2.cf,這是放 rules 的地方,每設定一次就要 restart postfwd2

# 每天只允許同一寄件者只能寄 1000 封,多了就阻擋
# sender 是固定參數
# 1000 就是 1000 封
# 86400 就是 一天的時間 (秒)
# 後面的字串就是退信訊息
# Reject sender sends over 1000 per day
id=R01; action=rate(sender/1000/86400/REJECT sender $$sender exceeded limit of 1000 per day)
# 每天只允許同一來源 IP 只能寄 2000 封
# Reject client sends over 2000 per day
id=R02; action=rate(client_address/2000/86400/REJECT client $$client_address exceeded limit of 2000 per day)

編輯 /etc/rsyslog.conf,我把 log 額外放,預設是會放在 maillog 裡

*.info;mail.none;authpriv.none;cron.none;local0.none /var/log/messages
local0.* /var/log/postfwd2
service rsyslog restart

編輯 /etc/logrotate.d/syslog,把 log 檔作輪替

# 加入
/var/log/postfwd2

秀出定義在 conf 裡的 rule

/usr/local/postfwd/sbin/postfwd2 -f /etc/postfix/postfwd2.cf -C

查看計算結果

/usr/local/postfwd/sbin/postfwd2 --dumpcache
%rate_cache -> %client_address=127.0.0.1 -> @list -> 'R02+2000_86400'
%rate_cache -> %client_address=127.0.0.1 -> %R02+2000_86400 -> @action -> 'REJECT client 127.0.0.1 exceeded limit of 2000 per day'
%rate_cache -> %client_address=127.0.0.1 -> %R02+2000_86400 -> @count -> '1'
%rate_cache -> %client_address=127.0.0.1 -> %R02+2000_86400 -> @maxcount -> '2000'
%rate_cache -> %client_address=127.0.0.1 -> %R02+2000_86400 -> @rule -> 'R02'
%rate_cache -> %client_address=127.0.0.1 -> %R02+2000_86400 -> @time -> '1391677750.95566'
%rate_cache -> %client_address=127.0.0.1 -> %R02+2000_86400 -> @ttl -> '86400'
%rate_cache -> %client_address=127.0.0.1 -> %R02+2000_86400 -> @type -> 'rate'
%rate_cache -> %client_address=127.0.0.1 -> %R02+2000_86400 -> @until -> '1391764150.95566'
%rate_cache -> %sender=cross@ssorc.tw -> @list -> 'R01+10_86400'
%rate_cache -> %sender=cross@ssorc.tw -> %R01+10_86400 -> @action -> 'REJECT sender cross@ssorc.tw exceeded limit of 1000 per day'
%rate_cache -> %sender=cross@ssorc.tw -> %R01+10_86400 -> @count -> '1'
%rate_cache -> %sender=cross@ssorc.tw -> %R01+10_86400 -> @maxcount -> '1000'
%rate_cache -> %sender=cross@ssorc.tw -> %R01+10_86400 -> @rule -> 'R01'
%rate_cache -> %sender=cross@ssorc.tw -> %R01+10_86400 -> @time -> '1391677750.95566'
%rate_cache -> %sender=cross@ssorc.tw -> %R01+10_86400 -> @ttl -> '86400'
%rate_cache -> %sender=cross@ssorc.tw -> %R01+10_86400 -> @type -> 'rate'
%rate_cache -> %sender=cross@ssorc.tw -> %R01+10_86400 -> @until -> '1391764150.95566'

刪除計數結果,重新計算

/usr/local/postfwd/sbin/postfwd2 --delrate="sender=cross@ssorc.tw"
rate cache item 'sender=cross@ssorc.tw' removed

以上是清 sender,下面的就是清來源 IP 歸零

/usr/local/postfwd/sbin/postfwd2 --delrate="client_address=127.0.0.1"
rate cache item 'client_address=127.0.0.1' removed

如果成功外阻擋的話,maillog 會看到

Feb 6 16:51:35 ssorc postfix/smtpd[24633]: NOQUEUE: reject: RCPT from localhost[127.0.0.1]: 554 5.7.1 <cross@ssorc.tw>: Recipient address rejected: sender cross@ssorc.tw exceeded limit of 1000 per day; from=<cross@ssorc.tw> to=<cross@ssorc.tw> proto=ESMTP helo=<ssorc.tw>

至於 postfix 要怎麼新增 virtual domain

編輯 /etc/postfix/main.cf

smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10045,permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
virtual_mailbox_domains = ssorc.tw
virtual_mailbox_maps = hash:/etc/postfix/virtual_mailbox_maps
virtual_mailbox_base = /var/vmail
virtual_uid_maps = static:1000
virtual_gid_maps = static:1000

編輯 /etc/postfix/virtual_mailbox_maps

cross@ssorc.tw ssorc.tw/cross/Maildir/

接著作完以下

postmap /etc/postfix/virtual_mailbox_maps
useradd -u 1000 -d /var/vmail -s /sbin/nologin vuser
mkdir /var/vmail/ssorc.tw/
chown -R vuser.vuser /var/vmail

postfwd 提供一個流程圖 可以看一下了解運作方式

postfwd workflow 流程圖

其它的限制也可以參考 postfwd rate limit examples

我上面的測試是針對所有 domain 的,但假如你要針對某個也是可以的

像它範例有提到 client_name=unknown 就針對來源是未知的

收件者是某某某 recipient_domain=XXX.tw

除了針對 sender 與 client_address 也可以針對 收件者名稱

id=R03; action=rate(recipient/20/86400/REJECT recipient $$recipient exceeded limit of 20 per day)

也可以針對信件大小 (不過我試不出來,從 cache 裡看不到相關資訊)

id=R04; action=size(recipient/2048000/86400/REJECT only allow 2mb per day)

 

Related posts 相關文章
postfix 怎麼記錄信件主旨於 maillog 中
More...
讓 Plesk 的 Postfix 使用 Domain Key、SPF
More...
Postfix 如何讓某個帳號跑另一個 IP 寄信出去
More...
Windows 作業系統最大支援幾 G 的記憶體
More...

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。