国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Socket之so_linger與rst

ashe / 2748人閱讀

摘要:滑動窗口滑動窗口毫無疑問是用來加速數據傳輸的。處理程序會在自己認為的異常時刻發送包。序列號問題是與滑動窗口對應的,偽造的包里需要填序列號,如果序列號的值不在之前向發送時的滑動窗口內,是會主動丟棄的。

看Apache HttpClient的源碼時,發現abortRequest的時候,調用到socket時代碼如下:

public void shutdown() throws IOException {
        Socket socket = (Socket)this.socketHolder.getAndSet((Object)null);
        if (socket != null) {
            try {
                socket.setSoLinger(true, 0);
            } catch (IOException var6) {
                ;
            } finally {
                socket.close();
            }
        }

    }

what is so_linger?這個嘛得先從tcp三次握手與四次揮手說起:

TCP三次握手與四次揮手

三次握手建立連接:

為了能夠說清楚后面的RST攻擊,需要結合上圖說說:SYN標志位、序號、滑動窗口大小。
建立連接的請求中,標志位SYN都要置為1,在這種請求中會告知MSS段大小,就是本機希望接收TCP包的最大大小。
發送的數據TCP包都有一個序號。它是這么得來的:最初發送SYN時,有一個初始序號,根據RFC的定義,各個操作系統的實現都是與系統時間相關的。之后,序號的值會不斷的增加,比如原來的序號是100,如果這個TCP包的數據有10個字節,那么下次的TCP包序號會變成110。
滑動窗口用于加速傳輸,比如發了一個seq=100的包,理應收到這個包的確認ack=101后再繼續發下一個包,但有了滑動窗口,只要新包的seq與沒有得到確認的最小seq之差小于滑動窗口大小,就可以繼續發。

滑動窗口
滑動窗口毫無疑問是用來加速數據傳輸的。TCP要保證“可靠”,就需要對一個數據包進行ack確認表示接收端收到。有了滑動窗口,接收端就可以等收到許多包后只發一個ack包,確認之前已經收到過的多個數據包。有了滑動窗口,發送端在發送完一個數據包后不用等待它的ack,在滑動窗口大小內可以繼續發送其他數據包。
如果談到TCP攻擊就需要注意,TCP的各種實現中,在滑動窗口之外的seq會被扔掉!

四次握手的正常TCP連接關閉


FIN標志位也看到了,它用來表示正常關閉連接。圖的左邊是主動關閉連接方,右邊是被動關閉連接方,用netstat命令可以看到標出的連接狀態。
FIN是正常關閉,它會根據緩沖區的順序來發的,就是說緩沖區FIN之前的包都發出去后再發FIN包,這與RST不同。

RST標志位

RST表示復位,用來異常的關閉連接,在TCP的設計中它是不可或缺的。就像上面說的一樣,發送RST包關閉連接時,不必等緩沖區的包都發出去(不像上面的FIN包),直接就丟棄緩存區的包發送RST包。而接收端收到RST包后,也不必發送ACK包來確認。
TCP處理程序會在自己認為的異常時刻發送RST包。例如,A向B發起連接,但B之上并未監聽相應的端口,這時B操作系統上的TCP處理程序會發RST包。
又比如,AB正常建立連接了,正在通訊時,A向B發送了FIN包要求關連接,B發送ACK后,網斷了,A通過若干原因放棄了這個連接(例如進程重啟)。網通了后,B又開始發數據包,A收到后表示壓力很大,不知道這野連接哪來的,就發了個RST包強制把連接關了,B收到后會出現connect reset by peer錯誤。

說了這么多好像還沒說so_linger.

so_linger

Linux網絡編程中,socket的選項很多.其中幾個比較重要的選項有:SO_LINGER(僅僅適用于TCP,SCTP), SO_REUSEADDR.

在默認情況下,當調用close關閉socke的使用,close會立即返回,但是,如果send buffer中還有數據,系統會試著先把send buffer中的數據發送出去,然后close才返回.

SO_LINGER選項則是用來修改這種默認操作的.于SO_LINGER相關聯的一個結構體如下:

