如何使用libpcap检测系统中被拒绝的网络连接?
用libpcap检测被拒绝的TCP连接
要区分「连接被拒绝的RST」和「正常关闭/异常断开的RST」,核心是看RST出现的阶段:连接被拒绝的RST只发生在TCP三次握手未完成时(通常是客户端发SYN请求后,服务器直接回复RST拒绝),而已建立连接后的RST属于连接断开,不属于被拒绝范畴。
下面提供两种可行方案:
方案一:用BPF过滤器实现无状态检测(快速但有少量误判)
针对连接被拒绝的典型场景(客户端发SYN后收到服务器的RST+ACK/SYN+RST),可以用以下BPF过滤器:
tcp[tcpflags] & (tcp-rst | tcp-ack) == (tcp-rst | tcp-ack) and tcp.ack != 0
这个过滤器会抓取所有带RST+ACK标志的包——这类包通常是服务器对客户端SYN请求的拒绝响应(比如端口未监听、防火墙拦截)。
如果想更精准过滤初始连接阶段的RST,可以结合SYN标志(部分系统会回复SYN+RST):
tcp[tcpflags] & (tcp-rst) != 0 and (tcp[tcpflags] & (tcp-syn) != 0 or tcp[tcpflags] & (tcp-ack) != 0)
注意:这种方式可能会包含极少数已建立连接后的异常RST,但覆盖了绝大多数连接被拒绝的场景,适合快速部署。
方案二:应用层状态跟踪(精准无误差)
如果需要100%准确区分,必须在程序中维护TCP连接的状态,步骤如下:
- 先用BPF过滤器抓取所有TCP包(或至少SYN、RST、ACK包):
tcp[tcpflags] & (tcp-syn | tcp-rst | tcp-ack) != 0 - 在程序中维护一个连接状态表,记录每个连接的阶段:
- 当抓到纯SYN包(只有SYN标志,无ACK):标记该连接为「正在发起连接」。
- 当抓到SYN+ACK包:标记对应连接为「已完成半连接」。
- 当抓到ACK包(对应SYN+ACK的响应):标记连接为「已建立」。
- 当抓到RST包时,检查对应连接的状态:
- 如果连接处于「正在发起连接」或「已完成半连接」阶段:判定为连接被拒绝。
- 如果连接处于「已建立」阶段:判定为连接异常断开,不属于被拒绝范畴。
这种方式完全精准,但需要额外开发状态跟踪逻辑,适合对准确性要求高的场景。
内容的提问来源于stack exchange,提问作者Yosef
相关产品推荐
相关产品推荐

