UDP 协议是什么?特点、报文格式与适用场景
UDP 全称 User Datagram Protocol(用户数据报协议),由 RFC 768 定义,是 TCP/IP 传输层的两大协议之一,IP 协议号为 17。它不建立连接、不确认、不重传、不保证顺序,首部只有源端口、目的端口、长度、校验和 4 个字段共 8 字节,换来低延迟和低开销,DNS、DHCP、NTP、SNMP、音视频和 HTTP/3 都建立在它之上。
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 重新查询。