#include  
struct linger { 
int l_onoff //0=off, nonzero=on(開關) 
int l_linger //linger time(延遲時間) 
} 

當調用setsockopt之后,該選項產生的影響取決于linger結構體中 l_onoff和l_linger的值:

0 = l_onoff
當l_onoff被設置為0的時候,將會關閉SO_LINGER選項,即TCP或則SCTP保持默認操作:close立即返回.l_linger值被忽略.

l_lineoff值非0,0 = l_linger
當調用close的時候,TCP連接會立即斷開.send buffer中未被發送的數據將被丟棄,并向對方發送一個RST信息.值得注意的是,由于這種方式,是非正常的4中握手方式結束TCP鏈接,所以,TCP連接將不會進入TIME_WAIT狀態,這樣會導致新建立的可能和就連接的數據造成混亂。

l_onoff和l_linger都是非0
在這種情況下,回事的close返回得到延遲。調用close去關閉socket的時候,內核將會延遲。也就是說,如果send buffer中還有數據尚未發送,該進程將會被休眠直到一下任何一種情況發生:
1) send buffer中的所有數據都被發送并且得到對方TCP的應答消息(這種應答并不是意味著對方應用程序已經接收到數據,在后面shutdown將會具體講道)
2) 延遲時間消耗完。在延遲時間被消耗完之后,send buffer中的所有數據都將會被丟棄。

上面1),2)兩種情況中,如果socket被設置為O_NONBLOCK狀態,程序將不會等待close返回,send buffer中的所有數據都將會被丟棄。所以,需要我們判斷close的返回值。在send buffer中的所有數據都被發送之前并且延遲時間沒有消耗完,close返回的話,close將會返回一個EWOULDBLOCK的error.

1.默認操作的close,close立即返回


說明:我們已經知道write操作返回成功只能說明數據已經發送到套接字的發送緩沖區,不能代表對端已經成功收到數據,close的默認返回成功也只是成功發出了一個FIN分節,也不代表對端已經確認

2.設置SO_LINGER套接字選項且l_linger為正值時的close:【數據ack了,并收到FIN了】 才返回


說明:這種情況下客戶的close要到它的數據和FIN已經被服務器的TCP確認以后才會返回;

3.設置SO_LINGER套接字選項且l_linger為偏小正值時的close:時間到了 返回-1,EWOULDBLOCK錯誤

說明:在服務端的確認到達之前,SO_LINGER套接字選項設置的延滯時間到,close將會返回EWOULDBLOCK錯誤,且套接字發送緩沖區中的任何殘留數據被丟棄。

總結:設置SO_LINGER套接字選項以后,close的成功返回只是告訴我們先前發送的數據的FIN已經由對端TCP確認,而不能告訴我們對端應用進程是否已經讀取數據,如果不設置該套接字選項,那么我們連對端TCP是否確認了數據都不知道。

l_onoff 非0,l_linger為0,丟棄發送緩沖區的任何數據,并發送rst給對端,沒有四分組連接終止序列--沒有fin,這樣一來避免了TIME_WAIT狀態,但是在2MSL秒內創建該連接的新化身,導致來自剛剛終止的連接上的舊數據被不正確的傳送到新的化身上

回到這段代碼

public void shutdown() throws IOException {
        Socket socket = (Socket)this.socketHolder.getAndSet((Object)null);
        if (socket != null) {
            try {
                socket.setSoLinger(true, 0);
            } catch (IOException var6) {
                ;
            } finally {
                socket.close();
            }
        }

    }

設置的是上述第三點:設置SO_LINGER套接字選項且l_linger為偏小正值時的close:時間到了 返回-1,EWOULDBLOCK錯誤. 為0立即返回,然后收到FIN之后發送RST,不會進入TIME_WAIT狀態。

附:RST攻擊

