https://ssorc.tw/4296
我今天要來限制一個 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 提供一個流程圖 可以看一下了解運作方式
http://postfwd.org/postfwd-ARCH.png
其它的限制也可以參考 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)