Что именно делает опция -q netcat?

У меня есть служба, поведение которой я отлаживаю за прокси. Прокси — это черный ящик, но поведение службы можно смоделировать с помощью тривиальной программы на Python, как показано ниже:

#!/usr/bin/env python

import socket
import sys
import time

PORT = int(sys.argv[1] or 50007)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    s.bind(('', PORT))
    s.listen(1)
    conn, addr = s.accept()
    print('conn from %s' % (addr,))
    data = conn.recv(1024)
    time.sleep(1)
    conn.sendall(data)
finally:
    conn.close()
    s.close()

Когда я подключаюсь к этому напрямую с помощью netcat, я получаю ожидаемое поведение, которое заключается в том, что после отправки произвольного текста на стандартный ввод с новой строкой сервер задерживается на секунду, возвращает его обратно и закрывает соединение. Однако, когда я размещаю эту службу за прокси-сервером, netcat вместо этого немедленно завершает работу со статусом 0, если я не задаю ей параметр -q с некоторым ненулевым числом, после чего она ведет себя так же, как и прямое соединение.

Чтобы процитировать справочную страницу для netcat в моей системе:

-q      after EOF on stdin, wait the specified number of seconds and then quit.
        If seconds is negative, wait forever.

Что я пытаюсь отладить, так это то, что отличается в поведении прокси-соединения, которое может привести к тому, что поведение соединения будет отличаться с опцией -q, и, к сожалению, справочная страница мало что делает, чтобы помочь меня. Что такое «stdin», на который он ссылается, если это не мой ввод (который никогда не получает от меня EOF)? Какой EOF -q игнорирует достаточно долго, чтобы получить обратно данные прокси-сервера, от которых ему не нужно игнорировать, когда нет прокси-посредника в соединении?

РЕДАКТИРОВАТЬ: По запросу вот несколько примеров вызовов, хотя они настолько просты, насколько это возможно:

# after starting the example server on <someserver> with <someport

$ echo foo | nc <someserver> <someport>
foo
$

# the above, just with -q1 (no change)
$ echo foo | nc -q1 <someserver> <someport>
foo
$

# after starting the example server behind the blackbox proxy
$ echo foo | nc <someproxy> <someproxyport>
$

# same, but with -q
$ echo foo | nc -q1 <someproxy> <someproxyport>
foo
$

person A. Wilson    schedule 21.01.2017    source источник
comment
Вы запускаете netcat интерактивно или с перенаправленным вводом?   -  person Leon    schedule 21.01.2017
comment
В зависимости от того, какой TCP-прокси вы используете, возможно, прокси-сервер буферизует ваш ввод. Может быть, nc завершает работу до того, как буфер очищается и перенаправляется на ваш сервер Python?   -  person dnswlt    schedule 21.01.2017
comment
Для @Леона: оба.   -  person A. Wilson    schedule 22.01.2017
comment
To @dnswlt: Ну, у сервера своя задержка, так в чем же разница между задержкой буфера прокси и задержкой с напрямую подключенным сервером? Поскольку я принципиально не знаю, что изменяет -q, я действительно не знаю, как сказать с большей точностью о том, может ли это быть тем или иным.   -  person A. Wilson    schedule 22.01.2017
comment
(Кроме того, когда я говорю, что прокси-сервер — это черный ящик, я на самом деле имею в виду, что не имею никакого представления о нем — нет доступа к машине, на которой он работает, нет документации о нем, нет особого способа получить о нем какое-либо представление, кроме отправки пакеты через него и посмотреть, что они делают)   -  person A. Wilson    schedule 22.01.2017
comment
Можете ли вы опубликовать точные команды, которые вы используете, а также примеры данных и результатов?   -  person Peter Gibson    schedule 24.01.2017
comment
Конечно, я так и сделал. Они противоположны сложным (я сделал этот образец сервера с целью отладки этой проблемы, так что это ожидаемо)   -  person A. Wilson    schedule 24.01.2017


Ответы (1)


echo foo | netcat отправляет EOF во всех случаях. Отличие состоит в том, как netcat закрывает свой сетевой сокет.

Без -q netcat отправляет TCP FIN сразу после получения EOF, закрывая свою половину TCP-соединения. Это не полное закрытие соединения, а просто признак того, что данных больше нет. будет отправлено. После этого netcat продолжает печатать данные из соединения, пока оно не закроется.

Обычный сервер не обрабатывает FIN от netcat, задерживает, отправляет эхо-ответ, а затем закрывает последнюю половину соединения.

Прокси-сервер черного ящика, похоже, реагирует на FIN от клиента, немедленно закрывая соединение. Это может быть какая-то оптимизация нагрузки на сервер, что имеет смысл, например, в случае с большим количеством веб-браузеров.

С -q netcat не отправляет FIN до тех пор, пока соединение не будет закрыто сервером или пока не истечет время ожидания -q.

Запустите свои четыре случая под tcpdump -w, затем загрузите файл захвата в Wireshark, следуйте потоку TCP и увидите разницу. Имейте в виду, что такое netcat поведение может зависеть от конкретной версии, Я подтверждаю это для Ubuntu 16.04 + netcat-openbsd 1.105.

person void    schedule 26.01.2017
comment
Спасибо за понимание TCP FIN, я думаю, что это объясняет большую разницу и должно быть полезно - person A. Wilson; 26.01.2017
comment
Не доверяйте мне слепо, все равно запустите tcpdump на своей системе ;) Вы получите навык, который поможет вам со всеми подобными вопросами в будущем. - person void; 27.01.2017
comment
Не волнуйтесь, это не так, и tcpdump уже является нормальной частью моего процесса отладки, я просто слишком мысленно застрял на прикладном уровне благодаря остальному контексту, который привел меня сюда. - person A. Wilson; 27.01.2017
comment
ncat: недопустимая опция -- 'q' - person JPX; 04.05.2020
comment
@JPX: это может быть в случае с сетевым котом OpenBSD - person void; 04.05.2020