Странное поведение netcat с UDP
Я заметил странное поведение, которое работает с netcat и UDP. Я запускаю экземпляр (экземпляр 1) netcat, который прослушивает порт UDP:
nc -lu -p 10000
Итак, я запускаю еще один экземпляр netcat (экземпляр 2) и пытаюсь отправить дейтаграммы в свой процесс:
nc -u 127.0.0.1 10000
Я вижу дейтаграммы. Но если я закрою экземпляр 2 и снова запустил netcat (пример 3):
nc -u 127.0.0.1 10000
Я не могу видеть датаграммы на терминале экземпляра 1. Как ни странно, операционная система назначает другой исходный порт UDP в экземпляре 3 в отношении экземпляра 2, и проблема в том, что если я использую тот же исходный порт экземпляра2 (пример 50000):
nc -u -p 50000 127.0.0.1 10000
снова экземпляр 1 netcat получает дейтаграммы. UDP - протокол соединения меньше, так почему? Это стандартное поведение netcat?
Ответы
Ответ 1
Когда nc
прослушивает сокет UDP, он "блокируется" на исходном и исходном IP-адресах первого пакета, который он получает. Проверьте эту трассировку:
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
Здесь вы можете увидеть, что он создал UDP-сокет, установил его для повторного использования адреса и связал его с портом 10 000. Как только он получил свою первую дейтаграмму (из порта 52 832), он выпустил системный вызов connect
, "связавший" его с 127.0.0.1:52,832. Для UDP a connect
отклоняет все пакеты, которые не соответствуют IP и порту в connect
.
Ответ 2
Используйте параметр -k
:
nc -l -u -k 0.0.0.0 10000
- -k означает keep-alive, что netcat продолжает прослушивание после каждого соединения.
- -u означает UDP
- -l прослушивание порта 10000
Ответ 3
Отказавшись от netcat в моей версии ОС, это довольно коротко и выполняет свою работу:
#!/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
Ответ 4
Как объясняет принятый ответ, ncat
похоже, не поддерживает --keep-open
с протоколом UDP. Однако сообщение об ошибке, которое оно печатает, указывает на обходной путь:
Ncat: UDP mode does not support the -k or --keep-open options, except with --exec or --sh-exec. QUITTING.
Простое добавление --exec/bin/cat
позволяет использовать --keep-open
для использования. Оба входа и выхода будут подключены к /bin/cat
с эффектом превращения его в "эхо-сервер", потому что все, что отправляет клиент, будет скопировано обратно на него.
Чтобы сделать что-то более полезное с помощью ввода, мы можем использовать операторы перенаправления оболочки (для --sh-exec
требуется --sh-exec
вместо --exec
). Для просмотра данных на терминале это работает:
ncat -k -l -u -p 12345 --sh-exec "cat > /proc/$$/fd/1"
Предостережение: приведенный выше пример отправляет данные в стандартный вывод родительской оболочки ncat, что может сбивать с толку в сочетании с дополнительными перенаправлениями. Простое добавление всего вывода в файл более просто:
ncat -k -l -u -p 12345 --sh-exec "cat >> ncat.out"