Вопрос Проверьте, доступен ли порт в удаленной системе (без telnet)


В прежние времена мы использовали telnet чтобы увидеть, открыт ли порт на удаленном хосте: telnet hostname port будет пытаться подключиться к любому порту на любом хосте и предоставить вам доступ к необработанному потоку TCP.

В наши дни системы, над которыми я работаю, не устанавливают telnet (по соображениям безопасности), и все исходящие подключения ко всем хостам блокируются по умолчанию. Со временем можно легко потерять информацию о том, какие порты открыты для хостов.

Есть ли другой способ проверить, открыт ли порт в удаленной системе - с использованием системы Linux с ограниченным количеством установленных пакетов и telnet недоступно?


251
2017-07-19 16:54


происхождения


Связанный: проверить статус одного порта на удаленном хосте на SO - kenorb


ответы:


Бэшу удалось получить доступ TCP а также UDP порты на некоторое время. На странице руководства:

/dev/tcp/host/port
    If host is a valid hostname or Internet address, and port is an integer port number
    or service name, bash attempts to open a TCP connection to the corresponding socket.
/dev/udp/host/port
    If host is a valid hostname or Internet address, and port is an integer port number
    or service name, bash attempts to open a UDP connection to the corresponding socket.

Поэтому вы можете использовать что-то вроде этого:

xenon-lornix:~> cat < /dev/tcp/127.0.0.1/22
SSH-2.0-OpenSSH_6.2p2 Debian-6
^C pressed here

Таа Даа!


214
2017-07-22 10:37



Это также, по-видимому, работает в MinGW, Например, удаленный VNC сервер на 192.168.2.100 отвечает «RFB 003.008», используя «cat </dev/tcp/192.168.2.100/5900». - Peter Mortensen
Однако на портах, которые не были открыты, он был отключен через 22 секунды (попробовал Ubuntu 14.04 (Trusty Tahr) для удаленного сервера). Интересно, что период таймаута намного короче, чем для nc (см. ответ thnee). - Peter Mortensen
@lornix, хорошо, но в этом случае я должен получить тот же результат с использованием nc без опции -z, но он все равно не работает: # nc -v -w5 127.0.0.1 18080 Подключение к 127.0.0.1 18080 порт [tcp / *] удалось! # cat </dev/tcp/127.0.0.1/18080 Просто зависает без каких-либо результатов. Просто хочу понять, когда я могу использовать опцию «/ dev / tcp / host / port» - Alexandr
@Alexandr ... на самом деле, «зависает без какого-либо результата» - это довольно ожидаемое поведение. Кот ждет ввода. Северная Каролина имеет дополнительные умения, позволяющие ему воспринимать ожидающие отсутствия данные и перестает пытаться. Кот не довольно как умный. Пытаться cat < /dev/tcp/localhost/22, вы должны получить свой заголовок sshd. Очевидно, ваш процесс на порту 18080 ждет чего-то, прежде чем отправить что-нибудь. Порт 22 (SSH) приветствует вас своей версией и еще много чего. Попробуйте! - lornix
@lornix, большое спасибо за объяснение! Теперь ограничение ясно. Я думаю, что использование nc должно быть предпочтительным способом проверки портов. - Alexandr


Хороший и многословный! Из справочных страниц.
Один порт:

nc -zv 127.0.0.1 80

Несколько портов:

nc -zv 127.0.0.1 22 80 8080

Диапазон портов:

nc -zv 127.0.0.1 20-30

294
2017-12-03 21:34



Похоже, это самый лучший ответ, спасибо. ;-) - lpapp
Это повешено при попытке Ubuntu 14.04 (Trusty Tahr) для удаленного сервера (той же локальной сети) для закрытых портов (он был отключен через 127 секунд), что не очень подходит для скриптов. Это действительно работало, хотя для службы, у которой был открыт порт. Использование опции «-w2» может быть решением. - Peter Mortensen
Используйте опцию -u для портов UDP. - Efren
В версии 6.4 ncat -z не распознается. Мне удалось обойтись без z - smishra
Вы можете проверить несколько диапазонов: nc -zv 127.0.0.1 22,80,8080,20-30,443-446 (nc Версия: 1.107-4). - bobbel


Netcat - полезный инструмент:

nc 127.0.0.1 123 &> /dev/null; echo $?

Выйдет 0 если порт 123 открыт и 1 если он закрыт.


96
2017-07-19 18:07



Это гораздо более элегантный и сценарируемый ответ, чем мой собственный. Мне жаль, что системные системные администраторы, которые скрывали telnet также удерживается nc (хотя - странно - не curlили wget). - Steve HHH
Да, это совершенно произвольно и глупо. - thnee
Пусть FOR заявления начинаются! - Chad Harrison
Это повешено при попытке Ubuntu 14.04 (Trusty Tahr) для удаленного сервера (той же локальной сети) для закрытых портов (время ожидания примерно через 127 секунд), что не очень подходит для скриптов. Это действительно работало, хотя для службы, у которой был открытый порт, возвращается 0. Использование варианта «-w2» может быть решением. - Peter Mortensen
я думаю -G 2 было бы более подходящим для тайм-аута TCP - A B


Простейший метод, не используя другой инструмент, такой как socat, как описано в ответе @ lornix выше. Это просто добавление фактического примера того, как можно было бы использовать psuedo-устройство /dev/tcp/... в Bash, если вы хотите, скажем, проверить, доступен ли другой сервер, доступный через командную строку.

