原文連接:https://fuckcloudnative.io/posts/deploy-k3s-cross-public-cloud/html
TCP 重置攻擊 是使用一個單一的數據包來執行的,只有幾個字節大小。攻擊者製做併發送一個僞造的 TCP 重置包來干擾用戶和網站的鏈接,欺騙通訊雙方終止 TCP
鏈接。咱們偉大的 xx 長城便運用了這個技術來進行 TCP 關鍵字阻斷。python
理解 TCP 重置攻擊並不須要具有深厚的網絡知識功底,只須要一臺筆記本就能夠對本身進行模擬攻擊。本文將會帶你瞭解 TCP 重置攻擊的原理,同時會幫助你理解不少關於 TCP 協議的特性。本文主要內容:linux
Python
腳原本模擬攻擊下面開始分析 TCP 重置攻擊原理。git
這一段略過,緣由你懂得,感興趣的請直接看原文。github
在 TCP 重置攻擊中,攻擊者經過向通訊的一方或雙方發送僞造的消息,告訴它們當即斷開鏈接,從而使通訊雙方鏈接中斷。正常狀況下,若是客戶端收發現到達的報文段對於相關鏈接而言是不正確的,TCP 就會發送一個重置報文段,從而致使 TCP 鏈接的快速拆卸。bash
TCP 重置攻擊利用這一機制,經過向通訊方發送僞造的重置報文段,欺騙通訊雙方提早關閉 TCP 鏈接。若是僞造的重置報文段徹底逼真,接收者就會認爲它有效,並關閉 TCP 鏈接,防止鏈接被用來進一步交換信息。服務端能夠建立一個新的 TCP 鏈接來恢復通訊,但仍然可能會被攻擊者重置鏈接。萬幸的是,攻擊者須要必定的時間來組裝和發送僞造的報文,因此通常狀況下這種攻擊只對長鏈接有殺傷力,對於短鏈接而言,你還沒攻擊呢,人家已經完成了信息交換。服務器
從某種意義上來講,僞造 TCP 報文段是很容易的,由於 TCP/IP 都沒有任何內置的方法來驗證服務端的身份。有些特殊的 IP 擴展協議(例如 IPSec
)確實能夠驗證身份,但並無被普遍使用。客戶端只能接收報文段,並在可能的狀況下使用更高級別的協議(如 TLS
)來驗證服務端的身份。但這個方法對 TCP 重置包並不適用,由於 TCP 重置包是 TCP 協議自己的一部分,沒法使用更高級別的協議進行驗證。網絡
儘管僞造 TCP 報文段很容易,但僞造正確的 TCP 重置報文段並完成攻擊卻並不容易。爲了理解這項工做的難度,咱們須要先了解一下 TCP 協議的工做原理。併發
TCP 協議的目標是向客戶端發送一份完整的數據副本。例如,若是個人服務器經過 TCP 鏈接向你的計算機發送個人網站的 HTML
,你的計算機的 TCP 協議棧應該可以以我發送的形式和順序輸出 HTML
。tcp
然而現實生活中個人 HTML 內容並非按順序發送的,它被分解成許多小塊(稱爲 TCP 分組),每一個小塊在網絡上被單獨發送,並被從新組合成原來發送的順序。這種從新組合後的輸出被稱爲 TCP 字節流。
將分組重建成字節流並不簡單,由於網絡是不可靠的。TCP分組可能會被丟棄,可能不按發送的順序到達客戶端,也可能會被重複發送、報文損壞等等。所以,TCP 協議的職責是在不可靠的網絡上提供可靠的通訊。TCP 經過要求鏈接雙方保持密切聯繫,持續報告它們接收到了哪些數據來實現可靠通訊,這樣服務端就可以推斷出客戶端還沒有接收到的數據,並從新發送丟失的數據。
爲了進一步理解這個過程,咱們須要瞭解服務端和客戶端是如何使用序列號(sequence numbers)來標記和跟蹤數據的。
TCP 協議的通訊雙方, 都必須維護一個序列號(sequence numbers),對於客戶端來講,它會使用服務端的序列號來將接收到的數據按照發送的順序排列。
當通訊雙方創建 TCP 鏈接時,客戶端與服務端都會向對方發送一個隨機的初始序列號,這個序列號標識了其發送數據流的第一個字節。TCP 報文段包含了 TCP 頭部,它是附加在報文段開頭的元數據,序列號就包含在 TCP 頭部中。因爲 TCP 鏈接是雙向的,雙方均可以發送數據,因此 TCP 鏈接的雙方既是發送方也是接收方,每一方都必須分配和管理本身的序列號。
當接收方收到一個 TCP 報文段時,它會向發送方返回一個 ACK
應答報文(同時將 TCP 頭部的 ACK
標誌位置 1),這個 ACK
號就表示接收方指望從發送方收到的下一個字節的序列號。發送方利用這個信息來推斷接收方已經成功接收到了序列號爲 ACK
以前的全部字節。
TCP 頭部格式以下圖所示:
一個確認應答報文的 TCP 頭部必須包含兩個部分:
TCP 總共有 6
個標誌位,下文就會講到其中的 RST
標誌位。
TCP 頭部包含了多個選項,其中有一個選擇確認選項(
SACK
),若是使用該選項,那麼當接收方收到了某個範圍內的字節而不是連續的字節時,就會發送SACK
告知對方。例如,只收到了字節1000~3000
和4000~5000
,但沒有收到3001~3999
。爲了簡單起見,下文討論 TCP 重置攻擊時將忽略選擇確認選項。
若是發送方發送了報文後在一段時間內沒有收到 ACK
,就認爲報文丟失了,並從新發送報文,用相同的序列號標記。這就意味着,若是接收方收到了重複的報文,可使用序列號來判斷是否見過這個報文,若是見過則直接丟棄。網絡環境是錯綜複雜的,每每並非如咱們指望的同樣,先發送的數據包,就先到達目標主機,反而它很騷,可能會因爲網絡擁堵等亂七八糟的緣由,會使得舊的數據包,先到達目標主機。通常分兩種狀況:
這兩種狀況對發送方來講實際上是同樣的,發送方並不能區分是哪一種狀況,因此只能從新發送數據包。
只要不頻繁重複發送數據,額外的開銷基本能夠忽略。
構建僞造的重置包時須要選擇一個序列號。接收方能夠接收序列號不按順序排列的報文段,但這種容忍是有限度的,若是報文段的序列號與它指望的相差甚遠,就會被直接丟棄。
所以,一個成功的 TCP 重置攻擊須要構建一個可信的序列號。但什麼纔是可信的序列號呢?對於大多數報文段(除了重置包,即 RST
包)來講,序列號是由接收方的接收窗口大小決定的。
想象一下,將一臺上世紀 90
年代初的古老計算機,鏈接到現代千兆光纖網絡。閃電般快速的網絡能夠以使人瞠目結舌的速度向這臺古老的計算機傳送數據,速度遠遠超過該計算機的處理能力。但並無什麼卵用,由於只有接收方接收並處理了報文,才能認爲這個報文已經被收到了。
TCP 協議棧有一個緩衝區,新到達的數據被放到緩衝區中等待處理。但緩衝區的大小是有限的,若是接收方的處理速度跟不上發送方的發送速度,緩衝區就會被填滿。一旦緩衝區被填滿,多餘的數據就會被直接丟棄,也不會返回 ACK。所以一旦接收方的緩衝區有了空位,發送方必須從新發送數據。也就是說,若是接收方的處理速度跟不上,發送方的發送速度再快也沒用。
緩衝區到底有多大?發送方如何才能知道何時能夠一次發送更多的數據,何時該一次發送不多的數據?這就要靠 TCP 滑動窗口了。接收方的滑動窗口大小是指發送方無需等待確認應答,能夠持續發送數據的最大值。 假設接收方的通告窗口大小爲 100,000
字節,那麼發送方能夠無需等待確認應答,持續發送 100,000
個字節。再假設當發送方發送第 100,000
個字節時,接收方已經發送了前 10,000
個字節的 ACK,這就意味着窗口中還有 90,000
個字節未被確認,發送方還能夠再持續發送 10,000
個字節。若是發送了 10,000
個字節的過程當中沒有收到任何的 ACK
,那麼接收方的滑動窗口將被填滿,發送方將中止發送新數據(能夠繼續發送以前丟失的數據),直到收到相關的 ACK
才能夠繼續發送。
TCP 鏈接雙方會在創建鏈接的初始握手階段通告對方本身窗口的大小,後續還能夠動態調整。TCP 緩衝區大的服務器可能會聲明一個大窗口,以便最大限度提升吞吐量。TCP 緩衝區小的服務器可能會被迫聲明一個小窗口,這樣作會犧牲必定的吞吐量,但爲了防止接收方的 TCP 緩衝區溢出,仍是頗有必要的。
換個角度來看,TCP 滑動窗口大小是對網絡中可能存在的未確認數據量的硬性限制。咱們能夠用它來計算髮送方在某一特定時間內可能發送的最大序列號(max_seq_no
):
max_seq_no = max_acked_seq_no + window_size
其中 max_acked_seq_no
是接收方發送的最大 ACK 號,它表示發送方知道接收方已經成功接收的最大序列號。window_size 是窗口大小,它表示容許發送方最多發送的未被確認的字節。因此發送方能夠發送的最大序列號是:max_acked_seq_no + window_size
。
TCP 規範規定,接收方應該忽略任何序列號在接收窗口以外的數據。例如,若是接收方確認了全部序列號在 15,000
如下的字節,且接收窗口大小爲 30,000
,那麼接下來接收方只能接收序列號範圍在 15,000 ~ 45,000
之間的數據。若是一個報文段的部分數據在窗口內,另外一部分數據在窗口外,那麼窗口內的數據將被接收確認,窗口外的數據將被丟棄。注意:這裏忽略了選擇確認選項,再強調一遍!
對於大多數 TCP 報文段來講,滑動窗口的規則告訴了發送方本身能夠接收的序列號範圍。但對於重置報文來講,序列號的限制更加嚴格,這是爲了抵禦一種攻擊叫作盲目 TCP 重置攻擊(blind TCP reset attack
),下文將會解釋。
對於 TCP 重置報文段來講,接收方對序列號的要求更加嚴格,只有當其序列號正好等於下一個預期的序列號時才能接收。繼續搬出上面的例子,接收方發送了一個確認應答,ACK 號爲 15,000
。若是接下來收到了一個重置報文,那麼其序列號必須是 15,000
才能被接收。
若是重置報文的序列號超出了接收窗口範圍,接收方就會直接忽略該報文;若是其序列號在接收窗口範圍內,那麼接收方就會返回一個 challenge ACK
,告訴發送方重置報文段的序列號是錯誤的,並告之正確的序列號,發送方能夠利用 challenge ACK
中的信息來從新構建和發送重置報文。
其實在 2010 年以前,TCP 重置報文段和其餘報文段的序列號限制規則同樣,但沒法抵禦盲目 TCP 重置攻擊,後來才採起這些措施施加額外的限制。
若是攻擊者可以截獲通訊雙方正在交換的信息,攻擊者就能讀取其數據包上的序列號和確認應答號,並利用這些信息得出假裝的 TCP 重置報文段的序列號。相反,若是沒法截獲通訊雙方的信息,就沒法肯定重置報文段的序列號,但仍然能夠批量發出儘量多不一樣序列號的重置報文,以指望猜對其中一個序列號。這就是所謂的盲目 TCP 重置攻擊(blind TCP reset attack
)。
在 2010 年以前 TCP 的原始版本中,攻擊者只須要猜對接收窗口內的隨便哪個序列號便可,通常只需發送幾萬個報文段就能成功。採起額外限制的措施後,攻擊者須要發送數以百萬計的報文段纔有可能猜對序列號,這幾乎是很難成功的。更多細節請參考 RFC-5963。
如下實驗是在
OSX
系統中完成的,其餘系統請自行測試。
如今來總結一下僞造一個 TCP 重置報文要作哪些事情:
ACK
標誌位置位 1 的報文段,並讀取其 ACK
號。RST
標誌位置爲 1),其序列號等於上面截獲的報文的 ACK
號。這只是理想狀況下的方案,假設信息交換的速度不是很快。大多數狀況下爲了增長成功率,能夠連續發送序列號不一樣的重置報文。爲了實驗簡單,咱們可使用本地計算機經過 localhost
與本身通訊,而後對本身進行 TCP 重置攻擊。須要如下幾個步驟:
下面正式開始實驗。
可使用 netcat 工具來創建 TCP 鏈接,這個工不少操做系統都預裝了。打開第一個終端窗口,運行如下命令:
$ nc -nvl 8000
這個命令會啓動一個 TCP 服務,監聽端口爲 8000
。接着再打開第二個終端窗口,運行如下命令:
$ nc 127.0.0.1 8000
該命令會嘗試與上面的服務創建鏈接,在其中一個窗口輸入一些字符,就會經過 TCP 鏈接發送給另外一個窗口並打印出來。
編寫一個攻擊程序,使用 Python 網絡庫 scapy
來讀取兩個終端窗口之間交換的數據,並將其打印到終端上。完整的代碼參考個人 GitHub 倉庫,代碼的核心是調用 scapy
的嗅探方法:
t = sniff( iface='lo0', lfilter=is_packet_tcp_client_to_server(localhost_ip, localhost_server_port, localhost_ip), prn=log_packet, count=50)
這段代碼告訴 scapy
在 lo0
網絡接口上嗅探數據包,並記錄全部 TCP 鏈接的詳細信息。
lo0
(localhost)網絡接口上進行監聽。localhost
,且端口號爲 8000
)的數據包。lfilter
規則的數據包。上面的例子只是將數據包打印到終端,下文將會修改函數來僞造重置報文。下面開始修改程序,發送僞造的 TCP 重置報文來進行 TCP 重置攻擊。根據上面的解讀,只須要修改 prn 函數就好了,讓其檢查數據包,提取必要參數,並利用這些參數來僞造 TCP 重置報文併發送。
例如,假設該程序截獲了一個從(src_ip
, src_port
)發往 (dst_ip
, dst_port
)的報文段,該報文段的 ACK 標誌位已置爲 1,ACK 號爲 100,000
。攻擊程序接下來要作的是:
IP/Port
應該是截獲數據包的目的 IP/Port
,反之亦然。RST
標誌位置爲 1,以表示這是一個重置報文。scapy
的 send
方法,將僞造的數據包發送給截獲數據包的發送方。對於個人程序而言,只需將這一行取消註釋,並註釋這一行的上面一行,就能夠全面攻擊了。按照步驟 1 的方法設置 TCP 鏈接,打開第三個窗口運行攻擊程序,而後在 TCP 鏈接的其中一個終端輸入一些字符串,你會發現 TCP 鏈接被中斷了!
ACK
號徹底相同。Wireshark
,監聽 lo0 網絡接口,並使用過濾器 ip.src == 127.0.0.1 && ip.dst == 127.0.0.1 && tcp.port == 8000
來過濾無關數據。你能夠看到 TCP 鏈接的全部細節。總的來講,TCP 重置攻擊既深奧又簡單,祝你實驗順利。
Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12離線安裝包發佈地址http://store.lameleg.com ,歡迎體驗。 使用了最新的sealos v3.3.6版本。 做了主機名解析配置優化,lvscare 掛載/lib/module解決開機啓動ipvs加載問題, 修復lvscare社區netlink與3.10內核不兼容問題,sealos生成百年證書等特性。更多特性 https://github.com/fanux/sealos 。歡迎掃描下方的二維碼加入釘釘羣 ,釘釘羣已經集成sealos的機器人實時能夠看到sealos的動態。