1. 程式人生 > >系統技術非業餘研究 » TCP連結主動關閉不發fin包奇怪行為分析

系統技術非業餘研究 » TCP連結主動關閉不發fin包奇怪行為分析

問題描述:
多隆同學在做網路框架的時候,發現一條tcp連結在close的時候,對端會收到econnrest,而不是正常的fin包. 通過抓包發現close系統呼叫的時候,我端發出rst報文, 而不是正常的fin。這個問題比較有意思,我們來演示下:

$ erl
Erlang R14B03 (erts-5.8.4)  [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.4  (abort with ^G)
1> {ok,Sock} = gen_tcp:connect("baidu.com", 80, [{active,false}]).
{ok,#Port<0.582>}
2> gen_tcp:send(Sock, "GET / HTTP/1.1\r\n\r\n").
ok
3> gen_tcp:close(Sock).
ok

我們往baidu的首頁發了個http請求,百度會給我們迴應報文的,我們send完立即呼叫close.

然後我們在另外一個終端開tcpdump抓包確認:

$ sudo tcpdump port 80 -i bond0 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on bond0, link-type EN10MB (Ethernet), capture size 96 bytes
17:22:38.246507 IP my031089.sqa.cm4.tbsite.net.19500 > 220.181.111.86.http: S 2228211568:2228211568(0) win 5840 <mss 1460,sackOK,timestamp 2607833238 0,nop,wscale 7>
17:22:38.284602 IP 220.181.111.86.http > my031089.sqa.cm4.tbsite.net.19500: S 3250338304:3250338304(0) ack 2228211569 win 8190 <mss 1436>
17:22:38.284624 IP my031089.sqa.cm4.tbsite.net.19500 > 220.181.111.86.http: . ack 1 win 5840
17:22:52.748468 IP my031089.sqa.cm4.tbsite.net.19500 > 220.181.111.86.http: P 1:19(18) ack 1 win 5840
17:22:52.786855 IP 220.181.111.86.http > my031089.sqa.cm4.tbsite.net.19500: . ack 19 win 5840
17:22:52.787194 IP 220.181.111.86.http > my031089.sqa.cm4.tbsite.net.19500: P 1:179(178) ack 19 win 5840
17:22:52.787203 IP my031089.sqa.cm4.tbsite.net.19500 > 220.181.111.86.http: . ack 179 win 6432
17:22:52.787209 IP 220.181.111.86.http > my031089.sqa.cm4.tbsite.net.19500: P 179:486(307) ack 19 win 5840
17:22:52.787214 IP my031089.sqa.cm4.tbsite.net.19500 > 220.181.111.86.http: . ack 486 win 7504
17:23:01.564358 IP my031089.sqa.cm4.tbsite.net.19500 > 220.181.111.86.http: R 19:19(0) ack 486 win 7504
...

我們可以清楚的看到 R 19:19(0) ack 486 win 7504,發了個rst包,通過strace系統呼叫也確認erlang確實呼叫了close系統呼叫。
那為什麼呢? @淘寶雕樑,tcp協議棧專家回答了這個問題:

在net/ipv4/tcp.c:1900附近

...
 /* As outlined in RFC 2525, section 2.17, we send a RST here because
    * data was lost. To witness the awful effects of the old behavior of
    * always doing a FIN, run an older 2.1.x kernel or 2.0.x, start a bulk
    * GET in an FTP client, suspend the process, wait for the client to
    * advertise a zero window, then kill -9 the FTP client, wheee...
    * Note: timeout is always zero in such a case.
    */
   if (data_was_unread) {
      /* Unread data was tossed, zap the connection. */
      NET_INC_STATS_USER(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE);
      tcp_set_state(sk, TCP_CLOSE);
      tcp_send_active_reset(sk, sk->sk_allocation);
..

程式碼裡面寫的很清楚,如果你的接收緩衝去還有資料,協議棧就會發rst代替fin.
我們再來驗證一下:

$ erl
Erlang R14B03 (erts-5.8.4)  [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.4  (abort with ^G)
1> {ok,Sock} = gen_tcp:connect("baidu.com", 80, [{active,false}]).
{ok,#Port<0.582>}
2> gen_tcp:send(Sock, "GET / HTTP/1.1\r\n\r\n").
ok
3> gen_tcp:recv(Sock,0).
{ok,"HTTP/1.1 400 Bad Request\r\nDate: Fri, 01 Jul 2011 09:24:37 GMT\r\nServer: Apache\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n127\r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>400 Bad Request</TITLE>\n</HEAD><BODY>\n<H1>Bad Request</H1>\nYour browser sent a request that this server could not understand.<P>\nclient sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /<P>\n</BODY></HTML>\n\r\n0\r\n\r\n"}
4> gen_tcp:close(Sock).
ok
5> 

這次我們把接收緩衝區裡的東西拉乾淨了。

再看下tcpdump:

...
17:36:07.236627 IP my031089.sqa.cm4.tbsite.net.9405 > 123.125.114.144.http: S 3086473299:3086473299(0) win 5840 <mss 1460,sackOK,timestamp 2608642228 0,nop,wscale 7>
17:36:07.274661 IP 123.125.114.144.http > my031089.sqa.cm4.tbsite.net.9405: S 738551248:738551248(0) ack 3086473300 win 8190 <mss 1436>
17:36:07.274685 IP my031089.sqa.cm4.tbsite.net.9405 > 123.125.114.144.http: . ack 1 win 5840
17:36:10.295795 IP my031089.sqa.cm4.tbsite.net.9405 > 123.125.114.144.http: P 1:19(18) ack 1 win 5840
17:36:10.334280 IP 123.125.114.144.http > my031089.sqa.cm4.tbsite.net.9405: . ack 19 win 5840
17:36:10.334547 IP 123.125.114.144.http > my031089.sqa.cm4.tbsite.net.9405: P 1:179(178) ack 19 win 5840
17:36:10.334554 IP my031089.sqa.cm4.tbsite.net.9405 > 123.125.114.144.http: . ack 179 win 6432
17:36:10.334563 IP 123.125.114.144.http > my031089.sqa.cm4.tbsite.net.9405: P 179:486(307) ack 19 win 5840
17:36:10.334566 IP my031089.sqa.cm4.tbsite.net.9405 > 123.125.114.144.http: . ack 486 win 7504
17:36:19.671374 IP my031089.sqa.cm4.tbsite.net.9405 > 123.125.114.144.http: F 19:19(0) ack 486 win 7504
17:36:19.709619 IP 123.125.114.144.http > my031089.sqa.cm4.tbsite.net.9405: . ack 20 win 5840
17:36:19.709643 IP 123.125.114.144.http > my031089.sqa.cm4.tbsite.net.9405: F 486:486(0) ack 20 win 5840
17:36:19.709652 IP my031089.sqa.cm4.tbsite.net.9405 > 123.125.114.144.http: . ack 487 win 7504
...

這次是發fin包了。

多隆同學再進一步,找出來之前squid client程式碼中不能理解的一句話:
client_side.c

...
 /* prevent those nasty RST packets */
    {
        char buf[SQUID_TCP_SO_RCVBUF];
        while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) > 0);
    }
...

總算明白了這句話的意思了!

小結:認真學習協議棧太重要了。

玩得開心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

No related posts.

相關推薦

系統技術業餘研究 » TCP連結主動關閉fin奇怪行為分析

問題描述: 多隆同學在做網路框架的時候,發現一條tcp連結在close的時候,對端會收到econnrest,而不是正常的fin包. 通過抓包發現close系統呼叫的時候,我端發出rst報文, 而不是正常的fin。這個問題比較有意思,我們來演示下: $ erl Erlang R14B03 (e

系統技術業餘研究 » gen_tcp連線半關閉問題

很久之前我發在javaeye論壇上,預防丟了抄過來: 原文:http://erlang.group.iteye.com/group/wiki/1422-gen_tcp-half-closed 當tcp對端呼叫shutdown(RD/WR) 時候, 宿主程序預設將收到{tcp_closed, Soc

系統技術業餘研究 » ss is one another utility to investigate sockets(特適合大規模tcp連結)

具體的可以參考這裡 他的最大特點是快, 當你的系統有上萬個tcp連結要了解的時候的時候, 你就知道我說什麼了. netstat等常規工具變成廢鐵了, 這時候他的作用就非常明顯了. /proc interface is inadequate, unfortunately. When amount

系統技術業餘研究 » gen_tcp接受連結時enfile的問題分析及解決

最近我們為了安全方面的原因,在RDS伺服器上做了個代理程式把普通的MYSQL TCP連線變成了SSL連結,在測試的時候,皓庭同學發現Tsung發起了幾千個TCP連結後Erlang做的SSL PROXY老是報告gen_tcp:accept返回{error, enfile}錯誤。針對這個問題,我展開了

系統技術業餘研究 » 看圖學TCP API以及狀態變遷

client的connect呼叫和server端之間的三根線應該對應著三次握手過程,這裡有一點問題。 client傳送的sync到達應該在server端accpet之前,所以橙色線應該指向accpet前面。 同樣,server端響應ack,sync是在accpet呼叫前的,因此粉色線也應該放在a

系統技術業餘研究 » 最快的Erlang http hello world 伺服器調優指南 (20Khttp短連結請求/S每桌面CPU)

erl的虛擬機器有2種方式 plain版本的和smp版本的。 smp版本由於鎖的開銷相比要比plain版本的慢很多。而32位機器由於記憶體訪問比64位的少,也會快出很多。所有我選擇在32位的linux系統下調優這個httpd伺服器。這個伺服器就是實現個簡單的功能,在browser下返回hello

系統技術業餘研究 » Erlang版TCP伺服器對抗攻擊解決方案

網際網路上的TCP伺服器面對的環境情況比企業私有的伺服器要複雜很多。常見的針對tcp伺服器的攻擊有以下幾種: 1. 偽造協議,導致伺服器crash. 比如說某條命令的欄位長度,協議最大規定是1024,偽造個4096的。 2. 偽造大的報文,比如說一個包有1024M這麼大。 3. 消耗伺服器資源。開

系統技術業餘研究 » Erlang程序簡單的主動負載管制實現

我們知道Erlang的排程器是公平的,當程序的時間片用完了後,會強制切出,但是這個粒度是比較粗的。比如說程序進行了大量的Io操作,這個操作換成時間片是不準確的,會導致某些CPU計算密集型的比較吃虧,IO密集型的合算。 為了避免這個情況,IO密集型的經常可以互動要求短暫放棄執行,最簡單的方法就是用訊

系統技術業餘研究

ItPub寫的文章“2017 年度 DB-Engines 資料庫冠軍得主:PostgreSQL 封王!”, 點選 這裡 進一步閱讀 升的最快的幾個資料庫,我簡單的無責任點評: PG資料庫是很老的資料庫,不過這幾年冉冉升起,因為是學院派的,有很好的學術和智力的支援,一直以來在資料庫的體系結構,程式碼

系統技術業餘研究 » MySQL資料庫架構的演化觀察

MySQL資料庫架構的演化觀察 December 14th, 2017 Categories: 資料庫 Tags: mysql

系統技術業餘研究 » inet_dist_connect_options

Erlang 17.5版本引入了inet_dist_{listen,connect}_options,對於結點間的互聯socket可以有更精細的控制,RPC的時候效能可以微調: raimo/inet_tcp_dist-priority-option/OTP-12476: Document ke

系統技術業餘研究 » 推薦工作機會

最後更新時間:2014/11/28 請賜簡歷至:[email protected], 感謝您對加入我們公司有興趣,我們希望能早日和您共事。 以下幾個職位1年內有效,歡迎內部轉崗:
 資深資料工程師 公司:阿里(核心系統資料庫組) 工作地點:杭州(西溪園區) 崗位描述: 分析雲服務產生的海

系統技術業餘研究 » 新的工作和研究方向

和大家更新下: 做了將近8年資料庫後,我的工作和研究方向將會延伸到虛擬化和計算相關的雲服務,希望能夠和大家一起進步,Happy New Year! 預祝大家玩得開心! Post Footer automatically generated by wp-posturl plugin for w

系統技術業餘研究 » 叢集引入inet_dist_{listen,connect}_options更精細引數微調

Erlang 17.5版本引入了inet_dist_{listen,connect}_options,對於結點間的互聯socket可以有更精細的控制,RPC的時候效能可以微調: raimo/inet_tcp_dist-priority-option/OTP-12476: Document ke

系統技術業餘研究 » 2017升的最快的幾個資料庫無責任點評

ItPub寫的文章“2017 年度 DB-Engines 資料庫冠軍得主:PostgreSQL 封王!”, 點選 這裡 進一步閱讀 升的最快的幾個資料庫,我簡單的無責任點評: PG資料庫是很老的資料庫,不過這幾年冉冉升起,因為是學院派的,有很好的學術和智力的支援,一直以來在資料庫的體系結構,程式碼

系統技術業餘研究 » Erlang 17.5引入+hpds命令列控制程序預設字典大小

Erlang 17.5釋出引入控制程序預設字典大小的命令列引數: Erlang/OTP 17.5 has been released Written by Henrik, 01 Apr 2015 Some highlights of the release are: ERTS: Added co

系統技術業餘研究 » inet_dist_listen_options

Erlang 17.5版本引入了inet_dist_{listen,connect}_options,對於結點間的互聯socket可以有更精細的控制,RPC的時候效能可以微調: raimo/inet_tcp_dist-priority-option/OTP-12476: Document ke

系統技術業餘研究 » 老生常談: ulimit問題及其影響

ulimit最初設計是用來限制程序對資源的使用情況的,因為早期的系統系統資源包括記憶體,CPU都是非常有限的,系統要保持公平,就要限制大家的使用,以達到一個相對公平的環境。以下是典型的機器預設的限制情況: $ ulimit -a core file size (blocks,

系統技術業餘研究 » 求賢帖

原創文章,轉載請註明: 轉載自系統技術非業餘研究 本文連結地址: 求賢帖 作為一個優秀的工程師,你其實不缺少才華,你缺少的是神一樣的隊友、充滿挑戰的世界級技術難題,和一個可以施展自己才華的大舞臺。加入阿里核心系統資料庫開發團隊吧,你缺的這裡都有。來吧,戳這裡,給我們見識你的機會:http://b

系統技術業餘研究 » Erlang R16B03釋出,R17已

Erlang R16B03釋出了,通常03版本是bug fix版本,進入生產版本,官方的說明如下: OTP R16B03 is a service release with mostly a number of small corrections and user contributions. B