和機(jī)制實(shí)現(xiàn)網(wǎng)絡(luò)側(cè)信道計(jì)算)
在實(shí)際網(wǎng)絡(luò)通信中路由器的主要職責(zé)是根據(jù)IP報(bào)文頭部的目標(biāo)地址進(jìn)行轉(zhuǎn)發(fā)它通常不關(guān)心數(shù)據(jù)載荷的內(nèi)容。但你是否想過能否利用路由器對報(bào)文必須進(jìn)行的某些標(biāo)準(zhǔn)操作來實(shí)現(xiàn)一些非標(biāo)準(zhǔn)的功能例如讓路由器在轉(zhuǎn)發(fā)過程中無意間完成一次簡單的算術(shù)運(yùn)算。這聽起來像是網(wǎng)絡(luò)協(xié)議棧的一個(gè)“副作用”或“技巧”但它恰恰揭示了網(wǎng)絡(luò)設(shè)備處理數(shù)據(jù)包時(shí)一些有趣且底層的機(jī)制。Hopsum 這個(gè)概念正是探索了這種可能性通過精心構(gòu)造的、本應(yīng)被丟棄的“過期”數(shù)據(jù)包誘導(dǎo)路由器在計(jì)算校驗(yàn)和Checksum的過程中間接地為我們執(zhí)行計(jì)算。本文面向?qū)W(wǎng)絡(luò)協(xié)議、路由器工作原理以及底層數(shù)據(jù)包操作感興趣的開發(fā)者、網(wǎng)絡(luò)工程師和安全研究人員。我們將從 IPv4 和 ICMP 協(xié)議的基礎(chǔ)講起深入理解校驗(yàn)和的計(jì)算機(jī)制然后探討 Hopsum 這一設(shè)想背后的原理、實(shí)現(xiàn)思路、潛在挑戰(zhàn)以及其作為學(xué)習(xí)工具的價(jià)值。通過本文你將能理解如何將網(wǎng)絡(luò)設(shè)備的固有行為轉(zhuǎn)化為一種計(jì)算原語并掌握相關(guān)的協(xié)議分析和數(shù)據(jù)包構(gòu)造技能。1. 理解基石IPv4、ICMP 與校驗(yàn)和要理解 Hopsum必須首先掌握三個(gè)核心概念I(lǐng)Pv4 報(bào)文結(jié)構(gòu)、ICMP 協(xié)議以及校驗(yàn)和算法。它們是整個(gè)設(shè)想得以成立的基礎(chǔ)。1.1 IPv4 報(bào)文頭部與生存時(shí)間TTLIPv4 報(bào)文頭部包含多個(gè)字段其中與 Hopsum 設(shè)想最相關(guān)的是生存時(shí)間Time To Live, TTL和頭部校驗(yàn)和Header Checksum。一個(gè)簡化的 IPv4 頭部關(guān)鍵字段如下0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -------------------------------- |Version| IHL |Type of Service| Total Length | -------------------------------- | Identification |Flags| Fragment Offset | -------------------------------- | Time to Live | Protocol | Header Checksum | -------------------------------- | Source Address | -------------------------------- | Destination Address | -------------------------------- | Options (if any) | --------------------------------TTLTime to Live這是一個(gè)8位字段初始值通常為64、128或255。每經(jīng)過一個(gè)路由器即一跳該值減1。當(dāng) TTL 減至0時(shí)路由器會(huì)丟棄該數(shù)據(jù)包并通常向源地址發(fā)送一個(gè)ICMP Time Exceeded消息。這個(gè)“遞減”操作是路由器對數(shù)據(jù)包內(nèi)容進(jìn)行的少數(shù)幾種算術(shù)運(yùn)算之一。頭部校驗(yàn)和Header Checksum這是一個(gè)16位字段用于檢測 IPv4 頭部在傳輸過程中是否發(fā)生錯(cuò)誤。關(guān)鍵點(diǎn)在于每當(dāng) IPv4 頭部的任何字段發(fā)生變化例如 TTL 被減1路由器都必須重新計(jì)算并更新這個(gè)校驗(yàn)和。這個(gè)重新計(jì)算的過程就是 Hopsum 設(shè)想利用的核心環(huán)節(jié)。1.2 ICMP 協(xié)議與錯(cuò)誤報(bào)告ICMPInternet Control Message Protocol是 IP 協(xié)議的輔助協(xié)議用于傳遞控制信息和錯(cuò)誤報(bào)告。當(dāng)路由器因?yàn)?TTL0 而丟棄一個(gè)數(shù)據(jù)包時(shí)它會(huì)生成一個(gè)ICMP Time Exceeded (Type 11, Code 0)報(bào)文并將其發(fā)送回原數(shù)據(jù)包的源地址。這個(gè) ICMP 報(bào)文本身也包含一個(gè)頭部和校驗(yàn)和。更重要的是根據(jù) RFC 792ICMP 錯(cuò)誤報(bào)文如 Time Exceeded的載荷部分必須包含觸發(fā)該錯(cuò)誤的原始 IP 數(shù)據(jù)包的頭8個(gè)字節(jié)以及其數(shù)據(jù)部分的前64位即原始IP頭至少8字節(jié)的原始傳輸層數(shù)據(jù)。這為“攜帶”信息提供了可能。1.3 校驗(yàn)和的計(jì)算原理IPv4 頭部校驗(yàn)和與 ICMP 校驗(yàn)和的計(jì)算算法相同都是簡單的16位二進(jìn)制反碼求和。算法步驟如下將需要計(jì)算校驗(yàn)和的字段對于IPv4是整個(gè)頭部對于ICMP是整個(gè)報(bào)文視為一系列16位2字節(jié)的字word。如果總字節(jié)數(shù)為奇數(shù)則在末尾補(bǔ)一個(gè)值為0的字節(jié)使其成為偶數(shù)。將所有16位字進(jìn)行二進(jìn)制求和普通的加法進(jìn)位會(huì)加到結(jié)果上。將求和結(jié)果中溢出的高位進(jìn)位不斷加到低位上直到?jīng)]有進(jìn)位為止。這個(gè)過程稱為“回卷”Wrap Around。最后對得到的16位結(jié)果取反碼即按位取反這個(gè)值就是校驗(yàn)和。在發(fā)送方計(jì)算出的校驗(yàn)和填入對應(yīng)字段。接收方或中間的路由器進(jìn)行同樣的計(jì)算但這次是將包括校驗(yàn)和字段在內(nèi)的所有16位字進(jìn)行求和。如果數(shù)據(jù)包沒有錯(cuò)誤這個(gè)求和的結(jié)果應(yīng)該等于0xFFFF二進(jìn)制全1。如果不是則說明數(shù)據(jù)包在傳輸中出錯(cuò)。注意IPv6 頭部取消了校驗(yàn)和將錯(cuò)誤檢測的責(zé)任完全交給了上層協(xié)議如TCP、UDP。因此Hopsum 的設(shè)想主要圍繞 IPv4 網(wǎng)絡(luò)展開。路由器在轉(zhuǎn)發(fā) IP 包時(shí)必須將 TTL 減1。由于 TTL 是 IPv4 頭部的一部分它的改變意味著頭部發(fā)生了變化因此路由器必須重新計(jì)算整個(gè) IPv4 頭部的校驗(yàn)和。這個(gè)“重新計(jì)算”是一個(gè)確定性的數(shù)學(xué)過程。Hopsum 的核心思想就是能否通過精心設(shè)計(jì)原始數(shù)據(jù)包的頭部字段特別是那些在傳輸中會(huì)保持不變的部分使得當(dāng)路由器為這個(gè)“過期”數(shù)據(jù)包生成 ICMP Time Exceeded 響應(yīng)時(shí)在 ICMP 響應(yīng)報(bào)文的某個(gè)部分如校驗(yàn)和或載荷中的某個(gè)字段體現(xiàn)出我們預(yù)設(shè)的“計(jì)算結(jié)果”2. Hopsum 設(shè)想的工作機(jī)制與實(shí)現(xiàn)思路Hopsum 不是一個(gè)已部署的軟件而是一個(gè)概念驗(yàn)證Proof of Concept或思想實(shí)驗(yàn)。它探討的是一種“計(jì)算范式”。下面我們拆解其工作機(jī)制和一種可能的實(shí)現(xiàn)思路。2.1 核心邏輯鏈假設(shè)我們想讓沿途的路由器對兩個(gè)數(shù) A 和 B 進(jìn)行加法運(yùn)算并將結(jié)果“報(bào)告”回來。邏輯鏈如下構(gòu)造觸發(fā)包Trigger Packet我們構(gòu)造一個(gè)特殊的 IPv4 數(shù)據(jù)包。將其 TTL 設(shè)置為 1確保它在到達(dá)第一個(gè)路由器后就會(huì)因 TTL 過期而被丟棄。編碼操作數(shù)我們將想要相加的兩個(gè)數(shù)字 A 和 B以某種形式編碼到這個(gè)觸發(fā)包的 IP 頭部或載荷的特定位置。這些位置需要滿足一個(gè)條件在路由器生成 ICMP Time Exceeded 報(bào)文時(shí)這些編碼值會(huì)被原封不動(dòng)地或經(jīng)過某種可預(yù)測的變換后復(fù)制到 ICMP 報(bào)文的載荷部分。誘導(dǎo)路由器“計(jì)算”路由器收到 TTL1 的包將其 TTL 減為 0然后丟棄。接著它需要構(gòu)造一個(gè) ICMP Time Exceeded 報(bào)文。在構(gòu)造過程中路由器會(huì) a. 計(jì)算這個(gè)新 ICMP 報(bào)文的校驗(yàn)和。 b. 將觸發(fā)包的頭部包含我們編碼的 A 和 B的前 8 個(gè)字節(jié)作為載荷的一部分放入 ICMP 報(bào)文。校驗(yàn)和作為“計(jì)算結(jié)果”ICMP 校驗(yàn)和的計(jì)算涵蓋了整個(gè) ICMP 報(bào)文包括其頭部和載荷即包含我們編碼的 A 和 B 的那部分?jǐn)?shù)據(jù)。因此最終計(jì)算出的 ICMP 校驗(yàn)和值在某種程度上是原始數(shù)據(jù)A和B和固定ICMP頭部的一個(gè)函數(shù)。如果我們設(shè)計(jì)的編碼方式非常巧妙使得 ICMP 校驗(yàn)和的計(jì)算結(jié)果恰好等于A B或 A ⊕ B 等其它運(yùn)算那么我們就成功地讓路由器完成了一次算術(shù)運(yùn)算并將結(jié)果“寫”在了校驗(yàn)和字段。接收與解碼我們作為發(fā)送方監(jiān)聽 ICMP 響應(yīng)。當(dāng)收到 ICMP Time Exceeded 報(bào)文時(shí)提取其校驗(yàn)和字段這個(gè)值就是我們期望的“運(yùn)算結(jié)果”。2.2 一個(gè)簡化的理論模型讓我們用極度簡化的偽代碼來理解這個(gè)過程。假設(shè) ICMP 校驗(yàn)和計(jì)算函數(shù)是Checksum(data)。我們構(gòu)造觸發(fā)包在載荷中固定位置放入兩個(gè)16位數(shù)A和B。路由器構(gòu)造 ICMP 響應(yīng)其載荷部分Payload_ICMP包含了觸發(fā)包的頭部我們無法控制以及我們的載荷包含 A 和 B。路由器計(jì)算ICMP_Checksum Checksum(ICMP_Header Payload_ICMP)。我們的目標(biāo)是通過精心選擇 A 和 B使得ICMP_Checksum A B模 2^16 運(yùn)算。這本質(zhì)上是一個(gè)反推問題已知ICMP_Header和Payload_ICMP中除 A、B 外的大部分固定內(nèi)容以及期望的校驗(yàn)和結(jié)果AB求解滿足等式的 A 和 B。由于校驗(yàn)和計(jì)算是線性運(yùn)算二進(jìn)制反碼加法在模 2^16-1 下是線性的理論上可以構(gòu)造出這樣的 A 和 B。2.3 實(shí)現(xiàn)挑戰(zhàn)與關(guān)鍵點(diǎn)在實(shí)際操作中會(huì)遇到諸多挑戰(zhàn)ICMP 載荷的不可控部分ICMP Time Exceeded 報(bào)文的載荷包含了原始 IP 包的頭 8 個(gè)字節(jié)。這 8 個(gè)字節(jié)中包括版本、IHL、TOS、總長度、標(biāo)識符、標(biāo)志位和片偏移這些字段在我們構(gòu)造觸發(fā)包時(shí)是確定的但并非全部可以為了“計(jì)算”而隨意設(shè)置例如總長度必須符合實(shí)際包長。校驗(yàn)和算法的非線性處理雖然二進(jìn)制加法是線性的但最后的“取反碼”操作是非線性的。不過在驗(yàn)證校驗(yàn)和時(shí)接收方是將所有字包括校驗(yàn)和相加看是否得全1。從構(gòu)造的角度看我們可以將“取反”的步驟納入方程求解。網(wǎng)絡(luò)地址轉(zhuǎn)換NAT與防火墻許多網(wǎng)絡(luò)環(huán)境會(huì)過濾或篡改 ICMP 報(bào)文這可能使得響應(yīng)無法返回或者返回的報(bào)文校驗(yàn)和被中間設(shè)備重新計(jì)算破壞了我們的“結(jié)果”。多跳與不確定性如果 TTL 設(shè)置大于1數(shù)據(jù)包可能會(huì)經(jīng)過多個(gè)路由器。每個(gè)路由器都會(huì)修改 TTL 和 IP 校驗(yàn)和但只有最終那個(gè) TTL 減到 0 的路由器才會(huì)發(fā)送 ICMP 響應(yīng)。路徑的不確定性使得我們難以預(yù)測是哪個(gè)路由器進(jìn)行了“計(jì)算”。盡管有這些挑戰(zhàn)Hopsum 的價(jià)值不在于成為一個(gè)實(shí)用的分布式計(jì)算平臺而在于它深刻地揭示了網(wǎng)絡(luò)協(xié)議棧中一些可被利用的確定性行為。3. 動(dòng)手實(shí)驗(yàn)構(gòu)造一個(gè)觸發(fā)包并觀察響應(yīng)為了更具體地理解這個(gè)過程我們可以使用像ScapyPython或raw socket編程這樣的工具來構(gòu)造數(shù)據(jù)包并進(jìn)行實(shí)驗(yàn)。以下是一個(gè)使用 Scapy 的概念性代碼框架用于發(fā)送一個(gè) TTL 很小的包并捕獲可能的 ICMP 響應(yīng)。3.1 環(huán)境準(zhǔn)備首先確保你有一個(gè)可以發(fā)送原始數(shù)據(jù)包并接收 ICMP 響應(yīng)的環(huán)境。通常這需要管理員/root權(quán)限。# 安裝 Scapy (Python 3) pip install scapy警告數(shù)據(jù)包構(gòu)造和發(fā)送應(yīng)在你自己控制的網(wǎng)絡(luò)環(huán)境如本地虛擬機(jī)、隔離的測試網(wǎng)絡(luò)中進(jìn)行。隨意向互聯(lián)網(wǎng)或他人網(wǎng)絡(luò)發(fā)送異常數(shù)據(jù)包可能違反服務(wù)條款或被誤認(rèn)為攻擊行為。3.2 使用 Scapy 發(fā)送探測包下面的 Python 腳本演示了如何構(gòu)造一個(gè) TTL 為 1 的 IP 包并發(fā)送到一個(gè)假設(shè)的下一跳地址例如你的默認(rèn)網(wǎng)關(guān)。#!/usr/bin/env python3 from scapy.all import * import sys def send_ttl_probe(dst_ip, src_port12345, dst_port80): 發(fā)送一個(gè)TTL很小的TCP SYN包誘導(dǎo)網(wǎng)關(guān)返回ICMP Time Exceeded。 實(shí)際上任何協(xié)議如UDP、ICMP Echo都可以。 # 構(gòu)造IP層設(shè)置TTL1目標(biāo)地址為遠(yuǎn)端服務(wù)器源地址為本機(jī) ip IP(dstdst_ip, ttl1) # 構(gòu)造TCP層使用SYN標(biāo)志隨機(jī)源端口目標(biāo)端口為80HTTP tcp TCP(sportsrc_port, dportdst_port, flagsS, seq1000) # 組合成數(shù)據(jù)包 packet ip / tcp print(f[*] 發(fā)送探測包到 {dst_ip}:{dst_port}, TTL{packet.ttl}) # 發(fā)送包并同時(shí)開啟嗅探以等待ICMP響應(yīng) # timeout 設(shè)置等待響應(yīng)的超時(shí)時(shí)間 answered, unanswered sr(packet, timeout2, verbose0) for sent, received in answered: if received.haslayer(ICMP): icmp_layer received.getlayer(ICMP) if icmp_layer.type 11 and icmp_layer.code 0: # Time Exceeded print(f[] 收到 ICMP Time Exceeded 來自 {received.src}) # 打印收到的ICMP包的校驗(yàn)和 print(f ICMP 校驗(yàn)和字段: 0x{icmp_layer.chksum:04x}) # 嘗試提取原始包的頭部信息 if received.haslayer(IPerror): original_ip received.getlayer(IPerror) print(f 原始觸發(fā)包 TTL: {original_ip.ttl1}) # 路由器已將其減為0 # 這里可以進(jìn)一步分析載荷尋找我們編碼的A和B else: print(f[?] 收到其他類型 ICMP: type{icmp_layer.type}, code{icmp_layer.code}) else: print(f[?] 收到非ICMP響應(yīng): {received.summary()}) if __name__ __main__: if len(sys.argv) ! 2: print(f用法: {sys.argv[0]} 目標(biāo)IP) sys.exit(1) target_ip sys.argv[1] send_ttl_probe(target_ip)3.3 運(yùn)行與觀察將腳本保存為hopsum_probe.py。在終端中運(yùn)行需要 root 權(quán)限sudo python3 hopsum_probe.py 8.8.8.8這里用8.8.8.8舉例你可以替換成你知道的、需要經(jīng)過至少一跳才能到達(dá)的任意公網(wǎng)IP。對于TTL1它很可能在你的網(wǎng)關(guān)處就被丟棄。預(yù)期輸出可能類似于[*] 發(fā)送探測包到 8.8.8.8:80, TTL1 [] 收到 ICMP Time Exceeded 來自 192.168.1.1 ICMP 校驗(yàn)和字段: 0x4d2f 原始觸發(fā)包 TTL: 0這個(gè)腳本并沒有實(shí)現(xiàn)完整的 Hopsum 計(jì)算它只是演示了如何觸發(fā) ICMP Time Exceeded 并獲取其校驗(yàn)和。0x4d2f這個(gè)值就是你的網(wǎng)關(guān)路由器在構(gòu)造那個(gè)特定 ICMP 報(bào)文時(shí)計(jì)算出的校驗(yàn)和。這個(gè)值是由 ICMP 頭部類型、代碼等和載荷包含我們發(fā)送的原始 IP 頭前8字節(jié)和TCP頭前8字節(jié)共同決定的。3.4 深入嘗試編碼信息要實(shí)現(xiàn) Hopsum我們需要控制觸發(fā)包的更多字段。例如我們可以將操作數(shù) A 和 B 編碼在 TCP 的序列號Sequence Number和確認(rèn)號Acknowledgment Number字段中因?yàn)檫@兩個(gè)字段是32位的且會(huì)被包含在 ICMP 載荷的前64位傳輸層數(shù)據(jù)里。def send_hopsum_encoded(dst_ip, A, B): 嘗試將A和B編碼到TCP頭部觀察ICMP校驗(yàn)和的變化。 這是一個(gè)概念性演示實(shí)際關(guān)系遠(yuǎn)比此復(fù)雜。 ip IP(dstdst_ip, ttl1) # 將A和B編碼到TCP序列號和確認(rèn)號取低16位作為示例 tcp TCP(sportRandShort(), dport80, flagsS, seqA, ackB) packet ip / tcp / Raw(bX*20) # 添加一些載荷確保長度 print(f[*] 發(fā)送編碼包: A(seq低16位){A 0xFFFF}, B(ack低16位){B 0xFFFF}) answered, _ sr(packet, timeout2, verbose0) for sent, received in answered: if received.haslayer(ICMP) and received.getlayer(ICMP).type 11: icmp_chksum received.getlayer(ICMP).chksum print(f[] ICMP 校驗(yàn)和: 0x{icmp_chksum:04x} ({icmp_chksum})) # 理論上我們需要建立 icmp_chksum 與 A, B 的數(shù)學(xué)關(guān)系模型 # 這需要解一個(gè)關(guān)于校驗(yàn)和計(jì)算的方程運(yùn)行這個(gè)腳本改變 A 和 B 的值觀察icmp_chksum的變化。你會(huì)發(fā)現(xiàn)它確實(shí)會(huì)變但變化規(guī)律并非簡單的AB。要建立準(zhǔn)確的數(shù)學(xué)模型需要完整實(shí)現(xiàn) RFC 1071 定義的校驗(yàn)和算法并考慮所有固定字段的影響。4. 校驗(yàn)和計(jì)算模型與方程構(gòu)建要讓路由器“計(jì)算”出我們想要的結(jié)果我們必須能夠精確預(yù)測給定輸入下ICMP 校驗(yàn)和會(huì)是什么。這就需要我們形式化校驗(yàn)和的計(jì)算過程。4.1 定義校驗(yàn)和計(jì)算函數(shù)我們實(shí)現(xiàn)一個(gè)標(biāo)準(zhǔn)的16位二進(jìn)制反碼求和函數(shù)def ones_complement_add(words): 對一系列16位整數(shù)列表進(jìn)行二進(jìn)制反碼求和。 words: list of integers (0-65535) 返回: 16位校驗(yàn)和0-65535 total 0 for word in words: total word # 處理溢出將進(jìn)位加回低位 total (total 0xFFFF) (total 16) # 取反碼得到校驗(yàn)和值 checksum ~total 0xFFFF return checksum def calculate_icmp_checksum(icmp_type, icmp_code, icmp_rest_of_header, payload_words): 計(jì)算ICMP校驗(yàn)和。 icmp_type, icmp_code: 各8位 icmp_rest_of_header: 16位對于Time Exceeded通常是0 payload_words: list of 16-bit words representing the payload # 將類型和代碼組合成一個(gè)16位字 type_code_word (icmp_type 8) | icmp_code # 校驗(yàn)和字段在計(jì)算時(shí)視為0 pseudo_header [type_code_word, icmp_rest_of_header] all_words pseudo_header payload_words return ones_complement_add(all_words)4.2 構(gòu)建 Hopsum 方程假設(shè)我們構(gòu)造的觸發(fā)包其 IP 頭前8字節(jié)和 TCP 頭前8字節(jié)共16字節(jié)即8個(gè)16位字中有一部分是我們可以控制的變量如編碼了 A 和 B其余是固定值或可預(yù)測值如IP版本、頭長度、總長度等。設(shè)這8個(gè)字為W[0]到W[7]其中W[i]和W[j]是我們編碼的 A 和 B。當(dāng)路由器構(gòu)造 ICMP Time Exceeded 報(bào)文時(shí)其載荷payload_words就包含了W[0]到W[7]。此外ICMP 頭部還有固定的類型11、代碼0和未用字段0。設(shè)C_target為我們希望路由器計(jì)算出的結(jié)果例如AB模 65536。那么我們需要解以下方程calculate_icmp_checksum(11, 0, 0, [W[0], W[1], ..., W[7]]) C_target其中W[0]...W[7]中的某些W是 A 和 B 的函數(shù)例如W[2] A,W[3] B其他W是常數(shù)。由于ones_complement_add是線性運(yùn)算在模2^16-1的域上我們可以將這個(gè)方程重寫為K a*A b*B ~C_target (模 2^16-1)這里K是所有固定字求和的結(jié)果包括ICMP頭部固定部分和載荷中的固定字a和b是系數(shù)通常是 1 或 -1取決于 A 和 B 在字序列中的位置和字節(jié)序。~C_target是對目標(biāo)值取反因?yàn)樾r?yàn)和是取反后存儲的。通過求解這個(gè)線性方程我們可以找到滿足條件的 A 和 B。這需要一些代數(shù)運(yùn)算但用編程實(shí)現(xiàn)是可行的。4.3 求解與驗(yàn)證腳本下面是一個(gè)高度簡化的示例演示如何為特定的目標(biāo)校驗(yàn)和比如AB求解 A假設(shè) B 固定或反之。def solve_for_A_given_B(C_target, B_fixed, fixed_words, A_position, B_position): 固定B求解A使得ICMP校驗(yàn)和等于C_target。 這是一個(gè)概念性框架忽略了字節(jié)序、IP頭固定字段計(jì)算等復(fù)雜細(xì)節(jié)。 fixed_words: 一個(gè)列表在A和B位置用None占位。 A_position, B_position: A和B在fixed_words列表中的索引。 # 1. 計(jì)算常數(shù)部分K假設(shè)A0 BB_fixed test_words fixed_words[:] test_words[A_position] 0 test_words[B_position] B_fixed # 這里需要將test_words轉(zhuǎn)換為實(shí)際的16位字列表包括ICMP頭部 # 為簡化假設(shè)有一個(gè)函數(shù)能計(jì)算除A外的所有貢獻(xiàn) # K contribution_of_all_fixed_parts(B_fixed) # 實(shí)際實(shí)現(xiàn)需要完整的包構(gòu)造和校驗(yàn)和計(jì)算模擬 # 2. 由于校驗(yàn)和計(jì)算是線性的A的貢獻(xiàn)是它本身如果它在載荷中作為一個(gè)獨(dú)立的16位字 # 方程: K A ~C_target (模 65535) # 所以 A (~C_target - K) mod 65535 # 注意這是極度簡化的模型真實(shí)情況要復(fù)雜得多。 # 以下為偽代碼 K calculate_constant_contribution(B_fixed, fixed_words, B_position) A_solution (~C_target - K) 0xFFFF return A_solution # 實(shí)際應(yīng)用需要模擬完整的IP和ICMP包結(jié)構(gòu)計(jì)算每個(gè)字段的精確貢獻(xiàn)。這個(gè)求解過程是 Hopsum 從設(shè)想變?yōu)榭裳菔敬a的關(guān)鍵。它要求我們對網(wǎng)絡(luò)數(shù)據(jù)包的比特級布局有極其精確的理解。5. 常見問題、挑戰(zhàn)與排查在實(shí)際嘗試實(shí)現(xiàn) Hopsum 時(shí)你會(huì)遇到一系列問題。下面列出常見問題及其排查思路。5.1 收不到 ICMP Time Exceeded 響應(yīng)問題現(xiàn)象可能原因檢查與排查方法處理建議發(fā)送探測包后無任何響應(yīng)本地防火墻阻止了出站原始套接字使用tcpdump或 Wireshark 在發(fā)送主機(jī)上抓包確認(rèn)包是否被發(fā)出。檢查防火墻規(guī)則如iptables,firewalld確保允許出站原始包。中間路由器或目標(biāo)主機(jī)防火墻丟棄了ICMP錯(cuò)誤報(bào)文在網(wǎng)關(guān)或更近的網(wǎng)絡(luò)節(jié)點(diǎn)抓包看ICMP響應(yīng)是否生成但被過濾。許多云主機(jī)提供商默認(rèn)禁用ICMP錯(cuò)誤消息。嘗試在可控的本地網(wǎng)絡(luò)如家庭路由器后測試。TTL 設(shè)置過大包到達(dá)了目標(biāo)主機(jī)目標(biāo)主機(jī)可能不回復(fù)TCP SYN到未開放端口如80或回復(fù)RST。使用traceroute命令先確定到目標(biāo)的第一跳地址將TTL設(shè)為1目標(biāo)地址設(shè)為該網(wǎng)關(guān)地址。收到響應(yīng)但不是 ICMP Time Exceeded目標(biāo)端口不可達(dá)如果目標(biāo)主機(jī)響應(yīng)可能是ICMP Destination Unreachable (Port)。確保使用一個(gè)大概率未使用的遠(yuǎn)程端口或使用不存在的目標(biāo)主機(jī)IP。5.2 計(jì)算出的校驗(yàn)和與預(yù)期不符問題現(xiàn)象可能原因檢查與排查方法處理建議即使A、B相同每次收到的校驗(yàn)和也不同觸發(fā)包中某些字段是隨機(jī)的檢查腳本中是否使用了隨機(jī)源端口、隨機(jī)IP ID、隨機(jī)TCP序列號等。在構(gòu)造觸發(fā)包時(shí)將所有非實(shí)驗(yàn)變量固定為常量例如固定源端口、IP ID、TCP序列號基數(shù)等。校驗(yàn)和變化與A、B的變化無簡單關(guān)系編碼位置或字節(jié)序錯(cuò)誤仔細(xì)核對RFC 791 (IP)和RFC 792 (ICMP)確認(rèn)ICMP載荷中原始包數(shù)據(jù)的格式和字節(jié)序網(wǎng)絡(luò)字節(jié)序。編寫一個(gè)函數(shù)完全模擬路由器構(gòu)造ICMP包并計(jì)算校驗(yàn)和的過程與抓取到的真實(shí)包進(jìn)行逐位比對。忽略了IP頭部的校驗(yàn)和路由器在轉(zhuǎn)發(fā)時(shí)修改了TTL因此也修改了IP頭的校驗(yàn)和。這個(gè)修改后的IP頭會(huì)被包含在ICMP載荷里。你的計(jì)算模型必須考慮“原始IP頭”是經(jīng)過路由器TTL遞減和校驗(yàn)和重算后的版本而不是你最初發(fā)送的版本。5.3 實(shí)驗(yàn)環(huán)境搭建建議使用虛擬網(wǎng)絡(luò)在 VirtualBox 或 VMware 中創(chuàng)建兩個(gè)虛擬機(jī)配置為僅主機(jī)Host-Only網(wǎng)絡(luò)相互可達(dá)。在一臺虛擬機(jī)上運(yùn)行發(fā)送腳本在另一臺或網(wǎng)關(guān)虛擬機(jī)上抓包分析。這是最安全、可控的方式。利用 Docker 網(wǎng)絡(luò)創(chuàng)建自定義的 Docker 網(wǎng)絡(luò)運(yùn)行容器利用容器作為簡單的路由器或終端進(jìn)行測試。本地回環(huán)適配器在 Linux 上可以嘗試向本地回環(huán)地址127.0.0.1發(fā)送TTL1的包但某些系統(tǒng)可能不會(huì)為本地產(chǎn)生的包生成ICMP Time Exceeded。明確目標(biāo)初期目標(biāo)不是實(shí)現(xiàn)完整的算術(shù)運(yùn)算而是先實(shí)現(xiàn)“發(fā)送固定包能準(zhǔn)確預(yù)測返回的ICMP校驗(yàn)和”。這是驗(yàn)證你對協(xié)議理解是否正確的基礎(chǔ)步驟。6. Hopsum 的意義、局限與擴(kuò)展思考6.1 作為學(xué)習(xí)工具的意義Hopsum 最大的價(jià)值在于教育性和啟發(fā)性深入理解協(xié)議它強(qiáng)迫你深入研究 IPv4、ICMP 的報(bào)文格式、字節(jié)序、校驗(yàn)和算法等細(xì)節(jié)。理解網(wǎng)絡(luò)設(shè)備行為讓你從“黑盒”使用路由器轉(zhuǎn)變?yōu)樗伎计鋬?nèi)部處理邏輯。掌握數(shù)據(jù)包構(gòu)造熟練使用Scapy、libpcap等工具進(jìn)行底層網(wǎng)絡(luò)編程。安全研究視角這種“濫用”協(xié)議預(yù)期行為的方式與某些網(wǎng)絡(luò)側(cè)信道攻擊或隱蔽信道技術(shù)有思想上的關(guān)聯(lián)有助于理解安全攻防。6.2 現(xiàn)實(shí)局限性效率極低完成一次“計(jì)算”需要往返一次網(wǎng)絡(luò)跳數(shù)的時(shí)間毫秒級并且需要構(gòu)造、發(fā)送、接收、解析多個(gè)數(shù)據(jù)包。與CPU的納秒級運(yùn)算速度相比效率相差數(shù)十億倍。不可靠ICMP 報(bào)文可能丟失、被過濾、被篡改。結(jié)果單一只能進(jìn)行非常有限類型的計(jì)算主要是與校驗(yàn)和算法相關(guān)的線性運(yùn)算。無通用性嚴(yán)重依賴于特定的網(wǎng)絡(luò)環(huán)境和協(xié)議版本IPv4。6.3 擴(kuò)展思考與相關(guān)概念盡管 Hopsum 本身不實(shí)用但其思想可以引申到其他領(lǐng)域網(wǎng)絡(luò)隱蔽信道Covert Channel利用協(xié)議字段如IP ID、TCP初始序列號、TTL來秘密傳輸信息是信息隱藏的一個(gè)研究方向。Hopsum 可以看作是一種極端隱蔽的信道。協(xié)議模糊測試Fuzzing通過發(fā)送非標(biāo)準(zhǔn)或畸形的數(shù)據(jù)包如奇異的TTL值、校驗(yàn)和來測試網(wǎng)絡(luò)設(shè)備或協(xié)議棧實(shí)現(xiàn)的健壯性。路徑診斷與拓?fù)浒l(fā)現(xiàn)traceroute工具本身就是利用 TTL 過期和 ICMP 響應(yīng)的原理。Hopsum 可以視為對traceroute原理的另一種深度應(yīng)用。IPv6 的挑戰(zhàn)如前所述IPv6 沒有頭部校驗(yàn)和。那么在純 IPv6 環(huán)境中是否還有其他必選字段的修改能產(chǎn)生類似的可利用點(diǎn)例如跳數(shù)限制Hop Limit的遞減是必須的但 IPv6 的擴(kuò)展頭部結(jié)構(gòu)更為復(fù)雜。6.4 最佳實(shí)踐與安全警告僅在授權(quán)環(huán)境測試所有數(shù)據(jù)包構(gòu)造和發(fā)送實(shí)驗(yàn)必須在你自己擁有完全控制權(quán)的網(wǎng)絡(luò)環(huán)境中進(jìn)行。明確學(xué)習(xí)目的理解原理為主不要試圖將其用于干擾或探測未經(jīng)授權(quán)的網(wǎng)絡(luò)。注意法律與政策即使是在自家網(wǎng)絡(luò)某些 ISP 可能對異常的 ICMP 流量有監(jiān)控或限制。代碼健壯性實(shí)驗(yàn)代碼應(yīng)包含充分的錯(cuò)誤處理和日志記錄避免因程序異常產(chǎn)生不可控的網(wǎng)絡(luò)流量。Hopsum 是一個(gè)精巧的“思維體操”它展示了將網(wǎng)絡(luò)基礎(chǔ)設(shè)施轉(zhuǎn)化為計(jì)算單元的某種理論可能性。通過嘗試實(shí)現(xiàn)它你收獲的將不是一種實(shí)用的計(jì)算工具而是對計(jì)算機(jī)網(wǎng)絡(luò)底層運(yùn)作機(jī)制深刻而直觀的理解。這種理解是進(jìn)行高性能網(wǎng)絡(luò)編程、協(xié)議設(shè)計(jì)、網(wǎng)絡(luò)安全分析和故障排查的堅(jiān)實(shí)基礎(chǔ)。下一步你可以嘗試實(shí)現(xiàn)完整的校驗(yàn)和預(yù)測模型或者探索如何利用 TCP 序列號、IP ID 等字段實(shí)現(xiàn)更復(fù)雜的“隱寫”或編碼方案從而深化對網(wǎng)絡(luò)協(xié)議可塑性的認(rèn)識。