目錄
10.1 引言
10.2 UDP 頭部
10.3 UDP校驗和
10.4 例子
10.5 UDP 和 IPv6
10.6 UDP-Lite
10.7?IP分片
10.7.1 例子:IPV4 UDP分片
10.7.2 重組超時
10.8 采用UDP的路徑MTU發現
10.9 IP分片和ARP/ND之間的交互
10.10 最大UDP數據報長度
10.11 UDP服務器的設計
10.11.1 IP地址和UDP端口號
10.11.2 限制本地IP地址
10.11.3 使用多地址
10.11.4 限制遠端IP地址
10.11.5 每端口多服務器的使用
10.11.6 跨越地址族:IPv4和IPv6
10.11.7 流量和擁塞控制的缺失
10.12 UDP/IPV4和UDP/IPV6數據報的轉換
10.13 互聯網中的UDP
10.14 與UDP和IP分片相關的攻擊
10.15 總結
10.1 引言
UDP(User Datagram Protocol):用戶數據報協議。一種傳輸層協議。
????????IPv4中協議字段值:17。
????????????????特點:
????????????????????????有消息邊界。
????????????????????????開銷更小,因為沒有TCP復雜機制。
當UDP應用程序每次調用send/write,就發出一個UDP數據報。
而TCP不一定,因為TCP可能分段,重組。
即TCP應用程序執行多次send/write調用會組合成一個數據包發送,或可能一個send/write調用被分成多個數據包發送。
10.2 UDP 頭部
頭部格式如下:
字段:
????????源端口
????????目的端口
????????長度:UDP報文總長度,包括頭部和數據。
????????校驗和:校驗整個UDP報文。
每個socket在創建時必須指定協議類型(TCP或UDP),并綁定到特定端口。
因此,一個套接字不能同時監聽TCP/UDP相同端口。
一個主機可以創建兩個socket,分別監聽TCP和UDP的相同端口號,表示兩種不同服務。
10.3 UDP校驗和
UDP校驗和:校驗范圍覆蓋UDP頭部、UDP數據,偽頭部。
偽頭部(pseudo-header):
????????計算UDP校驗和時,根據IP頭信息生成的虛擬頭部。
????????偽頭部格式通常包括:
????????????????源IP、目標IP、協議類型(UDP),UDP數據報總長等。
????????作用:提供更多信息,確保校驗更精確。
偽頭部細節如下圖:
NAT會改變報文IP和端口,所以經過NAT后需要重新校驗和。
IPv4頭中也有校驗和,但只校驗IPv4頭內容,不包括IP載荷。
????????在每跳都要重新計算,因為TTL字段值減小。
小結:
????????IPv4頭的校驗和字段:只校驗IPv4頭內容。
????????傳輸層TCP/UDP頭的校驗和字段:校驗范圍不僅包含傳輸層頭,還有載荷。
10.4 例子
10.5 UDP 和 IPv6
IPv6中TCP/UDP都需要偽頭部來計算校驗和。
Teredo隧道:
????????IPv6數據被封裝成IPv4 UDP數據報后,發給Teredo中繼,中繼解封裝后把IPv6報文轉發給主機。
Teredo和GRE對比:
????????通用性:
????????????????GRE更通用,可封裝任何類型數據包。
????????????????Teredo只用于IPv4 UDP封裝IPv6數據。
????????實現方式:
????????????????GRE:不需要服務器或中繼。
????????????????Teredo:需要服務器和中繼。
10.6 UDP-Lite
UDP:校驗是可選的,要么校驗整個UDP報文,要么不校驗。
UDP-Lite:對UDP數據一部分校驗,而不是整個數據報校驗。
????????所以未校驗部分,容忍比特差錯。
UDP-Lite:有單獨的IPv4協議和IPv6協議號。算是一種新的傳輸層協議。
所以UDP- Lite有一個校驗和覆蓋范圍字段,表示需要校驗哪部分數據。
????????最小值為8,即只校驗UDP-Lite頭。
????????特殊值:0,表示校驗整個負載。
socket簡化程序舉例,設置UDP-Lite校驗和覆蓋范圍:
int main() {
????????int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDPLITE);
????????int send_cscov = 8; // 只校驗UDP-Lite頭。
????????setsockopt(sockfd, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV, &send_cscov, sizeof(send_cscov)) ;
????????
????????int recv_cscov = 0; // 校驗整個負載
????????setsockopt(sockfd, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV, &recv_cscov, sizeof(recv_cscov));
}
10.7?IP分片
IPv6只允許源主機分片,不允許中間轉發設備分片,可減少中間設備負擔。
IPv4既允許源主機分片,也允許中間路由器分片。
IP數據報大于MTU則分片。
被分片IP數據報,到了目的地才會重組,這樣設計有兩個原因:
????????1. 減輕中間路由器轉發負擔。
????????2. 同一數據報的不同分片可能經不同路徑到達目的地,此時路徑上路由器不能收到所有分片,搜到沒有能力重組原始數據。
10.7.1 例子:IPV4 UDP分片
數據報分片后,每個分片IPv4頭中的總長度字段被修改成該分片的總長度。
任一分片丟失,整個IP數據報無法完整接收。
當TCP報文的一個分片丟失了,TCP協議棧會重傳整個TCP報文段,所以通常盡量避免TCP分片。
除最后一個分片外所有分片數據部分應是8字節倍數。
tcpdump為了能打印除了第一個分片外的其他分片的端口號,嘗試重組其他分片的數據報,以恢復只出現在第一個分片的UDP頭部中的端口號。
10.7.2 重組超時
當任一分片最先到達時,IP層就啟動計時器。
若超時前未收到所有分片,無法重組源報文,會丟棄所有分片,防止緩存耗盡。
超時時間:一般30s,60s。
只有接收到了第一個分片并且分片重組失敗時,才產生ICMP錯誤。
10.8 采用UDP的路徑MTU發現
PMTU:路徑MTU 。
PMTUD:路徑MTU發現。
????????作用:發現路徑中MTU的最小值。發送報文不超過MTU,防止分片。
UDP PMTUD原理:
????????源端發送一個較大UDP數據報,并設置 DF(Don't Fragment)標志,確保不被分片。
????????某個中間路由器發現數據報超過其出接口MTU,則丟棄該數據報并回復"Packet Too Big" 的ICMP 錯誤消息給源端。
????????源端收到ICMP錯誤消息后,得到其中指示的MTU。于是重新發送較小的UDP數據報。
????????重復該過程就獲得一個可在所有路由器通過的MTU,即路徑最小MTU,PMTU。
IP層會基于每個目的地址緩存一個PMTUD值,有到該目的地報文則更新,否則超時需要重新嘗試PMTUD。
PPPoE MTU:1492
? ? ? ? 1500字節去除了6字節PPPoE頭部,2字節PPP頭部。
10.9 IP分片和ARP/ND之間的交互
10.10 最大UDP數據報長度
理論一個IPv4數據報的最大長度是65535字節。
但實際存在限制,如:
????????1. 系統,setsocketopt設置收發緩存大小。
????????2. 應用程序。read/write指定讀寫大小數目小于一個UDP數據報,大多數時候發生API截斷數據報,丟棄數據報里超過接收應用程序指定字節數的數據。
MSG_TRUNC標志位:
????????當socket收到超過recv函數指定接收緩沖區大小時,如果設置該標志位,系統將丟棄緩沖區以外數據,并且不報告任何錯誤,而是正常返回已接收數據長度。
MSG_TRUNC使用方法:
????????len = recvfrom(sockfd, buf, BUF_SIZE, MSG_TRUNC, (struct sockaddr *)&client_addr, &client_len);
如何獲取截斷數據大小:
????????socklen_t optlen = sizeof(recv_len);
????????getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recv_len, &optlen);
而TCP是連續的字節流,沒有消息邊界,不會被截斷。
10.11 UDP服務器的設計
10.11.1 IP地址和UDP端口號
SO_REUSEADDR:
????????一個socket選項,當一個socket被關閉后,它的端口號會繼續一段時間的被占用。
????????在這個時間內,其他程序無法綁定相同端口號,出現"Address already in use"錯誤。
????????設置SO_REUSEADDR選項后,當socket關閉后,立即可以被其他程序綁定,無需等待一段時間。
如何設置SO_REUSEADDR屬性:
????????int reuse = 1;
????????setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
10.11.2 限制本地IP地址
兩種策略:
????????1. 只有報文目的IP地址是該接收接口的IP時,才接收數據。
????????2. 任何本地接口均可接收到目的IP是某本地接口之一的數據。
10.11.3 使用多地址
一臺主機上,可以開啟多個服務器進程,都使用同一個端口號,但每個服務器進程使用不同本機IP地址。
????????通過ip addr add給本機設備配置多個IP地址。
此時需要用SO_REUSEADDR選項告訴系統允許重用相同的端口。
10.11.4 限制遠端IP地址
可設置是否只接收來自指定源IPv4地址和端口號的UDP數據報。
10.11.5 每端口多服務器的使用
10.11.6 跨越地址族:IPv4和IPv6
10.11.7 流量和擁塞控制的缺失
UDP沒有流量和擁塞控制機制。
10.12 UDP/IPV4和UDP/IPV6數據報的轉換
10.13 互聯網中的UDP
UDP占據了的互聯網流量的10% ~ 40%,隨著P2P應用增加,UDP流量也在上升。
互聯網總體流量只有極少是分片的(大約分組數的0.3%,字節數的0.8%),而其中分片流量的68.3%是UDP。
常見分片流量如:
????????多媒體視頻流量(應用層大包)
????????VPN隧道中封裝/隧道流量(多層封裝)
10.14 與UDP和IP分片相關的攻擊
常見UDP DoS攻擊:
????????1. 短時間大流量。UDP沒有流控。
????????2. 放大攻擊。偽造IP源成受害者地址,并設置目的地址為廣播。于是廣播目的地都回復報文給該受害者。
????????3. 淚滴攻擊。構造一個重疊偏移分片,可覆蓋前一分片部分數據。
????????4. 發送不帶任何數據的分片,攻擊IPv4重組程序。
10.15 總結
UDP是簡單協議。
需要組播廣播時使用UDP,可避免連接開銷。
UDP使用場景:多媒體,P2P。