为什么TCP服务器在接受连接后会立即发送一个FIN呢?

8

从网络数据包捕获中,我看到了以下行为,这些行为对我来说似乎相当奇怪:

Client --> Server  [SYN]
Server --> Client  [SYN, ACK]
Client --> Server  [ACK]
Server --> Client  [FIN, ACK]
Client --> Server  [ACK]
Client --> Server  [TCP Segment of a reassembled PDU] (I don't know what this means)
Server --> Client  [RST]

有什么想法,为什么会发生这种情况?
此外,服务器端口为6000。这可能会引起任何问题吗?
我还有其他疑问:
1. 为什么有一个FIN,ACK?它不应该只是FIN吗?ACK在那条消息中的含义是什么? 2. 客户端也不应该有一个FIN吗?
编辑: 经过更多分析,我发现如果文件描述符的数量超过了限制,则服务器会发送FIN。但是,在这种情况下,并没有出现文件描述符超过限制的情况。还有哪些情况可能会发生这种情况?

1
服务器是远程的还是本地的?是否有可能是滥用的 ISP 插入了虚假数据包? - R.. GitHub STOP HELPING ICE
服务器是远程的。我如何找出是否有任何虚假数据包被插入? - Jay
@Jay 关于第一点,请参阅http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtps5%2Fs5tcpcf.html - onmyway133
6个回答

19
在深入分析后,发现以下原因是问题的根源:
当客户端尝试TCP连接时,即使服务器当前没有调用accept,连接也会通过。这将会发生在服务器调用了'listen'函数并且它会一直接受连接,直到达到了backlog限制。
但是,如果应用程序进程超过了它可以使用的最大文件描述符限制,那么当服务器调用accept时,它会意识到没有可分配的文件描述符用于套接字,并失败接受调用和发送FIN到另一侧的TCP连接。
我只是想在这里发布这个发现。我仍然把答案接受为Habbie的。
感谢所有回答这个问题的人。

6

FIN通常表示对套接字的另一端调用了shutdown(..)


你的意思是说,在这种情况下调用“accept”一定会成功返回? - Jay
是的。如果没有accept(),你只会看到静默并最终超时。 - Habbie
1
好的,但是,接受请求不可能发送FIN,对吧?我的意思是,在某些错误情况下,这种情况可能发生吗? - Jay
我并不知道,确实如此。 - Habbie
嗯?不,连接是在调用accept()之前建立的 - listen()函数的backlog参数指定了可以处于此状态(已连接但尚未调用accept())的连接数。 - caf

3
我猜测连接被inetd或类似的守护进程接受,然后尝试fork并执行另一个程序来处理连接,要么fork失败(由于资源耗尽),要么exec失败(由于文件不存在、权限错误等)。

2
我认为FIN是通过调用close()而不是shutdown()发送的。
连接在等待队列中;在accept()之后,服务器决定因为任何原因(例如TCP包装器ACL或文件描述符用尽)终止它。在这种情况下,close()将文件描述符(FD)的链接计数减少1到0,因此该连接的FD完全被销毁。之后,客户端向服务器非存在的套接字发送数据,服务器必须响应RST。
如果使用了shutdown(),服务器仍然可以恢复客户端发送的数据,并且必须等待来自客户端的FIN以正常关闭连接。不会发送RST回去。
附注: close() vs shutdown()

至少可以通过 close() 发送。我在使用 OpenSSH 时遇到了同样的问题(对于一些随机连接,[SYN] / [SYN, ACK] / [ACK] / [FIN,ACK] 序列),而 sshd 调用 close() 来关闭连接;它根本不使用 shutdown() - vinc17

1

可能是TCP包装器。如果服务器进程使用了libwrap支持,它将接受连接,检查/etc/hosts.allow/etc/hosts.deny,如果被策略拒绝,则立即关闭连接。

很容易看出服务器是否正在使用libwrap:

> ldd /usr/sbin/sshd | grep libwrap
libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f1562d44000)

0

看起来服务器在接受连接后很快就调用了shutdown


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接