Как заставить `nc` прослушивать порт без установки` SO_REUSEPORT`

930
MondKin

Я хочу, чтобы ncкоманда слушала порт TCP, поэтому я сделал:

nc -lv 8888 

Затем в другой консоли я проверил, получит ли другая программа, пытающаяся прослушивать тот же порт, Address already in useтип ошибки, поэтому я снова выполнил ту же команду:

nc -lv 8888 

К моему удивлению, вторая команда также преуспела. Изучая, как две программы могут прослушивать один и тот же порт TCP, я обнаружил, что это возможно, если для прослушивающего сокета открывается опция SO_REUSEPORT, поэтому я предполагаю, что nc она используется.

Как я могу ncзапретить другим программам использовать тот же порт? Мне бы хотелось, чтобы он прослушивал порт 8888 и был уверен, что это единственная программа, которая будет прослушивать этот порт.

До сих пор я был в состоянии сделать то, что я хочу, вводя socatвместе, ncкак это:

socat TCP-LISTEN:8888,fork TCP:localhost:4444 nc -lv 4444 

Поскольку socatзапрещает любую другую программу от прослушивания на том же порту.

Но возможно ли это сделать только nc?

1
Технически это может быть `SO_REUSEPORT`. Для пользователей, не знакомых с концепцией: [ссылка] (https://stackoverflow.com/q/14388706). В Linux это неплохо, потому что «все сокеты, которые хотят использовать один и тот же адрес и комбинацию портов, должны принадлежать процессам с одним и тем же эффективным идентификатором пользователя». Так что в теории вам нужно обратить внимание на то, что вы запускаете. Тем не менее, ваш вопрос оправдан. Kamil Maciorowski 6 лет назад 0
Спасибо за эту ссылку, я многому научился! Также обновил вопрос, чтобы прочитать `SO_REUSEPORT`. MondKin 6 лет назад 0

1 ответ на вопрос

2
mpromonet

Ищем один из исходных кодов netcat netcat.c в методе local_listen:

 ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); if (ret == -1) err(1, NULL);  # if defined(SO_REUSEPORT) ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); if (ret == -1) err(1, NULL); # endif 

Затем, чтобы изменить поведение, вам нужно изменить код.

Однако я провел тест с netcat-openbsd 1.105-7, который является частью Ubuntu Xenial, и кажется, что он собран без определения SO_REUSEPORT. Так как он устанавливает SO_REUSEADDR, но не SO_REUSEPORT (под ядром> 3.9), он работает так, как вы ожидаете, отказавшись запускать второй экземпляр на том же порту.

Я использую Ubuntu 18.04, так что, возможно, здесь он скомпилирован с `SO_REUSEPORT`. Облом нет никакой опции конфигурации для выключения этой опции :(. Спасибо за ваше время! MondKin 6 лет назад 0