Примеры

Скажем, у меня есть хост в моей сети с именем skinner,

$ (echo > /dev/tcp/skinner/22) >/dev/null 2>&1 \
    && echo "It's up" || echo "It's down"
It's up

$ (echo > /dev/tcp/skinner/222) >/dev/null 2>&1 && \
    echo "It's up" || echo "It's down"
It's down

Причина, по которой вы хотите echo > /dev/... в круглых скобках, подобных этому, (echo > /dev/...) потому что, если вы этого не сделаете, то с проверками соединений, которые не работают, вы получите эти типы сообщений.

$ (echo > /dev/tcp/skinner/223) && echo hi
bash: connect: Connection refused
bash: /dev/tcp/skinner/223: Connection refused

Их нельзя просто перенаправить на /dev/null поскольку они исходят от попытки вывести данные на устройство /dev/tcp, Таким образом, мы фиксируем весь этот вывод в пределах подкоманды, т. Е. (...cmds...) и перенаправить вывод подкоманды.


48
2017-09-02 17:59



Это отлично. Хотелось бы, чтобы его проголосовали до вершины. Я только читал это далеко по странице, потому что я случайно прокрутил его до его закрытия. - Still.Tony
@ Okuma.Tony - да, это всегда проблема с Q, у которой много ответов 8-). Спасибо за отзыв, хотя, это ценно. - slm


я нашел это curl может выполнить работу аналогично telnet, а также curl даже скажет вам, какой протокол ожидает слушатель.

Создайте HTTP-URI из имени хоста и порта в качестве первого аргумента для curl, Если curl может подключиться, он сообщит о несоответствии протокола и выходе (если слушатель не является веб-службой). Если curl не может подключиться, он будет тайм-аут.

Например, порт 5672 на хосте 10.0.0.99 либо закрыт, либо заблокирован брандмауэром:

$ curl http://10.0.0.99:5672
curl: (7) couldn't connect to host

Однако, из другой системы, порт 5672 на хосте 10.0.0.99 может быть достигнут, и, как представляется, выполняется прослушиватель AMQP.

$ curl http://10.0.0.99:5672
curl: (56) Failure when receiving data from the peer
AMQP

Важно различать разные сообщения: первый сбой состоял в том, что curl не удалось подключиться к порту. Второй сбой - это тест успеха, хотя curl ожидал прослушиватель HTTP вместо прослушивателя AMQP.


35
2017-07-19 17:05



Если curl недоступен, wget может быть. wget -qS -O- http://ip.add.re.ss:port должен эффективно делать то же самое. - Michael Kjörling
Это даже работает с именем хоста, например. curl myhost:22, - 에이바
Это может быть неверно. Я хожу на службу tomcat, но получаю ошибку 404. # curl -k 192.168.194.4:6443 <html> <head> <title> Apache Tomcat / 7.0.34 - Отчет об ошибке </ title> <style> <! - H1 --- HR {color: # 525D76;} -> </ style> </ head> <body> <h1> Статус HTTP 404 - / </ h1> <HR size = "1" noshade = "noshade"> <p> <b> type </ b> Отчет о состоянии </ p> <p> <b> сообщение </ b> <u> / </ u> </ p> <p> <b> описание </ b> <u> Запрошенный ресурс недоступен. </ u> </ p> HR size = "1" noshade = "noshade"> <h3> Apache Tomcat / 7.0.34 </ h3> </ body> </ html> - Mohammad Shahid Siddiqui
Смотрите мой после с аналогичным подходом. - kenorb


[admin@automation-server 1.2.2]# nc -v -z -w2 192.168.193.173 6443
nc: connect to 192.168.193.173 port 6443 (tcp) failed: Connection refused

[admin@automation-server 1.2.2]# nc -v -z -w2 192.168.194.4 6443
Connection to 192.168.194.4 6443 port [tcp/sun-sr-https] succeeded!

Надеюсь, он решает вашу проблему :)


8
2018-06-02 06:27



Да, это лучше - выключение почти сразу для закрытых портов. - Peter Mortensen
Всегда ли это использует TCP или есть ли способ проверить UDP? - kmoe


Вот однострочный:

</dev/tcp/localhost/11211 && echo Port is open || echo Port is closed

используя синтаксис Bash, описанный в @lornix ответ,

Для получения дополнительной информации проверьте: Расширенный Bash-Scripting Guide: Глава 29. /dev а также /proc,


7
2018-03-16 11:21





Я боролся целый день, потому что ни один из этих ответов не работал для меня. Проблема в том, что самая последняя версия nc больше не имеет -z флаг, тогда как прямой доступ через TCP (как в соответствии с @lornix и @slm) терпит неудачу, когда хост недоступен. В итоге я нашел эта страница, где я, наконец, нашел не одну, а два рабочие примеры:

  1. nc -w1 127.0.0.1 22 </dev/null

    ( -w флаг выполняет тайм-аут, а </dev/null заменяет -z флаг)

  2. timeout 1 bash -c '(echo > /dev/tcp/127.0.0.1/22) >/dev/null 2>&1'

    ( timeout команда позаботится о тайм-ауте, а остальное - от @slm)

Затем просто используйте && и / или || (или даже $?), чтобы извлечь результат. Надеюсь, кто-то найдет эту информацию полезной.


5
2018-05-31 08:45