我正在尝试构建一个负载平衡的 SMTP 集群。邮件服务器已经存在并运行 Exim 4。最初,我考虑使用 Nginx 进行负载平衡,但是在测试系统上,所有邮件服务器都将入站连接视为来自负载平衡器 IP,而不是实际的远程发送方 IP,经过大量 Google 搜索后,似乎没有任何方法可以解决这个问题。由于这实际上将邮件集群变成了开放中继,因此它显然无法启动,这很遗憾,因为 Nginx 在其他方面表现良好。
因此,我打算使用 HAProxy,因为我通过进一步的谷歌搜索了解到,它能够传递具有原始源 IP 完整的连接,这样系统中继允许列表和 ACL 就可以正常运行。
然而,按照几个在线示例设置 HAProxy 后,我要么收到“SMTP 同步错误”(以及 500 系列错误,因此邮件会被退回),并且连接立即断开,或者只是连接断开而根本没有 SMTP 消息。
这是正在使用的 haproxy.conf:
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user nobody
group nobody
daemon
stats socket /var/lib/haproxy/stats
defaults
log global
option redispatch
retries 3
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout check 10s
maxconn 3000
listen smtp
bind 0.0.0.0:25
mode tcp
no option http-server-close
balance roundrobin
# option smtpchk HELO smtp-in.example.com
server smtp01 10.0.0.141:25 send-proxy check
server smtp02 10.0.0.143:25 send-proxy check
尽管有 send-proxy 命令,据我所知这是告诉 haproxy 通过源 IP 的方式,但 Exim 日志如下所示:
016-12-26 07:06:48 SMTP 协议同步错误(未等待问候语就发送输入):拒绝来自 H=[10.0.0.150] 输入的连接="PROXY TCP4 10.0.0.150 10.0.0.143 40334 25\r\nHELO smtp-in.example.comr\n"
在这种情况下,.150 是负载平衡器,.143 是 Exim SMTP 服务器。
问题:
事实上,是否可以让 Nginx 将 SMTP 连接显示到邮件服务器,其中源 IP 是真正的远程源 IP,而不是负载均衡器?
或者,这在 HAProxy 中可行吗,如何实现?
在这种情况下,当前生产系统运行 LVS,但是它依赖于共享同一 IP 地址的所有邮件服务器上的负载平衡器和环回接口。新的负载平衡器将是 OpenSUSE 42.2,除其他事项外,如果它检测到网络上已在使用的 IP,它似乎会将其从自身中删除以避免冲突。因此 LVS 在新版本中被淘汰。
我正在考虑的其他解决方案包括完全分离入站和出站 SMTP 流量(目前所有流量都通过同一个负载平衡器运行)、在负载平衡器 IP 地址上安装一个简单的中继(可能是 qmail),配置为仅允许按照标准中继实践识别的范围,并在 MX 记录上使用简单的 DNS 循环将入站 SMTP 直接发送到邮件服务器。但负载平衡解决方案会更优雅。
答案1
我使用了自定义 tcp 检查
backend smtp-back
mode tcp
no option http-server-close
balance roundrobin
tcp-check expect string 220
tcp-check send HELO\ test\r\n
tcp-check expect string 250
tcp-check send QUIT\r\n
tcp-check expect string 221
server mail01 mail01:25 check inter 60s rise 3 fall 3 backup
server mail02 mail02:25 check inter 60s rise 3 fall 3 backup