歡迎您光臨本站 註冊首頁

qmail-remote 缺陷造成but_connection_died的補丁

←手機掃碼閱讀     火星人 @ 2014-03-04 , reply:0

qmail-remote 缺陷造成but_connection_died的補丁

最近發現 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 記錄如下:

代碼:
# 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 編輯 ]
《解決方案》

這個,能不能給做個 patch 文件阿
《解決方案》

請教大麻
  修改後是否需要重新編譯qmail?
《解決方案》

lz,你好。最近我也遇到這樣的為你。因為對qmail不是很懂,你上面的方法怎麼去操作,應用到qmail中呢?
《解決方案》

回復 1# 大麻
加的有問題。。。。當連接到對方伺服器,但是對方伺服器沒有任何回應時,recv 函數沒有讀到數據會一直阻塞下去。。。。。。肯定阻塞隊列。。

   

[火星人 ] qmail-remote 缺陷造成but_connection_died的補丁已經有412次圍觀

http://coctec.com/docs/service/show-post-11102.html