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 服务,仍要在服务器防火墙和安全组里按上文逐项收紧。