ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Postfix只发不收告警邮件服务器搭建:SASL认证与LDAP统一认证实战

Postfix只发不收告警邮件服务器搭建:SASL认证与LDAP统一认证实战 接手过几套内部监控系统之后你会发现告警邮件这件事远比想象中麻烦。Zabbix和Prometheus都在跑告警渠道却靠团队个人邮箱往外发。公网邮箱反垃圾策略一年比一年严自动触发的告警经常被丢进垃圾箱邮箱密码散落在各个脚本里换个人就得改一遍最头疼的是没有追溯能力谁在什么时候改过发送配置完全没记录。所以后来很多团队都会走同一条路自己搭一台postfix只发不收专门跑监控告警。这个方案的关键就三个词发送、认证、可控。这篇文章围绕标题里的两个核心点展开——只发不收和用户认证。我会把为什么只发不收、怎么做到只发不收、SASL认证怎么落地、认证账号体系怎么选包括时下热门的LDAP统一认证方向一次讲清楚最后附上监控系统接入的实操配置和排障路径。适合正在搭建或维护公司内部告警通道的运维、SRE和DevOps同学参考。1. 只发不收的定位告警邮件该有的样子1.1 为什么不能用个人邮箱发监控告警很多人第一反应是直接用公司邮箱账号发告警不就行了短期看确实行长期看全是坑。公网邮箱服务商对自动登录、频繁发送、异地IP登录都有风控。告警系统一旦拉起一批故障通知很容易触发频率限制轻则进垃圾箱重则账号被临时冻结。而且告警脚本里必然要存账号密码明文写在配置文件里是常态这让邮箱账号的暴露面变得非常大。还有人员变动问题发告警的邮箱绑定了某个离职员工的账号一旦被回收整个监控系统的通知链就断了。自己搭一台只发不收的postfix相当于把告警通道从个人行为变成基础设施。发送账号、认证方式、允许来源、日志留存全部由自己控制不依赖任何外部邮箱策略也不怕个人账号变动影响监控链路。1.2 只发不收在邮件架构里意味着什么说只发不收不是简单不装收信软件而是要在发送链路的每个环节都做减法不监听公网25端口对外收信不做外部邮件的接收节点。不提供POP3/IMAP服务用户没有收信入口。本地域不接收投递mydestination清空别人往这台服务器发信会被拒收。不做开放中继只允许认证用户或可信内网IP发信。在这个架构里postfix扮演的是一个纯MTA的角色负责把本机或内网监控系统生产的邮件投递到目标邮箱服务器。它不关心有没有人往里写信只关心往外发的信能不能正确投递、认证是否通过。1.3 和公司正式邮件系统的边界划分一台只发不收的告警服务器和公司正式的企业邮件系统是两个完全不同的东西。正式邮件系统有完整账户体系、webmail、通讯录、归档、反垃圾网关而告警postfix只需要一个瘦身的投递通道。这就引出标题里第二个关键词用户认证。虽然只发不收但认证不能省。原因很简单哪怕只监听内网只要机器上有对外可达的端口就有被扫描和利用的风险。没有认证的postfix就是一个开放中继垃圾邮件发送者一旦发现它就会利用它的投递能力向外狂发垃圾信到时候服务器的IP会进入各大邮件服务商的黑名单连自己正常发告警都会被挡。所以认证不是给管理员添麻烦而是保护这条唯一出口的必要手段。2. 基础安装与关键参数把postfix调成单向发信通道2.1 环境准备我以Debian/Ubuntu系为例RHEL系的差异点在关键地方会单独说明。首先是最小化安装apt update apt install -y postfix mailutils安装过程中会弹出postfix配置类型选择这里可以直接选No configuration后面我们完全用自定义配置。安装完先看一下主配置文件的初始状态确认postfix版本postconf mail_version顺便规划一下主机名和域名。比如告警服务器主机名是alert-smtp规划的域名是alert.example.com。这个域名一般用内部DNS解析即可不建议和服务器的外网域名混用。2.2 main.cf里的关键参数核心是不接收安装完成后编辑/etc/postfix/main.cf把默认配置里跟接收相关的项目全部拿掉。下面这份配置是我在多个环境里调整过的版本直接落地基本可用# 基础标识 myhostname alert-smtp.example.com myorigin $myhostname # 只监听本机和内网可信网段不对外服务 inet_interfaces 127.0.0.1, 192.168.10.20 # 不接收任何本地域邮件 mydestination # 可信内网范围 mynetworks 127.0.0.0/8, 192.168.10.0/24 # 限制投递大小 message_size_limit 10240000 # 关闭Vrfy命令减少信息泄露 disable_vrfy_command yes在这个配置里最核心的就是mydestination 这一行。默认配置里会带上$myhostname和localhost意味着postfix会接收发给这些域名/主机名的邮件并投递到本地邮箱。把它清空后别人往这台机器发信postfix找不到对应投递域直接返回550。这就是不收的第一道闸门。inet_interfaces指定监听地址如果告警服务器只在本机跑监控工具甚至可以只监听127.0.0.1让postfix完全不出现在网络上。如果有内部其他服务器要远程用SMTP发信就监听内网IP但要配合后面的认证配置来保证安全。mynetworks这段是内网信任区。在这个地址段内的来源IP不需要认证就能发信。如果你的监控服务器和postfix不在同一网段记得把对应网段加进去否则Zabbix或Alertmanager发信时会被拒绝。2.3 让配置生效并验证拒收改完配置先做语法检查postfix check没有输出就是没问题。然后重载systemctl restart postfix验证监听端口ss -lntp | grep 25接着验证外部投递是否被拒。找一台非信任网段的机器尝试连接25端口往里发信telnet alert-smtp.example.com 25如果监听地址是内网IP外部机器根本连不上如果连上了比如同一内网网段但不在mynetworks里会看到postfix返回550的拒收响应。日志里也会出现类似这样的记录NOQUEUE: reject: RCPT from [192.168.20.10]: 550 5.1.1 testalert.example.com: Recipient address rejected: User unknown in local recipient table出现User unknown in local recipient table说明不收已经生效了。这里有个细节值得注意只发不收的服务器本地用户表是空的所以任何发到本域的邮件都会被拒绝这是预期行为不是故障。2.4 加固收尾除了上面的核心配置我一般还会顺手做三件事限制连接频率降低被扫的风险。在main.cf里加smtpd_client_connection_rate_limit 10 smtpd_client_message_rate_limit 20开启postfix自带的连接级日志方便回溯smtpd_verbose yes确认/etc/aliases里没有意外配置特别是root别名不要指向外部邮箱避免本地误投递。这些配置对单纯的告警服务器来说完全够用。3. SASL用户认证从裸奔中继到强制校验3.1 没有认证的postfix有多危险在第2章的配置里mynetworks内的机器可以直接发信不需要认证。但如果监听的内网IP暴露给了更大的网段或者公司网络环境里有安全短板垃圾邮件发送者就可能在你的服务器上建立中继。一旦IP进了各类反垃圾黑名单你的正常告警邮件也会被目标邮箱服务器拒收整个监控链路直接瘫痪。所以认证是必选项。Postfix本身不做用户校验它通过SASL框架对接认证后端。SASLSimple Authentication and Security Layer是一套认证框架postfix只负责把客户端的认证请求交给SASL层去验证并根据验证结果决定放行或拒绝。3.2 选Cyrus SASL还是Dovecot SASL这是配置认证时碰到的第一个选择题。Postfix兼容两套SASL实现它们的差异我直接整理成表。对比项Cyrus SASLsaslauthdDovecot SASL认证后端PAM系统用户、LDAP等passwd-file、SQL、LDAP等适用场景有系统账号或想对接LDAP做统一认证想用虚拟账号不想创建系统用户配置复杂度低改几个文件就能跑中需要配置dovecot的多个模块对只发不收场景的适配很合适认证开销小也合适但多装了一个dovecot密码存储依赖系统的shadow/ldap密码文件或数据库可自定义对于监控告警这种用途我的建议很直接如果你打算用系统用户做账号选Cyrus SASL如果你已经有一套用户数据库比如专门维护虚拟账号的LDAP或MySQL选Dovecot SASL对接更方便。下面的配置以Cyrus SASL为例因为本文场景最常用的是它。3.3 Cyrus SASL配置从安装到跑通安装必要组件apt install -y sasl2-bin libsasl2-modules先启动saslauthd并把它设为开机自启systemctl enable saslauthd systemctl start saslauthdDebian/Ubuntu的saslauthd默认用PAM方式认证也就是直接验证系统用户。编辑/etc/default/saslauthdSTARTyes MECHANISMSpam # 如果后续对接LDAP改成 ldap 并配置 /etc/saslauthd.conf MECH_OPTIONS创建系统用户作为告警发信账号useradd -r -s /usr/sbin/nologin alert echo alert:YourStrongPassword | chpasswd passwd -l root # 保险起见锁定其他不相关账号不是必需步骤这里只是提醒别乱锁系统账号注意不需要给这个用户设置正常的登录shell它唯一的用途就是SASL认证。/usr/sbin/nologin完全可以。接下来配置postfix的SASL参数。编辑/etc/postfix/main.cf追加# SASL认证 smtpd_sasl_auth_enable yes smtpd_sasl_type cyrus smtpd_sasl_path smtpd smtpd_sasl_security_options noanonymous broken_sasl_auth_clients yes # 限制规则可信内网直接放行其他来源必须认证 smtpd_relay_restrictions permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination # 在25端口也启用认证很多老客户端默认走25 smtpd_recipient_restrictions permit_mynetworks, permit_sasl_authenticated, reject在/etc/postfix/sasl/smtpd.conf里写pwcheck_method: saslauthd mech_list: plain login log_level: 7这里log_level: 7是调试阶段用的方便看认证日志生产环境建议改回1。然后重启服务systemctl restart postfix systemctl restart saslauthd用saslauthd自带工具做认证测试testsaslauthd -u alert -p YourStrongPassword输出0: OK Success.说明saslauthd那边已经通了。3.4 用SMTP客户端做完整发信认证测试saslauthd通不代表postfix链路通还要用真实SMTP会话验证。用swaks最方便apt install -y swaks swaks --to opsexample.com --from alertexample.com \ --server 127.0.0.1:587 --auth LOGIN --auth-user alert \ --auth-password YourStrongPassword \ --header Subject: postfix auth test --body test from alert-smtp如果没有587监听先在main.cf里启用submission端口port 587。因为很多公网邮件服务商优先信任587提交的邮件25端口的投诉率高。在/etc/postfix/master.cf里确认这几行是启用的submission inet n - y - - smtpd -o syslog_namepostfix/submission -o smtpd_tls_security_levelencrypt -o smtpd_sasl_auth_enableyes -o smtpd_relay_restrictionspermit_sasl_authenticated,reject如果上面的swaks命令返回类似250 2.0.0 Ok: queued as XXXXX恭喜认证和发信链路已经打通。如果返回认证失败优先看saslauthd是不是没起来或者系统用户密码不对。4. 认证账号体系选型本机用户、LDAP还是虚拟账号4.1 三种方案该怎么挑认证是通了但账号从哪来是另一个值得提前想清楚的问题。我经常看到有团队用系统用户当告警账号用了一两年后来要接入新的监控系统、要协调离职入职、要分权限系统账户管理就开始难受了。下面这个表格是我在方案评审时常用的对照方案优点缺点适合规模本机系统用户PAM配置最简单依赖少每台机器独立管理不好扩展1-3台监控系统账号就几个LDAP/AD统一认证账号集中管理与公司身份体系打通支持统一密码策略要额外维护LDAP配置复杂度高一些已有统一认证体系的团队虚拟账号数据库Dovecot/Dovecot SQL账号独立于操作系统可造大量按用途区分的账号引入dovecot架构更重需要很多发信账号或对接自研系统对于只发不收的告警服务器来说账号数量通常非常有限——告警、监控、批处理加起来不会超过十个。但热门搜索词里出现了LDAP统一用户认证和单点登录说明很多人的实际场景是公司已经有统一账号体系希望所有系统的认证都收口到LDAP而不是每台机器各搞一套账密。这个诉求很合理下面单独给一套对接LDAP的配置方案。4.2 对接LDAPsaslauthd的ldap后端配置saslauthd对接LDAP的原理很简单客户端把用户名密码提交给postfixpostfix把认证请求交给saslauthdsaslauthd用这个账密去LDAP上做一次bind操作绑定成功就是认证通过。先改saslauthd的认证机制# /etc/default/saslauthd 修改 MECHANISMSldap然后编辑/etc/saslauthd.confldap_servers: ldap://ldap.example.com:389 ldap_search_base: dcexample,dccom ldap_filter: ((uid%u)(objectClassposixAccount)) ldap_bind_dn: cnadmin,dcexample,dccom ldap_password: YourBindPassword ldap_timeout: 5 ldap_force_auto_uri: no这里的ldap_filter很关键需要根据你LDAP里的账户属性来定。如果用uid字段做登录名就用上面的写法如果用的是mail字段就改成(mail%u)如果账号分布在多个OU下search_base可以写深一点。重启服务并测试systemctl restart saslauthd testsaslauthd -u alice -p password123如果返回0: OK Success.说明LDAP认证已经通了。此时任何LDAP里的用户都可以用他自己的账密来通过postfix认证。你还可以让postfix只接受特定group的人发信配置方式是在saslauthd之外再加一层check_sasl_access限制比如建一个哈希表只放行指定用户名。4.3 单点登录视角下的建议从单点登录的角度看接入LDAP确实让告警服务器的账号管理和公司统一身份体系对齐了新员工开通LDAP账号立刻能用统一的密码发信离职员工账号一冻结postfix的认证自然也就失效了不需要单独去每台机器上清理账号。这对规模化运维是一个不小的优势。但这里我要泼一点冷水如果你们团队没有专门的LDAP维护人员只是两三个人的小运维组单纯为了告警还要维护一套LDAP性价比其实不高。本机账号方案可能才是更务实的做法。技术选型不是越复杂越好是要匹配你的实际规模。方案的价值在于解决问题不在于用了多新的技术。5. 监控告警接入Zabbix与Alertmanager的实战配置5.1 发信工具的选择postfix环境起来之后真正生产环境里的使用方式是多种多样的。有人直接用命令行的mail命令从服务器发信有人用脚本调用smtplib走587端口加密认证有人让Zabbix或Alertmanager直接对接SMTP服务。根据我的经验最稳妥的是统一走submission587端口加认证这样不管从哪台机器发信都经过身份校验审计日志也统一。5.2 Zabbix的SMTP媒体类型配置Zabbix从5.0版本开始内置了SMTP媒体类型配置非常简单打开管理 - 报警媒介类型 - Email。SMTP服务器填alert-smtp.example.com。SMTP服务器端口填587。勾选SSL verify peer和SSL verify host按实际TLS情况来如果TLS证书是自签的需要关闭这两项安全性和易用性之间要有取舍。SMTP HELO填alert-smtp.example.com。认证方式选用户名和密码用户名填alert密码填对应密码。发件人地址填alertexample.com。在动作里关联用户和告警级别就可以发起告警邮件了。5.3 Alertmanager接入Prometheus生态的Alertmanager通过email_configs发信配置更直接route: group_by: [alertname] receiver: email-ops receivers: - name: email-ops email_configs: - to: opsexample.com from: alertexample.com smarthost: alert-smtp.example.com:587 auth_username: alert auth_password: YourStrongPassword require_tls: false headers: subject: {{ template email.default.subject . }}这里的smarthost就是我们的postfix地址。要求告警邮件送达率高from地址的域名要真实存在并且最好有对应的SPF记录。这里多说一句监控告警邮件虽然是内部系统生成但目标邮箱可能是QQ邮箱、网易邮箱或企业微信邮箱这些服务商对发件域名都有校验from域名要有SPF和DKIM记录否则大概率进垃圾箱。Postfix本身不负责SPF/DKIM它们属于DNS侧配置可以在DNS服务商的解析记录里加一个SPF TXT记录指向允许发送该域名的服务器或IP。5.4 一个通用的测试脚本无论用Zabbix还是Alertmanager上线前都应该做一个独立的发信测试。我一般用一个Python脚本直接走587端口这样能精确控制头和认证细节import smtplib from email.mime.text import MIMEText msg MIMEText(监控告警测试邮件, plain, utf-8) msg[Subject] Alert Test msg[From] alertexample.com msg[To] opsexample.com server smtplib.SMTP(alert-smtp.example.com, 587) server.starttls() server.login(alert, YourStrongPassword) server.sendmail(alertexample.com, [opsexample.com], msg.as_string()) server.quit()这段脚本可以作为监控系统发信功能的前置校验。如果它通了Zabbix或Alertmanager的配置问题就只可能在它们自身。6. 高频故障与排查链路认证失败和拒收问题定位6.1 认证失败的三种表现SASL认证出问题日志里的表现五花八门。我根据经验把最常遇到的几种归了一下类第一种saslauthd服务没起来。postfix日志里会出现sasl_cyrus: error: SASL service not started之类的提示。这时候需要systemctl status saslauthd确认启动状态。第二种系统用户密码错误。postfix日志会记录SASL authentication failure: Password verification failedsaslauthd日志里会看到auth failure。这种情况先用testsaslauthd确认到底是密码问题还是saslauthd本身的问题。第三种认证机制不匹配。客户端请求PLAIN但smtpd.conf里只启用了LOGIN或者反过来。日志表现为SASL authentication failure: no mechanism available。解决办法是在mech_list里同时写上plain login。6.2 拒收和中继问题的定位表除了认证失败发不出去是更大的故障。下面是一个快速定位表现象可能原因定位方式554 5.7.1 Relay access denied来源IP不在mynetworks且未通过认证在发信端加认证或确认mynetworks配置550 5.1.1 Recipient address rejected对方域名不是postfix的投递目标确认目标邮箱地址拼写或postfix的relay配置454 4.7.0 Temporary authentication failuresaslauthd没起来或LDAP不可达检查saslauthd进程和/var/log/auth.log451 4.3.0 System storage error磁盘满或邮件队列异常df -hpostqueue -p查看队列25端口连接超时防火墙拦截或inet_interfaces未包含该网卡iptables -Lss -lntp确认监听6.3 完整的排查链路遇到问题我习惯按下面这个顺序来排查第一步看日志。Debian/Ubuntu看/var/log/mail.logRHEL系看/var/log/maillog。重点看包含sasl、reject、fatal的行。如果日志一开始没有详细信息把/etc/postfix/main.cf里的smtpd_verbose yes打开再重试一次发信。第二步用postfix check和postconf -n做静态检查。看配置里是否有不合法的参数也确认自己期望的改动是否真的生效了。很多人改了main.cf但没执行postfix reload这是最常见的低级错误。第三步用swaks分别走25和587端口做对比测试。如果25能发而587不能基本可以锁定是submission的配置块没有正确生效回到master.cf检查。第四步检查队列。postqueue -p如果看到队列里堆积了大量邮件用postcat -q 队列ID查看具体的投递错误比如目标邮件服务器超时、SPF校验被拒等。6.4 日志中常见的认证相关关键词最后附一些日志关键词看到它们基本能对应到具体问题SASL authentication failure # 认证密码不匹配或机制不匹配 SASL service not started # saslauthd进程未运行 warning: SASL authentication problem: unsupported mechanism Relay access denied # 未认证或不在信任网段 NOQUEUE: reject # 投递阶段被拒 statussent (250 2.0.0 Ok) # 发送成功出现在外发时排查认证问题时一个很容易被忽视的点是时间同步。如果postfix所在服务器和saslauthd或LDAP服务器的系统时间偏差过大某些带时间戳的认证交换会失败现象表现为时好时坏。所以排查前先把chronyc tracking或timedatectl看一遍排除时钟问题再往深挖。从我实际维护这套系统的经验看一台只发不收的postfix真正需要稳定跑起来核心就是一个清晰的认证链路加一个能看到异常的日志观察习惯。只要配置干净、账号边界清晰、日志有留存这套告警通道可以很安静地运行很多年。后面如果再接入新的监控系统无非是多配一个账号、多填几行SMTP参数的事。遇到发不出去的时候回来翻一下第6章的定位表大多数问题都能在几分钟内定位到是网络、认证还是配置的问题。这就是搭一套可控的告警基础设施带给你最大的确定性。
返回列表