網路與 IP

UDP 協議是什麼?特點、報文格式與適用場景

UDP 全稱 User Datagram Protocol(使用者資料包協議),由 RFC 768 定義,是 TCP/IP 傳輸層的兩大協議之一,IP 協議號為 17。它不建立連線、不確認、不重傳、不保證順序,首部只有源連接埠、目的連接埠、長度、校驗和 4 個欄位共 8 位元組,換來低延遲和低開銷,DNS、DHCP、NTP、SNMP、音影片和 HTTP/3 都建立在它之上。

作者 頂聯產品團隊發布於 7 分鐘閱讀

UDP 協議是什麼?UDP 全稱 User Datagram Protocol,中文叫使用者資料包協議,1980 年由 RFC 768 定義,工作在 TCP/IP 的傳輸層(對應 OSI 第 4 層),與 TCP 並列。它在 IP 之上只加了兩樣東西:連接埠號,用來區分同一台主機上的不同程式;校驗和,用來發現資料在途中出錯。除此之外它什麼都不做:不握手、不確認、不重傳、不排序、不控制傳送速度,應用交給它多少位元組,它就原樣封裝成一個資料包發出去。所以 UDP 首部只有 8 位元組,傳送時沒有任何等待,適合 DNS 查詢、時間同步、音影片、遊戲這類“快比全重要”或者“一問一答”的場景。

UDP 工作在哪一層

UDP 位於傳輸層,下面是 IP,上面是應用程式。IP 包頭的“協議”欄位等於 17,表示裡面裝的是 UDP(TCP 是 6);系統收到後再按 UDP 首部裡的目的連接埠,把資料交給監聽該連接埠的程式。防火牆規則裡的 -p udp、交換器 ACL 裡的 udp 關鍵字,匹配的就是 IP 協議號 17。

UDP 之上還可以再疊一層“傳輸協議”,這是它在機房裡越來越常見的原因:

  • QUIC 跑在 UDP 上,自己實現了可靠傳輸和加密,HTTP/3 就建立在 QUIC 之上;
  • VXLAN 把整個乙太網幀裝進 UDP(目的連接埠 4789),讓二層網路跨三層網路延伸;
  • WireGuard、OpenVPN、IPsec 的 NAT 穿越也常用 UDP 承載隧道,裡面的 TCP 連線自己負責重傳。

“無連線、不可靠”具體指什麼

對比項 UDP TCP
建立連線 不需要,第一個包就攜帶資料 三次握手完成後才能發資料
確認與重傳 沒有,丟了就丟了 每段資料都要確認,超時重傳
順序 不保證,先發的可能後到 按序號重排後交給應用
流量與擁塞控制 沒有,應用發多快就發多快 按接收視窗和網路擁塞情況調節速率
資料邊界 保留:發一次就是一個資料包,收一次拿到完整的一個 位元組流,沒有訊息邊界,應用要自己分包
首部長度 固定 8 位元組 20–60 位元組
一對多 支援廣播、組播 只能一對一
伺服器狀態 不需要為每個客戶端維護連線 每個連線佔一份狀態和收發緩衝區

幾個常見的誤解:

  • “不可靠”不等於“經常丟包”。UDP 不會主動丟資料,丟包只發生在網路擁塞、鏈路出錯或接收緩衝區滿的時候,這些情況 TCP 一樣會遇到;區別是 TCP 會補發,UDP 把怎麼處理留給應用:DNS 超時重問,影片跳過這一幀,QUIC 自己重傳。
  • 校驗和只能發現錯誤,不能糾正。校驗失敗的資料包被直接丟棄,應用既收不到它,也不會收到通知。
  • 接收端來不及讀也會丟。高速收包的 UDP 服務(如日誌匯聚、流量採集)要關注 netstat -su 輸出裡的 receive buffer errors,持續增長說明程式讀得不夠快,需要調大 net.core.rmem_max 和程式自身的接收緩衝區。

