web-dev-qa-db-fra.com

Comportement étrange de netcat avec UDP

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?

32
MirkoBanchi

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.

40
David Schwartz

Utilisez l'option-k:

nc -l -u -k 0.0.0.0 10000
  • -k signifie garder en vie, que netcat continue d'écouter après chaque connexion
  • -u signifie UDP
  • -l écoute sur le port 10000
5

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
3
James Kay

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"
0
Todd Owen