A和服務器B之間建立了TCP連接,此時C偽造了一個TCP包發給B,使B異常的斷開了與A之間的TCP連接,就是RST攻擊了。實際上從上面RST標志位的功能已經可以看出這種攻擊如何達到效果了。
那么偽造什么樣的TCP包可以達成目的呢?我們至頂向下的看。
假定C偽裝成A發過去的包,這個包如果是RST包的話,毫無疑問,B將會丟棄與A的緩沖區上所有數據,強制關掉連接。
如果發過去的包是SYN包,那么,B會表示A已經發瘋了(與OS的實現有關),正常連接時又來建新連接,B主動向A發個RST包,并在自己這端強制關掉連接。

這兩種方式都能夠達到復位攻擊的效果。似乎挺恐怖,然而關鍵是,如何能偽造成A發給B的包呢?這里有兩個關鍵因素,源端口和序列號。
一個TCP連接都是四元組,由源IP、源端口、目標IP、目標端口唯一確定一個連接。所以,如果C要偽造A發給B的包,要在上面提到的IP頭和TCP頭,把源IP、源端口、目標IP、目標端口都填對。這里B作為服務器,IP和端口是公開的,A是我們要下手的目標,IP當然知道,但A的源端口就不清楚了,因為這可能是A隨機生成的。當然,如果能夠對常見的OS如windows和linux找出生成source port規律的話,還是可以搞定的。
序列號問題是與滑動窗口對應的,偽造的TCP包里需要填序列號,如果序列號的值不在A之前向B發送時B的滑動窗口內,B是會主動丟棄的。所以我們要找到能落到當時的AB間滑動窗口的序列號。這個可以暴力解決,因為一個sequence長度是32位,取值范圍0-4294967296,如果窗口大小像上圖中我抓到的windows下的65535的話,只需要相除,就知道最多只需要發65537(4294967296/65535=65537)個包就能有一個序列號落到滑動窗口內。RST包是很小的,IP頭+TCP頭也才40字節,算算我們的帶寬就知道這實在只需要幾秒鐘就能搞定。

那么,序列號不是問題,源端口會麻煩點,如果各個操作系統不能完全隨機的生成源端口,或者黑客們能通過其他方式獲取到source port,RST攻擊易如反掌,后果很嚴重。

參考:

http://blog.csdn.net/russell_...
https://www.cnblogs.com/my_li...
http://blog.csdn.net/le119126...
《UNIX Network ProgrammingVolume 1, Third Edition: TheSockets Networking API》
http://blog.csdn.net/yusiguyu...
http://blog.csdn.net/yusiguyu...
http://www.cs.northwestern.ed...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70740.html

相關文章

  • 斷開TCP連接

    摘要:我們知道通過三次握手建立可靠連接,通過四次揮手斷開連接,連接是比較昂貴的資源。從上分析,安全可靠的斷開連接至少需要四次,再多一次的意義不大。連接的異常斷開以上都是在理想的情況下發生的,理想狀態下,一個連接可以被長期保持。 我們知道TCP通過三次握手建立可靠連接,通過四次揮手斷開連接,TCP連接是比較昂貴的資源。為什么TCP需要通過三次握手才能建立可靠的連接?兩次不行么?斷開連接為什么需...

    fyber 評論0 收藏0
  • Java必知必會socket

    摘要:上,數據按有限大小的包傳輸,這些包成為數據報,每個數據報包含一個首部和一個有效載荷。不過,由于數據報長度有限,通常必須將數據分解為多個包,再在目的地重新組合。這兩個構造函數,在返回之前會與遠程主機建立一個活動的網絡連接。 Internet上,數據按有限大小的包傳輸,這些包成為數據報(datagram),每個數據報包含一個首部(header)和一個有效載荷(payload)。首部包含包發...

    jackzou 評論0 收藏0
  • (超簡單)ESP8266深度睡眠模式下遠程采集溫濕度信息

    摘要:超簡單深度睡眠模式下遠程采集溫濕度信息項目背景相關技術深度睡眠模式溫濕度采集數據收發前后端實現后端前端項目背景自己用收納箱做了一個用于存放打印耗材的干燥箱,想用閑置的開發板和溫濕度傳感器做一個遠程溫濕度監測的小項目。 ...

    pkhope 評論0 收藏0

發表評論

0條評論

ashe

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<