UDP 포트 6666을 통해 통신하려고 합니다(목표는 netconsole용 수신기를 설정하는 것이지만 여기서는 관련이 없습니다).
듣는 면에서는 nc -luv 6666
.보내는 쪽에서 . nc -uv LISTENER_IP 6666
보내고 받을 수 있고 생활이 좋습니다.
지금은 리스너를 실행 상태로 두고 발신자를 종료하고 다른 리스너를 시작합니다. 즉시 종료됩니다. 네트워크 추적에 따르면 수신 서버가ICMP 포트에 연결할 수 없습니다.. 그러나 리스너는 계속해서 다음 내용을 듣습니다.
$ sudo ss -nlup|grep 6666
UNCONN 0 0 :::6666 :::* users:(("nc",pid=3417,fd=3))
수신기를 종료하고 새 수신기를 실행합니다. 보낸 사람을 죽이기 전까지는 모든 것이 이전처럼 작동합니다.
발신자와 수신자는 동일한 네트워크에 있는 물리적 시스템입니다. 실제 머신과 그 머신에서 실행되는 가상 머신 간의 동일한 테스트는 동일한 결과를 생성합니다.
이 행동을 어떻게 설명해야 할까요?
답변1
이는 UDP "연결" 작동 방식으로 인해 예상되는 동작입니다. 이것은 논의된다nc6(1)
매뉴얼 페이지 에서socat
("UDP")이지만 다음에도 적용됩니다 nc
.
netcat6의 UDP 지원은 연결 모드와 수신 모드 모두에서 잘 작동합니다. 수신 모드에서 UDP를 사용할 때 netcat6은 선택적 주소 및/또는 포트(지정된 경우)와 일치하는 모든 소스로부터 UDP 패킷을 허용합니다. 그러나 첫 번째 패킷이 수신되면 netcat6은 해당 클라이언트로부터 후속 패킷만 수신합니다. 이는 UDP 소켓을 "연결된" 상태로 설정하여 수행됩니다(udp(4) 및 connect(2) 참조). 다른 소스의 패킷은 커널에 의해 삭제되고 ICMP 연결할 수 없음 응답이 전송됩니다.
UDP를 사용하여 원격 호스트에 연결할 때 nc6은 원격 서버가 수신 중인지 여부에 관계없이 연결이 열려 있다고 보고합니다. 이는 UDP가 연결 없는 프로토콜이므로 실제로 연결이 필요하지 않기 때문입니다. 그러나 첫 번째 패킷을 보낸 후 서버는 ICMP 연결할 수 없음 응답으로 응답할 수 있으며 이로 인해 nc6이 "연결 거부됨" 오류 메시지와 함께 종료됩니다.
발신자로부터 연결하면 임의의 UDP 소스 포트가 선택됩니다. 그런 다음 수신기는 해당 특정 쌍에 바인딩되고 host:port
해당 지점부터 다른 연결을 수신하지 않습니다. 이 문제를 해결하려면 송신자가 항상 동일한 포트를 사용하도록 강제해야 합니다. 이 예제를 사용 하는 socat
이유는 더 쉽기 때문입니다.
청중:
# socat -d -d UDP-LISTEN:6666 stdout
2018/01/29 22:02:02 socat[20969] N listening on UDP AF=2 0.0.0.0:6666
2018/01/29 22:02:07 socat[20969] N accepting UDP connection from AF=2 10.100.0.5:39000
2018/01/29 22:02:07 socat[20969] N using stdout for reading and writing
2018/01/29 22:02:07 socat[20969] N starting data transfer loop with FDs [5,5] and [1,1]
hello
bye
hello1
bye1
보내는 사람:
# socat -d -d stdin UDP:listener-host:6666
2018/01/29 22:01:56 socat[8237] N using stdin for reading and writing
2018/01/29 22:01:56 socat[8237] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:01:56 socat[8237] N successfully connected from local address AF=2 10.100.0.5:39000
2018/01/29 22:01:56 socat[8237] N starting data transfer loop with FDs [0,0] and [5,5]
hello
bye
2018/01/29 22:02:10 socat[8237] N socket 1 (fd 0) is at EOF
2018/01/29 22:02:10 socat[8237] N exiting with status 0
# socat -d -d stdin UDP:listener-host:6666
2018/01/29 22:02:13 socat[8238] N using stdin for reading and writing
2018/01/29 22:02:13 socat[8238] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:02:13 socat[8238] N successfully connected from local address AF=2 10.100.0.5:57125
2018/01/29 22:02:13 socat[8238] N starting data transfer loop with FDs [0,0] and [5,5]
hello
2018/01/29 22:02:16 socat[8238] E read(5, 0x5619f9b09330, 8192): Connection refused
2018/01/29 22:02:16 socat[8238] N exit(1)
# socat -d -d stdin UDP:listener-host:6666,sourceport=39000
2018/01/29 22:05:17 socat[8280] N using stdin for reading and writing
2018/01/29 22:05:17 socat[8280] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:05:17 socat[8280] N successfully connected from local address AF=2 10.100.0.5:39000
2018/01/29 22:05:17 socat[8280] N starting data transfer loop with FDs [0,0] and [5,5]
hello1
bye1
2018/01/29 22:05:23 socat[8280] N socket 1 (fd 0) is at EOF
2018/01/29 22:05:24 socat[8280] N exiting with status 0
보시다시피 발신자의 소스 포트가 변경되지만 강제로 동일한 포트를 재사용하면 작동합니다.