免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6263 | 回复: 4

[Mail] qmail-remote 缺陷造成but_connection_died的补丁 [复制链接]

论坛徽章:
0
发表于 2007-07-25 16:33 |显示全部楼层
最近发现 qmail 发送日志中存在大量的如下的日志记录:

delivery 10277: deferral: Connected_to_xxx.xxx.xxx.xxx_but_connection_died._(#4.4.2)/

经过实际跟踪的结果,发现原来 qmail-remote 投递程序中存在明显的缺陷, 该缺陷
表现为:

如果远程主机 remote 禁止本地连接(qmail 最常见的做法是在 tcpserver 中使用 tcp.smtp.cdb 来
deny 指定的主机), telnet 记录如下:

代码:
[root@home sysconfig]# telnet xxx.xxx.xxx.xxx 25
Trying xxx.xxx.xxx.xxx...
Connected to xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx).
Escape character is '^]'.
Connection closed by foreign host.


从上面跟踪可以得知, 远程主机判断来访的IP后, 随即关闭了连接. 而 qmail-remote 无法正
确识别改种情况, 如果发送的域名地址有多个 MX 记录, 则 qmail 总是试图连接该优先级别的
地址, 而不会自动转向更低一级别的 MX 记录, 从而造成邮件在队列中堆积.

解决方法及补丁:

通过分析 qmail-remote.c 程序发现, qmail-remote 调用了 timeoutconn() 函数,

代码:
  for (i = 0;i < ip.len;++i) if (ip.ix.pref < prefme) {
    if (tcpto(&ip.ix.ip)) continue;
  
    smtpfd = socket(AF_INET,SOCK_STREAM,0);
    if (smtpfd == -1) temp_oserr();
  
    if (timeoutconn(smtpfd,&ip.ix.ip,(unsigned int) port,timeoutconnect) == 0) {
      tcpto_err(&ip.ix.ip,0);
      partner = ip.ix.ip;
#ifdef TLS
      partner_fqdn = ip.ix.fqdn;
#endif
      smtp(); /* does not return */
    }
    tcpto_err(&ip.ix.ip,errno == error_timeout);
    close(smtpfd);
  }


为此, 可在执行前 smtp() 让程序判断 socket 是否内容可读, 考虑到通用性, 在 timeoutconn.c
更改如下:

代码:
  if (FD_ISSET(s,&wfds)) {
    int dummy;
    dummy = sizeof(sin);
    if (getpeername(s,(struct sockaddr *) &sin,&dummy) == -1) {
      read(s,&ch,1);
      return -1;
    }
   ndelay_off(s);
    if (recv(s, &ch, 1, MSG_PEEK) <= 0) return -1; // 此行是增加的
    return 0;
  }


在程序中增加 recv 从 socket 读取一个字符数据, 如果失败, 表示远程端已经断开连接,
直接返回失败 (-1). 由于 recv 设置了 MSG_PEEK 参数, 所以所读的数据不会中缓冲区移除,
从而不会影响后面程序正常的 SMTP 会话.

特别注意,本补丁对在 smtp 会话过程中的中断无效。

原文在:
http://bbs.igenus.org/phpBB2/viewtopic.php?p=8448#8448


[ 本帖最后由 大麻 于 2007-7-25 16:35 编辑 ]

论坛徽章:
0
发表于 2007-07-25 22:53 |显示全部楼层
這個,能不能給做個 patch 文件阿

论坛徽章:
0
发表于 2010-09-15 09:51 |显示全部楼层
请教大麻
  修改后是否需要重新编译qmail?

论坛徽章:
0
发表于 2011-02-18 10:28 |显示全部楼层
lz,你好。最近我也遇到这样的为你。因为对qmail不是很懂,你上面的方法怎么去操作,应用到qmail中呢?

论坛徽章:
0
发表于 2013-09-27 14:21 |显示全部楼层
回复 1# 大麻
加的有问题。。。。当连接到对方服务器,但是对方服务器没有任何回应时,recv 函数没有读到数据会一直阻塞下去。。。。。。肯定阻塞队列。。

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

PostgreSQL中国大会,早鸟票抢购!

PostgreSQL中国大会,早鸟票抢购!
2019年11月29~11月30日,由 PostgreSQL中文社区与ITPUB联合主办的第九届《PostgreSQL 中国技术大会》将在北京隆重召开。PostgreSQL 作为功能最强的的开源关系型数据库之一,得到了越来越多企业的推广和运用,也越来越受到广大技术爱好者的欢迎和重视。这将是 PostgreSQL 的又一次交流盛会。




----------------------------------------

点击报名>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP