SYN 包在什么场景下会被丢弃
SYN 包被丢弃的根本原因无非以下几类:
目的地不存在:目标机器宕机或IP地址不存在。
目的地拒绝:目标机器存在,但防火墙或自身规则拒绝了连接。
目的地过载:目标机器存在且未拒绝,但资源耗尽无法处理新连接。
网络路径问题:数据包在传输过程中因路由、策略、拥塞等原因丢失。
一、在接收端(服务器端)被丢弃
这是最常见的情况,服务器或其前方的防护设备主动丢弃了 SYN 包。
端口未监听(Port Not Listening)
场景:客户端向服务器的某个端口发送 SYN 包,但该端口上没有应用程序在监听(例如,试图连接一个未启动的 Web 服务端口 8080)。
结果:服务器的协议栈会直接回复一个 RST (Reset) 包,而不是丢弃 SYN。但有时在严格的安全策略下,前方的防火墙可能会直接丢弃 SYN 包以隐藏信息。
防火墙/安全组(Firewall/Security Group)拦截
场景:这是生产环境中最常见的原因。出于安全考虑,防火墙(包括云服务商的安全组)会设置规则,只允许特定来源 IP、特定端口的流量通过。
结果:如果 SYN 包不符合任何允许(Allow)规则,它会被防火墙静默丢弃(Silently Drop)。客户端收不到任何回复(RST 或 SYN-ACK),会导致连接超时。
服务器内核参数限制 - 半连接队列满
场景:服务器收到 SYN 包后,会创建一个「半连接」(或称为 SYN_RECV 状态)的条目,并将其放入一个名为 半连接队列(syns queue) 的缓冲区。如果短时间内有海量的 SYN 包涌入(无论是正常流量还是 SYN Flood 攻击),这个队列会被打满。
结果:当队列满时,新的 SYN 包会被内核丢弃。相关的内核参数是
net.ipv4.tcp_max_syn_backlog
。检查命令:
netstat -tlnp | grep SYN_RECV
可以查看当前的半连接数量。
服务器过载(CPU、内存)
场景:服务器整体负载极高,CPU 耗尽或内存不足。
结果:操作系统协议栈没有足够的计算资源来处理新的 SYN 包,可能会导致其被丢弃或延迟处理,表现为超时。
二、在中间网络路径上被丢弃
数据包从客户端到服务器需要经过多个路由器、交换机等网络设备,这些环节也可能出问题。
路由黑洞(Routing Blackhole)
场景:由于错误的路由配置,某个路由器知道如何将数据包发送到目的地,但目的地路由器不知道如何返回。或者更常见的, asymmetric routing (非对称路由)。
结果:SYN 包能到达服务器,服务器回复的 SYN-ACK 包在返回途中因无路由而被丢弃。从客户端的角度看,SYN 包发出后无响应(超时),感觉像是 SYN 被丢弃了。
网络拥塞(Network Congestion)
场景:网络路径中的某个链路带宽已满,路由器或交换机的缓冲区溢出。
结果:路由器会根据其策略(如尾丢弃 Tail Drop)随机丢弃数据包,SYN 包也可能在其中。
中间设备策略丢弃
场景:路径中的路由器、交换机或防火墙(不仅是服务器端的)配置了访问控制列表(ACL)或限速策略(Rate Limiting)。
结果:如果 SYN 包违反了这些策略,也会被中间设备丢弃。
MTU 问题与 PMTUD 失败
场景:SYN 包本身很小,通常不会触发。但如果通信路径上某个链路的 MTU(最大传输单元)较小,并且 Path MTU Discovery (PMTUD) 机制出现问题(例如 ICMP 报文被防火墙禁用)。
结果:包含 DF(Don't Fragment)标志的大数据包(虽然不是SYN包,但SYN包也可能因为某些选项变大)会被中间路由器丢弃,并应返回一个 ICMP 需要分片的报文。如果此 ICMP 报文被阻塞,连接就会失败。
三、在发送端(客户端)被丢弃
这种情况相对少见,但也可能发生。
客户端防火墙/出站规则
场景:客户端的防火墙阻止了向外部特定端口发送 SYN 包的请求。
结果:SYN 包在离开客户端机器前就被丢弃了。
错误的源地址
场景:客户端使用了一个非本机配置的 IP 地址作为源地址发送 SYN 包(例如,伪造 IP 的 DDoS 攻击)。
结果:运营商的路由器或客户端本地的路由器会发现这个数据包「不该从这里来」,从而将其丢弃。
如何排查?
当怀疑 SYN 包被丢弃时,可以按以下顺序排查:
服务器端检查:
netstat -tlnp
:确认端口是否在监听。systemctl status firewalld
/ufw status
/ 云平台安全组:检查防火墙规则。netstat -s | grep -i listen
/ss -s
:查看是否有 SYNs to LISTEN sockets dropped 的计数。sysctl net.ipv4.tcp_max_syn_backlog
:检查半连接队列大小。
双向网络路径检查:
ping
:检查基本连通性(但注意,ICMP 和 TCP 路径可能被不同对待)。traceroute
/mtr
:追踪到目标端口(如mtr -P 80 <host>
)的路径,看在哪里中断。在客户端和服务器同时抓包:这是最权威的方法。
如果在服务器端抓包(
tcpdump -i any host <client_ip> and port <server_port>
)看不到 SYN 包,问题出在网络路径或客户端。如果看到了 SYN 包但没有回复 SYN-ACK,问题出在服务器(防火墙、队列满、应用没响应)。
如果服务器回复了 SYN-ACK 但客户端没收到,问题出在返回路径上(非对称路由、中间设备丢弃)。