postfix实践记录
最近在搞postfix. 邮局应该是互联网最早的一代应用,发展至今二三十年,软件和架构都非常成熟,搭建和配置也相当灵活,本文记录一下实践过程中的点滴。
配额管理
用户的配额都是放在数据库中,而邮件系统获取配额记录有两种方式。
方式1:通过postfix的virtual_mailbox_limit_maps指定
virtual_mailbox_limit_maps = mysql:/usr/local/etc/postfix/mysql/mysql-virtual-quota.cf
内容:
hosts = IP
user = DB_USER
password = DB_PASS
dbname = DB_NAME
table = mail_users
query = select quota from mail_users where email='%s'
方式2:通过courier-authlib+courier-maildrop指定。其中authlib用于认证,maildrop用于投递,由postfix调用
编辑courier/authlib/etc/authlib/authmysqlrc:
MYSQL_SERVER mysql.example.com
MYSQL_USERNAME admin
MYSQL_PASSWORD admin
MYSQL_PORT 0
MYSQL_OPT 0
MYSQL_DATABASE mysql
MYSQL_USER_TABLE passwd
MYSQL_CRYPT_PWFIELD crypt
MYSQL_QUOTA_FIELD quota
MYSQL_UID_FIELD uid
MYSQL_GID_FIELD gid
MYSQL_LOGIN_FIELD id
MYSQL_HOME_FIELD home
MYSQL_NAME_FIELD name
各个字段分别与数据库中的相应项对应,认证程序即通过这些字段构造sql向db查询。
在每个邮箱Maildir目录下面,会有一个maildirsize文件,用于存放配额。实际测试证明,当配额调整后,maildirsize不会立刻被重写,只有当用户收发邮件时,触发maildrop程序,才会更新maildirsize.
两种方式有何优劣,待研究。
限速
即限制用户单位时间内的邮件发送量,也是两种方式,均采用第三方软件。
方式1:policyd. 强大的反垃圾邮件过滤器。
安装policyd(本人用的v1.9),在配置文档中设定端口(设定的是10032),导入sql建好数据库表,并指定在postfix的main.cf中挂接policyd插件:
smtpd_end_of_data_restrictions = check_policy_service inet:127.0.0.1:10032 permit
也可以加到smtpd_recipient_restrictions中,区别是smtpd_end_of_data_restrictions是在收到客户端END-OF-DATA命令后调用过滤器(也就是从客户端收完待发的邮件数据后),而smtpd_recipient_restrictions是在收到RCPT TO命令后调用,SMTP交互的过程中,RCPT TO在END-OF-DATA之前,放在END-OF-DATA会消耗更多的带宽和处理时间。这里放在smtpd_end_of_data_restrictions后,我想应该是考虑通过获取更多的邮件头以备调用policyd更复杂的过滤规则。
在policyd的配置中,关于收发限制是以下参数(部分):
# —- SENDER THROTTLE —-
SENDERTHROTTLE=1 是否开启发送限制
SENDERMSGLIMIT=150 单位时间内,用户能发送的邮件数量上限
SENDERQUOTALIMIT=250000000 单位时间内,用户发送发送邮件的总大小上限
SENDERRCPTLIMIT=86400 单位时间内,用户发送邮件的接受者的数量上限
SENDERMSGSIZE=1024000000 能发送的最大邮件字节数
SENDERTIMELIMIT=24h 单位时间# —- RECIPIENT THROTTLE —-
RECIPIENTTHROTTLE=0 是否开启接受限制
RECIPIENTMSGLIMIT=100 单位时间内,用户能接收的邮件数量上限
RECIPIENTTIMELIMIT=24h 单位时间
这些参数基本上是初始设置,也即在创建邮箱账户的时候所insert到db中的值。我们可以通过编程式的手段来直接操作db,对不同邮箱账户或域进行动态调整,非常灵活。
方式2:milter-limit
安装milter-limit,在postfix的main.cf中挂接:
smtpd_milters = unix:/var/run/milter/milter-limit.socket
配置是通过makemap生成:
makemap hash /etc/mail/access.db < /etc/mail/acces
对于管理系统来说,由于发送限制的配额是存放于db中,这种就需要一个定时程序,先从db查询并生成/etc/mail/acces,然后通过makemap生成hash,再重启milter-limit:
/usr/local/etc/rc.d/milter-limit.sh start restart