UDP 報文格式:8 位元組首部

 0                   15 16                  31  (位)
+----------------------+----------------------+
|   源連接埠 Source Port  | 目的連接埠 Dest Port    |
+----------------------+----------------------+
|     長度 Length       |  校驗和 Checksum      |
+----------------------+----------------------+
|               資料 Data(可變長)             |
+---------------------------------------------+
欄位 長度 含義
源連接埠 16 位 傳送方的連接埠,對方回覆時發回這個連接埠;不需要回復時可以填 0
目的連接埠 16 位 接收方程式監聽的連接埠,如 DNS 的 53
長度 16 位 UDP 首部加資料的總位元組數,最小 8(沒有資料),最大 65535
校驗和 16 位 覆蓋偽首部(源 IP、目的 IP、協議號、UDP 長度)、UDP 首部和資料;IPv4 下可以填 0 表示不校驗,IPv6 下原則上必須計算

偽首部把 IP 位址也納入校驗,用來發現“資料沒錯但送錯了主機”的情況。也因為校驗和包含 IP 位址,NAT 裝置改寫位址時必須同時更新 UDP 校驗和。

用一個算例看各層的位元組數:不帶 EDNS 擴充套件、查詢 www.example.com 的 A 記錄(dig +noedns +noadflag www.example.com 發出的就是這樣一個包):

部分 位元組 說明
DNS 首部 12 事務 ID、標誌位和各段計數
查詢名 17 編碼為 3www7example3com0:每段前加 1 位元組長度,末尾 1 位元組 0
查詢型別與類別 4 型別 A 和類別 IN 各 2 位元組
DNS 報文合計 33 即 UDP 的資料部分
UDP 首部 8 長度欄位的值為 8 + 33 = 41
IPv4 首部 20 IP 總長度為 61
乙太網頭和 FCS 18 線路上的幀共 79 位元組

用 tcpdump 能看到同樣的數字:

tcpdump -i eth0 -nn udp port 53
# 10:20:31.508812 IP 198.51.100.23.51365 > 223.5.5.5.53: 4660+ A? www.example.com. (33)

括號裡的 33 就是 UDP 資料部分(DNS 報文)的長度,4660 是 DNS 事務 ID,後面的 + 表示請求遞迴。加 -X 引數能看到十六進位制原文:20 位元組 IP 首部之後緊跟的 8 位元組就是 UDP 首部,依次是源連接埠 c8a5(51365)、目的連接埠 0035(53)、長度 0029(41)和校驗和。

UDP 用於哪些場景:常見服務與連接埠

服務 UDP 連接埠 為什麼用 UDP
DNS 53 一問一答各一個包,先握手會讓每次查詢多一個往返
DHCP 服務端 67,客戶端 68 客戶端還沒有 IP 位址,只能靠廣播,TCP 做不到
TFTP 69 PXE 網路卡韌體裡只能放下很簡單的協議,TFTP 在 UDP 上自己逐塊確認
NTP 123 時間戳講究準時,重傳過來的舊包反而有害
SNMP 161 查詢,162 Trap 監控系統要輪詢成百上千台裝置,無連線開銷小
Syslog 514 裝置日誌單向傳送,偶爾丟一兩條可以接受
IPMI(RMCP+) 623 BMC 資源有限,協議自帶會話管理和重試
IKE / IPsec NAT 穿越 500 / 4500 VPN 隧道協商與承載
VXLAN 4789 封裝二層幀,可靠性交給內層 TCP
WireGuard 常用 51820,可自定義 隧道協議,內層連線自己負責重傳
HTTP/3(QUIC) 443 在 UDP 上自建可靠傳輸,避開 TCP 的隊頭阻塞
語音視訊通話、直播、線上遊戲 由應用協商或自定義 遲到的資料已經沒用,寧可丟棄也不等待

