主持人A:
tar cf - stuff | dd | nc -N -l 12987
主持人B:
nc a.example.com 12987 | dd | tar tf -
在主机 A 上,完成dd
后打印其摘要tar
。因此很明显,tar 关闭了管道/文件 -> EOF
。
165040+0 条记录输入 165040+0 条记录输出 84500480 字节传输耗时 25.464802 秒(3318325 字节/秒)
两台主机都nc
高兴地坐在那里而不退出。
nc(1)
:
-N shutdown(2) the network socket after EOF on the input. Some
servers require this to finish their work.
因此,主机 A应该nc
已经看到EOF
并关闭了该死的套接字,而主机 Bnc
应该已经看到 TCP 连接终止并且应该已经关闭stdout
(stdin
/ )。dd
tar
我如何告诉在主机 B 上nc
关闭stdout
/终止并在主机 A 上终止。
nc
漏洞?
-D
(调试)什么也不做。nc
甚至无法说出它的版本号......叹
两位主持人都是FreeBSD 10.3-RELEASE-p4,仅限 IPv4。
答案1
我也对 netcat 的行为感到困惑,所以我深入研究了代码。以下是整个故事:
nc 服务器 ( nc -l
) 和客户端仅在相互连接关闭后退出。也就是说,如果每一方都发送了一个鳍数据包给对方。
服务器总是FIN
在收到FIN
客户端发来的数据包后才发送数据包。(除非服务器已经发送了数据FIN
包。)
客户端可以以下列方式发送 FIN 数据包:
- 在 stdin之后
EOF
,带参数运行时-N
- 在标准输入之后
EOF
,当服务器已经发送 FIN 数据包时
使用选项-d
stdin 将被忽略,并且nc
行为就像EOF
在 stdin 上遇到一样。
选项-N
总是暗示在标准输入上FIN
遇到后发送EOF
。
交换数据后退出nc进程的方法:
乔治的回答
server$ echo hello | nc -l -N 2000 client$ nc -d localhost 2000
发送后
hello
,服务器EOF
在 stdin 上遇到FIN
因 而发送的情况-N
。客户端收到消息,并且由于
-d
,在标准输入上看到EOF
,因此发送FIN
,因为服务器已经发送了FIN
。连接关闭,客户端和服务器均退出。
客户端发起关闭
server$ echo hello | nc -l 2000 client$ nc -dN localhost 2000
服务器
EOF
在 stdin 之后保持连接打开。客户端
EOF
在标准输入上看到并发送FIN
,因为-N
。服务器
FIN
收到客户端的后发送FIN
。连接关闭,客户端和服务器均退出。
答案2
nc
建立一个双向连接。即,它stdin
从主机 B 向主机 A 发送消息,同时从 A 向 B 发送所需的消息。
在主机 B 上使用-d
以忽略stdin
。在主机 A 上仍然需要在 EOF 上-N
关闭连接。TCP
总之
主持人A:
tar cf - stuff | dd | nc -N -l 12987
主持人B:
nc -d a.example.com 12987 | dd | tar tf -