Всем привет. Пока тут боролся с багом, решил поделиться и с вами. Сегодня рассмотрим, как без curl/wget/telnet делать TCP/UDP-запросы. Опять же, мало кто про это знает.

Порой бывает, что на серверах нет курла, вегета (как приправа с упоротым поваром) и даже пинга. Например, в Docker-контейнерах. И установить никак. Но в Bash-скрипте или во время дебага надо протестировать приложение, службу или порт.

В общем, если столкнулся с отсутствием привычных тебе утилит, выход есть. Сейчас покажу крутые фичи.

Я обычно при дебаге использую telnet, чтобы проверить, открыт ли нужный порт на удалённой тачке. Чтобы понимать, что никакой фаервол меня не блокирует. Почему telnet? Привычка!

Проверяем, открыты ли порты 80 и 443:

:> /dev/tcp/bashdayz.ru/80
:> /dev/tcp/bashdayz.ru/443

Если порт открыт, то после выполнения команды на экран ничего не выведется. Но ты вправе получить статус через echo $?. Если вернулся 0, значит, порт открыт и всё ок. Если вернулось > 0, то пизда рулю, порт закрыт.

Есть нюанс: команда может висеть очень долго, поэтому приправляем её таймаутом:

timeout 5s bash -c ':> /dev/tcp/bashdayz.ru/80'
timeout 5s bash -c ':> /dev/tcp/bashdayz.ru/443'

Теперь, в случае если порт недоступен, мне не нужно ждать 100500 часов, пока команда завершится. Всё станет известно спустя 5 секунд. Повторюсь, что на экран никакого вывода не будет. Статус получаем через echo $?, ну ты понял.

А что означает этот непонятный символ «:>»?

Нет, это не смайлик с дятлом. Это сокращённая версия true:

true > /dev/tcp/bashdayz.ru/80

true — команда, которая всегда возвращает успешный (нулевой) код возврата. Это означает, что команда завершилась успешно, без ошибок.

Чтобы весь этот фокус работал, требуется Bash с поддержкой net-redirections (--enable-net-redirections), но, как показывает практика, такая функция в 99% включена по умолчанию, если, конечно, ты не адепт Gentoo и из исходников Bash собирал.

Аналогично можно слать UDP-запросы:

:> /dev/udp/localhost/8888

То есть синтаксис простой: /dev/протокол/хост/порт.

Давай ещё пример покажу, как с NIST Time Server получить актуальную дату и время с разных NTP:

cat </dev/tcp/time.nist.gov/13
cat </dev/tcp/time.cloudflare.com/13
cat </dev/tcp/time.windows.com/13
cat </dev/tcp/pool.ntp.org/13
cat </dev/tcp/time.google.com/13
cat </dev/tcp/time.apple.com/13
cat </dev/tcp/time.nrc.ca/13
cat </dev/tcp/time.windows.com/13

Некоторые могут не работать, санкции или хрен пойми чё с ними, но первый у меня везде работает.

Ну и как дополнительный вариант для проверки открытых портов можно использовать nc.

nc -zv bashdayz.ru 80

Тут оно на экран тебе результат сразу вывалит без всяких костылей.

nc, или netcat, — утилита, которая предоставляет возможность взаимодействия с сетью. Она может выполнять различные функции, такие как установка TCP- или UDP-соединений, передача данных между хостами, сканирование портов, создание простых серверов и т. п.

Ключ -z тестирует порт без передачи данных, а ключ -v, логично, что verbose (подробная инфа).

Да, ты скажешь, можно же через nmap это всё сделать. Да, справедливо. Но я показываю, как не пользоваться сторонними утилитами и получить желаемое с помощью Bash. Пардон за nc, но не мог его не упомянуть.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Если столкнулся с отсутствием привычных тебе утилит, выход есть.

Пользуйся, обязательно пригодится в работе и дебаге. Увидимся!