ChinaUnix首页 > 精华文章 > Mail服务器 > 正文

[保留] qmail-remote 缺陷造成but_connection_died的补丁


http://www.chinaunix.net 作者:大麻  发表于:2007-07-25 22:53:31
发表评论】 【查看原文】 【Mail服务器讨论区】【关闭

最近发现 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); 
[color=red]    if (recv(s, &ch, 1, MSG_PEEK) <= 0) return -1; // 此行是增加的 
[/color]    return 0; 
  } 


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

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

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


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



 alvis 回复于:2007-07-25 22:53:31

這個,能不能給做個 patch 文件阿




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=967198
转载请注明作者名及原文出处