什么情况下会把 SYN 包丢弃?
什么情况下会把 SYN 包丢弃?(超详细解析)
👤 作者:凡间的八戒
🏷 标签: 计算机网络 / TCP / 传输层 / Linux 内核 / 网络协议
💬 一句话导读: 本文从内核参数、NAT 环境、队列溢出以及 SYN 攻击四个角度,彻底解析为什么服务端会丢弃 SYN 包。
🧭 一、背景
在学习 TCP 协议(三次握手、连接维护和关闭)时,遇到了一个常见但很容易忽视的问题:
在什么情况下服务器会直接丢掉客户端的 SYN 包?
SYN 是建立 TCP 连接的第一步,丢失后会导致:
- 连接建立失败
- 服务偶尔无法访问
- NAT 环境下间歇性掉线
- 线上系统莫名“抽风”
为了彻底理解这一问题,我写下了本篇博客,用最清晰的结构帮你搞懂 SYN 丢弃背后的真正原因。
🧩 二、SYN 包会被丢弃的三大典型情况
下面我按照出现概率 + 隐蔽性,从最容易造成线上事故的情况开始讲起。
Ⅰ. 开启 tcp_tw_recycle + 开启 tcp_timestamps + 客户端在 NAT 后面(最隐蔽的元凶)
这是网络领域最著名的坑,甚至坑到 Linux 官方直接把 tcp_tw_recycle 彻底删除。
🔹 1.1 tcp_tw_recycle 是什么?
它的作用是:
加速 TIME_WAIT 状态的回收,让来自同一客户端 IP 的连接能更快复用端口。
但问题是,它依赖于客户端 时间戳 monotonic(单调递增)。
🔹 1.2 tcp_timestamps 的作用
时间戳用于:
- 判断报文是否过期
- 分辨乱序报
- 作为可靠性提升机制
但时间戳会循环(32 位数字),并不绝对可靠。
🔹 1.3 NAT 环境会引发必现致命问题
NAT 的所有客户端 共享一个出口 IP。
但每个客户端时间戳不同!
于是:
- A 客户端通过 NAT 上网
- A 的 TCP 时间戳被服务端记录
- B 客户端发送 SYN
- B 的时间戳 < A 的时间戳
- 服务端认为报文过期
- ⚠ B 的 SYN 被直接丢弃
所以:
NAT + recycle = 必乱套
这也是为什么 Linux 内核从 4.12 起删除了 tcp_tw_recycle。
Ⅱ. 连接队列(半连接 / 全连接)满了,也会丢 SYN
握手队列分两种:
| 队列 | 状态 | 描述 |
|---|---|---|
| 半连接队列 | SYN_RCVD | 三次握手未完成的连接 |
| 全连接队列 | ESTABLISHED | 等待应用层 accept() |
🔸 2.1 半连接队列满(SYN 队列)
当客户端没发送第三次握手(ACK):
- TCP 会把连接放在半连接队列
- 队列满 → 新的 SYN 会被丢掉
常见原因:
- 客户端延迟大
- 防火墙丢 ACK
- SYN Flood 攻击
🔸 2.2 全连接队列满(accept 队列)
当握手完成后,如果服务器应用层太慢:
- accept() 没及时取走连接
- 队列填满
结果:
➡ 新的连接无法进入 → SYN 可能被丢或者延迟处理
典型场景:
- Web 服务处理阻塞
- 日志写入太慢
- 单线程应用卡顿
Ⅲ. 遭受 SYN Flood,但未开启 syn cookies
SYN Flood 的特点:
- 伪造源地址
- 不发送第三次握手 ACK
- 半连接队列瞬间堆满
如果没启用 syn cookies:
➡ 正常用户的 SYN 也会被丢弃。
🔹 开启 syn cookies 后情况不同
队列满时:
- 内核不占队列
- 直接根据 Cookie 算法生成 SYN+ACK
- 客户端回 ACK 后才建立连接
因此:
syn cookies 是服务器抵御 SYN Flood 的关键手段。
📝 三、总结:SYN 包被丢弃的四大原因
| 序号 | 原因 | 场景说明 |
|---|---|---|
| 1 | tcp_tw_recycle + NAT | 最隐蔽,最容易引发线上事故 |
| 2 | 半连接队列满 | 网络慢、ACK 丢失、攻击导致 |
| 3 | 全连接队列满 | 应用层 accept 太慢 |
| 4 | SYN Flood 未开启 cookies | 队列耗尽 |
🛠 四、生产环境推荐配置
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_syncookies = 1
🛑 务必关闭 tcp_tw_recycle
🛑 新内核已移除此参数,千万不要再用
💡 五、个人学习总结
写完这篇文章,我对 TCP 三次握手背后的机制、内核参数影响、NAT 行为的冲突有了更深刻理解。
尤其是:
tcp_tw_recycle为什么会造成线上随机掉线- SYN 队列与 accept 队列的真正差别
- 为什么 SYN Flood 不开启 syn cookies 会全线瘫痪
这些知识在课程学习、项目开发、甚至未来运维网络系统时都有重大价值。