不適合 UDP 的場景也很明確:檔案傳輸、資料庫、網頁這類一個位元組都不能錯、又不打算自己實現重傳的業務,直接用 TCP。另外,有些企業網和代理環境會整體限制 UDP,基於 UDP 的協議要準備好退回 TCP 的方案,HTTP/3 退回 HTTP/2 就是這樣設計的。

伺服器防火牆放行 UDP 和 TCP 有什麼不同

1. 協議要單獨寫。 TCP 53 和 UDP 53 是兩個連接埠,對外提供 DNS 兩個都要放行;安全組裡選“全部 TCP”,不包含任何 UDP 連接埠。

# iptables:對外提供 DNS,只允許內網存取 NTP
iptables -A INPUT -p udp --dport 53 -j ACCEPT
iptables -A INPUT -p tcp --dport 53 -j ACCEPT
iptables -A INPUT -p udp -s 10.0.0.0/8 --dport 123 -j ACCEPT
# firewalld:放行 WireGuard 的 UDP 連接埠
firewall-cmd --permanent --add-port=51820/udp
firewall-cmd --reload
# Windows 防火牆:協議引數寫 UDP
New-NetFirewallRule -DisplayName "Syslog UDP 514" -Direction Inbound -Protocol UDP -LocalPort 514 -Action Allow

2. 狀態防火牆靠超時判斷“會話”。 UDP 沒有 SYN 和 FIN,Linux 的連線跟蹤按源位址、源連接埠、目的位址、目的連接埠和協議記錄 UDP 流:看到第一個包記為 NEW,對方回包後記為 ESTABLISHED,一段時間沒有包就刪除記錄。超時時間可以這樣檢視:

sysctl net.netfilter.nf_conntrack_udp_timeout net.netfilter.nf_conntrack_udp_timeout_stream

前者用於只有單向或零星往返的流,預設 30 秒;後者用於持續雙向通訊的流,時間更長,具體以核心版本為準。長時間不發包的 UDP 應用(部分 VPN、遊戲、物聯網裝置)超過時限後會被當成新會話,入站方向又沒放行時,伺服器下發的資料就到不了,所以這類應用都會定時傳送保活包。雲平台的安全組和 NAT 閘道器也有各自的 UDP 超時,以平台文件為準。

3. 無狀態 ACL 沒法用 established 放行 UDP 回包。 交換器、路由器上的 ACL 一般不跟蹤連線狀態。思科 ACL 的 established 關鍵字依據的是 TCP 頭裡的 ACK、RST 標誌位,對 UDP 不起作用。伺服器向外查詢 DNS 時,回包只能按“源連接埠為 53、目的連接埠在本機臨時連接埠範圍內”來放行(查詢用的源連接埠是隨機選的);而 UDP 的源連接埠可以隨意偽造,這類規則的約束力比 TCP 弱得多。所以機房裡 UDP 回程的控制,更多依賴伺服器或邊界上的狀態防火牆。

4. 測試方法不同。 UDP 沒有握手,連接埠掃描只能告訴你“沒收到拒絕”。可靠的做法是一端發、一端看:

# 伺服器上:抓目標連接埠的包,看請求有沒有到達
tcpdump -nni any udp port 123
# 沒有現成服務時,臨時監聽一個空閒連接埠(部分 nc 版本要寫成 nc -u -l -p 9999)
nc -u -l 9999
# 客戶端:發一行文字過去,伺服器視窗裡出現這行字就說明 UDP 能到達
echo hello | nc -u -w 1 203.0.113.10 9999

tcpdump 看得到請求、卻沒有應答,問題在服務本身;連請求都看不到,問題在路上的防火牆、安全組或 ACL。

5. 暴露在公網的 UDP 服務要防反射放大。 攻擊者偽造受害者的源位址,向開放的 UDP 服務發小請求,服務把大得多的應答發給受害者。開放遞迴的 DNS、NTP、SNMP、Memcached(UDP 11211)、SSDP(UDP 1900)都曾被這樣大規模利用。不需要對公網提供的 UDP 服務,只監聽內網位址,或者在防火牆上限定來源;必須開放的,要限速並關閉能返回大量資料的功能。

