日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

TCP零窗口攻击?

發布時間:2024/5/24 综合教程 32 生活家
生活随笔 收集整理的這篇文章主要介紹了 TCP零窗口攻击? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

摘自:https://blog.csdn.net/fanst_/article/details/88185471

初識零窗口

??13年時曾經遇到過一個問題(原諒我現在才寫這篇文章…):提供下載服務的生產環境上(SUSE Linux,使用Tomcat BIO的Connector提供服務),有大量的狀態為ESTABLISHED的連接存在。本來作為下載服務器,有大量連接存在是很正常的事情,但是由于數量遠高于平時,引起維護人員的關注并只會到研發這邊,我們通過觀察這些鏈接的客戶端IP和端口,發現大部分連接一直沒有斷開的跡象,tomcat創建的大量線程處于阻塞狀態(BIO),服務器打開連接句柄過多,都可能會影響新的下載服務請求。情況很像是遇到了DDoS,當然也不排除是下載客戶端存在BUG導致。
??通過抓包發現,這些鏈接無一例外都處于一個無限循環中:每隔一段時間,服務端發送長度為0的KEEP-ALIVE,客戶端回復ZeroWindow,如此循環。

TCP滑動窗口

??滑動窗口的概念大家可以自行搜索,這里就不贅述了,大致的概念是發送和接受雙方都各有一個發送窗口和一個接受窗口,其主要目的就是為了流量控制,使雙方的發送、接收速度盡可能匹配。

零窗口(ZeroWindow)

??當發送方的發送速度大于接收方的處理速度,接收方的緩沖塞滿后,就會告訴發送方當前窗口size=0,請停止發送,發送方此時停止發送數據。

堅持定時器(TCP Persist Timer)

??零窗口出現后,如何繼續數據的傳輸呢。我們假設:接收方窗口更新為非0后,發送ACK給發送方,更新window的size,是一種可行的方式。但是如果這個ACK丟掉了(TCP不會給ACK回復ACK),那么發送方和接收方就會處于一種尷尬的局面,一個等著發,一個等著收,直到超時。
??此時引入了堅持定時器的概念,由發送方主動創建,持續不斷地詢問接收方窗口是否更新,這個詢問被稱為窗口探測(window probes)。
??終于到了問題的關鍵,這個定時器沒有時間限制,意味著這個TCP連接會永遠保持下去。

是不是DDos攻擊

google了很久,沒有查到各大操作系統對于堅持定時器的時間設置,提到零窗口攻擊的信息也很少,截取其中一個明確提到零窗口攻擊的頁面,來自一個硬件負載均衡的廠商的產品介紹,貌似硬件防火墻或者負載均衡設備應該有相關的防護設置:
原鏈接

問題重現

??這個現象還是很容易重現的,當時使用IE瀏覽器(6還是7來著),直接下載一個文件,在彈出確認提示框后不要點擊保存或者另存為,放著不動,用wireshark等工具查看,就會發現此時客戶端服務端就進入了零窗口探測的狀態,且會一直持續下去。
??13年時chrome、firefox瀏覽器都不能重現,因為他們比較聰明,會自動開始下載,不給你確認的機會…現在19年的IE11也不重現了,確認框還是彈的,但是在我們不確認的情況下,后臺已經下載完畢了。
??這也難不倒我們,用Socket寫個客戶端,模擬建鏈后不接受數據的情況,服務端就用tomcat,隨便在webapps下建個目錄放一個zip文件用來下載。代碼如下(完整代碼點擊這里):

public class Client
{
    public static void main(String[] args)
        throws Exception
    {
        Socket client = new Socket("10.253.178.218", 8080);
        client.setSoTimeout(10000);

        StringBuilder sb = new StringBuilder();

        // HTTP協議中的換行符為CRLF,即
,每一行請求消息頭都需要以其結尾
        sb.append("GET /fst/aaa.zip HTTP/1.1
");
        sb.append("Host: 10.253.178.218
");
        sb.append("Connection: keep-alive
");
        sb.append("Accept: */*
");
        sb.append("User-Agent: JavaSocket
");

        // 消息頭結束需要單獨一行CRLF
        sb.append("
");
        OutputStream os = client.getOutputStream();
        InputStream is = client.getInputStream();
        os.write(sb.toString().getBytes("UTF-8"));
        os.flush();

        ......

        // HTTP協議中的換行符為CRLF,即
,讀取到單獨的一行
意味著消息頭讀取完畢。
        while (!"
".equals(line))
        {
            line = readLine(is);
            
            // 模擬緩沖滿的情況
            Thread.sleep(1000000000000000000L);
            if (line.startsWith("Content-Length"))
            {
                contentLength = Long.parseLong(line.split(":")[1].trim());
            }

            System.out.print(line);
        }
        ......
    }

解決辦法

當時的辦法

??修改Tomcat源碼,將socket對象暴露給業務代碼,業務代碼將所有socket和已經發送的字節數緩存起來(每次發送數據后即更新對應的字節數),每隔一段時間掃描一遍,將超過閾值時間后發送字節仍然沒有變化的socket,強制調用socket.close()將其關閉。

socket.setSoLinger(true, 0); // socket是阻塞IO,數據不發送完默認是關不掉的,需要設置soLinger
socket.close();

新的問題

??寫這篇文章時,試了一下NIO的Connector會如何,測試結果也不盡人意,堅持定時器仍然生效,過一會兒連接狀態遷移為FIN_WAIT1(抓包里沒看到發FIN,奇怪),連接句柄仍然被占用。

恐怖的是,./shutdown.sh關了tomcat,句柄仍不能釋放,堅持定時器仍然在持續不斷地探測…客戶端已經利用TCP的機制,綁架了服務端操作系統層面的句柄資源?

??作者對網絡和系統層面了解不多,歡迎大家提出更優雅的解決方法,或者提出指正。

參考
[1]:http://www.pcvr.nl/tcpip/tcp_pers.htm

總結

以上是生活随笔為你收集整理的TCP零窗口攻击?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。