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"
精彩评论