UDP 大包與分片:MTU 要算進去

TCP 會按 MSS 把資料切成合適的段再發,UDP 不會:應用一次交給它 4000 位元組,它就生成一個 4008 位元組的資料包,超過鏈路 MTU 的部分由 IP 層分片。分片帶來三個實際問題:

  • 任何一片丟失,整個資料包作廢。UDP 沒有重傳,丟包率被放大。
  • 只有第一片帶 UDP 首部。後續分片裡沒有連接埠號,按連接埠寫的防火牆和 ACL 可能把它們丟掉,有的網路乾脆丟棄所有分片。
  • IPv6 的中間路由器不做分片。超過路徑 MTU 的包被丟棄,並回送 ICMPv6 “包過大”訊息;這條訊息再被過濾,就成了黑洞。

所以基於 UDP 的協議都會主動控制包長:DNS 社群在 2020 年的 DNS Flag Day 建議把 EDNS 緩衝區設為 1232 位元組,應答更大時讓客戶端改用 TCP;QUIC 要求路徑至少能透過 1200 位元組的 UDP 載荷,在此基礎上再探測更大的包長。機房裡用到 UDP 封裝時要把開銷算進 MTU:VXLAN 每個包多出 50 位元組(外層乙太網頭 14、IP 頭 20、UDP 頭 8、VXLAN 頭 8),承載網的 MTU 至少設為 1550,虛擬機器裡才能繼續使用 1500。

在機房裡怎麼落地

UDP 反射攻擊能成立,前提是攻擊者能發出偽造源位址的包。機房能做的,是在接入層就不讓偽造來源的流量離開:Toplink DCIM 的 IP 位址管理 統一登記每個位址歸屬哪台伺服器,交換器側開啟源位址校驗後,只放行源 IP 屬於該連接埠的流量,偽造來源的資料包直接丟棄;再配合 ARP 繫結把 IP 與伺服器網路卡的 MAC 鎖定。這些連接埠級配置在 交換器管理 裡填寫,由系統按廠商指令集下發,不用逐台登入交換器。客戶伺服器上開放了哪些 UDP 服務,仍要在伺服器防火牆和安全組裡按上文逐項收緊。

常見問題

UDP 一個包最多能裝多少資料?

IPv4 包的總長度上限是 65535 位元組,扣掉 20 位元組 IPv4 首部和 8 位元組 UDP 首部,單個 UDP 資料包最多攜帶 65507 位元組;IPv6 的載荷長度不含 40 位元組首部,上限是 65527 位元組。超過鏈路 MTU 就要 IP 分片,在常見的 1500 位元組 MTU 上,不分片能裝下的資料是 1472 位元組(IPv4)。

HTTP/3 為什麼改用 UDP?

HTTP/3 執行在 QUIC 上,QUIC 基於 UDP,在使用者態自己實現可靠傳輸、擁塞控制和加密,避免了 TCP 一個包丟失就阻塞整條連線上所有請求的問題,建連也更快。QUIC 用連線 ID 而不是 IP 和連接埠識別連線,手機在 Wi-Fi 和行動網路之間切換時,連線不必重建。

UDP 不可靠,為什麼 DNS 還用它?

DNS 的查詢和應答通常各只有一個包,丟了由客戶端超時重發即可,代價比每次查詢先做三次握手小得多。應答太大裝不下時,伺服器在應答裡置截斷標誌,客戶端再改用 TCP 重新查詢。

想看看在你的機房裡怎麼用?

從一次產品示範開始,梳理你的業務鏈路。

查看價格
服務熱線 400-112-2951

讓我們聊聊你的 IDC 業務

掃碼新增企業微信,預約產品示範或申請試用。

Toplink 企業微信二維碼

長按儲存或使用企業微信 / 微信掃描

也可致電
400-112-2951
Telegram
@TopLink88