开发者

Strange behaviour of netcat with UDP

开发者 https://www.devze.com 2023-04-11 20:43 出处:网络
I noticed a strange behaviour working with netcat and UDP. I start an instance (instance 1) of netcat that listens on a UDP port:

I noticed a strange behaviour working with netcat and UDP. I start an instance (instance 1) of netcat that listens on a UDP port:

nc -lu -p 10000

So i launch another instance of netcat (instance 2) and try to send datagrams to my process:

nc -u 127.0.0.1 10000

I see the datagrams. But if i close instance 2 and relaunch again netcat (instance 3):

nc -u 127.0.0.1 10000

i can't see datagrams on instance 1's terminal. Obsiously the operating 开发者_运维知识库system assigns a different UDP source port at the instance 3 respect to instance 2 and the problem is there: if i use the same instance'2 source port (example 50000):

 nc -u -p 50000 127.0.0.1 10000

again the instance 1 of netcat receives the datagrams. UDP is a connection less protocol so, why? Is this a standard netcat behaviour?


When nc is listening to a UDP socket, it 'locks on' to the source port and source IP of the first packet it receives. Check out this trace:

socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(10000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
recvfrom(3, "f\n", 2048, MSG_PEEK, {sa_family=AF_INET, sin_port=htons(52832), sin_addr=inet_addr("127.0.0.1")}, [16]) = 2
connect(3, {sa_family=AF_INET, sin_port=htons(52832), sin_addr=inet_addr("127.0.0.1")}, 16) = 0

Here you can see that it created a UDP socket, set it for address reuse, and bound it to port 10,000. As soon as it received its first datagram (from port 52,832), it issued a connect system call 'connecting' it to the 127.0.0.1:52,832. For UDP, a connect rejects all packets that don't match the IP and port in the connect.


Use the -k option:

nc -l -u -k 0.0.0.0 10000
  • -k means keep-alive, that netcat keeps listening after each connection
  • -u means UDP
  • -l listening on port 10000


Having given up on netcat on my OS version this is pretty short and gets the job done:

#!/usr/bin/ruby
# Receive UDP packets bound for a port and output them
require 'socket'
require 'yaml'

unless ARGV.count == 2
  puts "Usage: #{$0} listen_ip port_number"
  exit(1)
end
listen_ip = ARGV[0]
port = ARGV[1].to_i

u1 = UDPSocket.new
u1.bind(listen_ip, port)
while true
  mesg, addr = u1.recvfrom(100000)
  puts mesg
end


As the accepted answer explains, ncat appears not to support --keep-open with the UDP protocol. However, the error message which it prints hints at a workaround:

Ncat: UDP mode does not support the -k or --keep-open options, except with --exec or --sh-exec. QUITTING.

Simply adding --exec /bin/cat allows --keep-open to be used. Both input and output will be connected to /bin/cat, with the effect of turning it an "echo server" because whatever the client sends will be copied back to it.

To do something more useful with the input, we can use the shell's redirection operators (thus requiring --sh-exec instead of --exec). To see the data on the terminal, this works:

ncat -k -l -u -p 12345 --sh-exec "cat > /proc/$$/fd/1"

Caveat: the above example sends data to the stdout of ncat's parent shell, which could be confusing if combined with additional redirections. To simply append all output to a file is more straightforward:

ncat -k -l -u -p 12345 --sh-exec "cat >> ncat.out"
0

精彩评论

暂无评论...
验证码 换一张
取 消