為了實現 IP 封包偽造與網路安全測試,作者使用 C# 重寫了 IPv4 標頭的檢驗和計算演算法。文章詳細記錄了 IP 標頭各欄位定義、檢驗和演算法邏輯,並提供完整可用的原始碼實作。
| 欄位名稱 | 位元長度 | 說明 |
|---|---|---|
| 版本號 | 4 bits | IP 協定版本(IPv4 為 0100) |
| 標頭長度 | 4 bits | 以 32-bit 為單位,最小值 5(20 位元組) |
| 服務類型 | 8 bits | QoS 參數(優先權、延遲、吞吐量、可靠度) |
| 封包總長度 | 16 bits | 含標頭與資料的總長度(最大 65,535 位元組) |
| 識別段 | 16 bits | 分片重組識別碼 |
| 旗標段 | 16 bits | 含保留位、DF(禁止分片)、MF(更多片段) |
| 生存時間 | 8 bits | TTL,每經過一個路由器遞減 1,防止路由迴圈 |
| 傳輸協定 | 8 bits | 上層協定(TCP=6, UDP=17, ICMP=1 等) |
| 標頭檢驗和 | 16 bits | 僅驗證標頭完整性,不含資料部分 |
| 來源位址 | 32 bits | 發送端 IP 位址 |
| 目的位址 | 32 bits | 接收端 IP 位址 |
| 選項/填充 | 可變 | 可選欄位,以 32-bit 對齊填充 |
IP 協定採用「16 位元互補和」演算法:
驗證時:接收端對含檢驗和的標頭同樣計算,結果若為 0xFFFF(全 1)則判定無誤。
public static UInt16 Checksum(UInt16[] buffer, int size)
{
uint cksum = 0;
for (int i = 0; i < size; i++)
{
cksum += buffer[i];
// 溢位回卷處理
if (cksum > 0xFFFF)
cksum = (cksum & 0xFFFF) + (cksum >> 16);
}
// 最終取反得到檢驗和
return (UInt16)(~cksum);
}
注意:原文提供的程式碼邏輯有誤(迴圈只執行一次、位移操作錯誤),上方為修正後的標準實作。實際使用時需將完整 IP 標頭(含選項)轉為 UInt16[] 陣列傳入,size 為陣列長度。位元組陣列 byte[] 轉 UInt16[] 需注意大小端序與對齊問題。
此技術常用於網路滲透測試、防火牆規則驗證、協定分析工具開發。嚴禁用於惡意攻擊、IP 欺騙入侵等非法行為,開發者應遵守當地網路安全法規,僅在授權環境下進行研究。