J'ai remarqué un comportement étrange en travaillant avec netcat et UDP. Je démarre une instance (instance 1) de netcat qui écoute sur un port UDP:
nc -lu -p 10000
Je lance donc une autre instance de netcat (instance 2) et essaie d'envoyer des datagrammes à mon processus:
nc -u 127.0.0.1 10000
Je vois les datagrammes. Mais si je ferme l'instance 2 et relance à nouveau netcat (instance 3):
nc -u 127.0.0.1 10000
je ne peux pas voir les datagrammes sur le terminal de l'instance 1. Le système d’exploitation affecte un autre port source UDP à l’instance 3 par rapport à l’instance 2 et le problème existe: si j’utilise le même port source d’instance2 (exemple 50000):
nc -u -p 50000 127.0.0.1 10000
à nouveau l'instance 1 de netcat reçoit les datagrammes. UDP est une connexion sans protocole alors pourquoi? Est-ce un comportement standard de netcat?
Lorsque nc
écoute un socket UDP, il se "verrouille" sur le port source et l'adresse IP source du premier paquet qu'il reçoit. Découvrez cette 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
Ici, vous pouvez voir qu’il a créé un socket UDP, le configurer pour la réutilisation d’adresses et le relier au port 10 000. Dès qu'il a reçu son premier datagramme (à partir du port 52 832), il a émis un appel système connect
le "connectant" au 127.0.0.1:52 832. Pour UDP, une connect
rejette tous les paquets qui ne correspondent pas à l'adresse IP et au port dans la connect
.
Utilisez l'option-k
:
nc -l -u -k 0.0.0.0 10000
Après avoir abandonné netcat sur la version de mon système d'exploitation, ceci est assez court et donne le coup d'envoi:
#!/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
Comme l'explique la réponse acceptée, ncat
ne semble pas prendre en charge --keep-open
avec le protocole UDP. Cependant, le message d'erreur qu'il imprime suggère une solution de contournement:
Ncat: UDP mode does not support the -k or --keep-open options, except with --exec or --sh-exec. QUITTING.
Ajouter simplement --exec /bin/cat
permet d'utiliser --keep-open
. L'entrée et la sortie seront toutes deux connectées à /bin/cat
, avec pour effet de le transformer en "serveur d'écho", car les données envoyées par le client y seront copiées.
Pour faire quelque chose de plus utile avec l'entrée, nous pouvons utiliser les opérateurs de redirection du shell (nécessitant donc --sh-exec
au lieu de --exec
). Pour voir les données sur le terminal, cela fonctionne:
ncat -k -l -u -p 12345 --sh-exec "cat > /proc/$$/fd/1"
Mise en garde: l'exemple ci-dessus envoie des données à la sortie standard du parent Shell de ncat, ce qui peut prêter à confusion s'il est combiné à des redirections supplémentaires. Ajouter simplement toutes les sorties dans un fichier est plus simple:
ncat -k -l -u -p 12345 --sh-exec "cat >> ncat.out"