SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-21

Как проверить открытый порт в Linux: ss, nc и nmap

Узнайте, как проверить доступность порта с помощью ss, nc и nmap. Разберитесь, почему закрытый порт мгновенно сбрасывает соединение, а заблокированный межсетевым экраном зависает.

Проверка открытого порта в Linux: сначала определитесь с вопросом

Чтобы проверить, открыт ли порт в Linux, сначала решите, какой именно вопрос вы задаете, так как термин «открыт» означает разные вещи в зависимости от точки наблюдения. На самом сервере «открыт» означает, что процесс привязан к этому порту и ожидает соединений. С другого компьютера «открыт» означает, что пакет доходит до процесса и получает ответ. Если ответа нет, возникает вопрос, какое именно устройство отбросило пакет. sudo ss -ltnp отвечает на первый вопрос. nc -z или nmap отвечают на второй. Счетчики межсетевого экрана и tcpdump отвечают на третий.

Выполнение неверной проверки — частая причина потери времени. Тест, запущенный на самом сервере, не затрагивает сетевой межсетевой экран провайдера, так как этот фильтр находится за пределами системы. Если номера портов для вас в новинку, в статье как работают порты и сокеты в Linux описана модель, на которую опирается остальная часть этого руководства.

Что слушает порты на этом сервере? Читаем вывод ss

ss поставляется в составе iproute2, поэтому присутствует в каждом современном дистрибутиве. netstat является частью net-tools, который в Ubuntu не устанавливается по умолчанию уже много лет, поэтому netstat -tulpn часто отвечает netstat: command not found. Изучите ss и избежите разочарований.

sudo ss -ltnp

-l показывает только слушающие сокеты. -t ограничивает список протоколом TCP. -n выводит числа вместо разрешения имен, поэтому команда выполняется мгновенно. -p указывает процесс-владелец, для чего требуются права root: без sudo столбец Process будет пустым для всех процессов, которыми вы не владеете. Замените -t на -u, чтобы увидеть UDP.

State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
LISTEN 0      4096   127.0.0.53%lo:53    0.0.0.0:*   users:(("systemd-resolve",pid=612,fd=14))
LISTEN 0      128    0.0.0.0:22          0.0.0.0:*   users:(("sshd",pid=921,fd=3))
LISTEN 0      511    127.0.0.1:8080      0.0.0.0:*   users:(("node",pid=1442,fd=19))
LISTEN 0      128    [::]:22             [::]:*      users:(("sshd",pid=921,fd=4))

Столбец Local Address определяет всё, но именно его чаще всего пропускают при просмотре.

  • 0.0.0.0:22 означает любой IPv4-адрес на машине, поэтому сервис доступен извне, если это разрешает firewall.
  • [::]:22 — то же самое для IPv6.
  • 127.0.0.1:8080 означает только loopback. Ничто за пределами этой машины не может получить к нему доступ.
  • 10.20.0.5:5432 означает конкретный адрес интерфейса и никакой другой, что часто встречается в конфигурациях частных сетей.
  • Пустой столбец Process обычно означает отсутствие прав sudo, а не отсутствие самого процесса.

Чтобы узнать состояние конкретного порта, используйте фильтр внутри ss вместо grep по всему списку:

sudo ss -ltnp 'sport = :8080'
sudo lsof -nP -iTCP:8080 -sTCP:LISTEN
sudo fuser 8080/tcp

Пустой вывод всех трех команд означает, что порт никто не занимает. Сервис остановлен, произошел сбой при запуске или он слушает другой адрес. Прочитайте systemctl status <unit> и journalctl -u <unit> -n 50, прежде чем менять правила firewall.

Почему 127.0.0.1 в Local Address отнимает у людей полдня

Сокет, привязанный к 127.0.0.1, недоступен с другого хоста, и никакие изменения правил межсетевого экрана это не исправят. Ядро маршрутизирует 127.0.0.0/8 только на интерфейс loopback, а пакет с таким адресом назначения, пришедший на реальную сетевую карту, отбрасывается как «марсианский». В итоге процесс запущен, ss показывает, что он слушает порт, ufw allow 8080 сообщает об успехе, но соединение с вашего ноутбука всё равно не устанавливается. Оно прерывается мгновенным Connection refused, так как пакет достигает вашего публичного адреса, не находит там привязанного сокета, и ядро отвечает TCP-сбросом.

Многие программы намеренно привязываются к loopback, и для базы данных или панели администратора это правильное поведение по умолчанию. У вас есть два честных варианта. Измените адрес привязки в конфигурации самой программы (listen_addresses в postgresql.conf, bind в redis.conf, аргумент host, который принимает ваше приложение), а затем откройте порт в межсетевом экране. Либо оставьте привязку на loopback и обращайтесь к сервису через что-то другое, например, через reverse proxy Nginx или SSH-туннель с вашего ноутбука:

ssh -L 8080:127.0.0.1:8080 user@203.0.113.10

В Docker существует такое же различие во флаге публикации портов. -p 8080:8080 выполняет привязку к 0.0.0.0 и открывает доступ к контейнеру из сети. -p 127.0.0.1:8080:8080 выполняет привязку к loopback и оставляет сервис локальным.

Как проверить открыт ли порт в Linux с другого компьютера

Выполняйте этот тест из другой сети. Проверка с самого сервера подтверждает лишь работоспособность loopback-интерфейса. Даже подключение к собственному публичному IP-адресу с этого же сервера минует сетевой файрвол провайдера, так как фильтрация трафика происходит за пределами VPS.

nc -zv -w 3 203.0.113.10 443

-z устанавливает соединение и закрывает его, не передавая данные. -w 3 завершает попытку через три секунды, и этот флаг важен: без таймаута при потере пакета клиент будет повторять отправку SYN более двух минут, пока ядро не прекратит попытки. Успешный результат выглядит так:

Connection to 203.0.113.10 443 port [tcp/https] succeeded!

Если утилита отсутствует (nc: command not found), установите netcat-openbsd в Debian или Ubuntu, либо используйте встроенную функцию перенаправления сети в bash, которая не требует установки дополнительных пакетов:

timeout 3 bash -c '</dev/tcp/203.0.113.10/443' && echo open || echo "no answer"

Этот синтаксис является особенностью bash, поэтому запускайте его через bash. /bin/sh в Debian и Ubuntu — это dash, в котором нет /dev/tcp, поэтому он сообщит об отсутствии пути. Для проверки диапазона портов или если вам нужно получить именованный статус, используйте nmap для хостов, за которые вы отвечаете:

sudo nmap -Pn -p 22,80,443 203.0.113.10
sudo nmap -Pn -p 1-1024 203.0.113.10

-Pn пропускает обнаружение хоста. Большинство хостинг-провайдеров VPS блокируют ICMP echo, поэтому без -Pn nmap решит, что хост недоступен, и не будет выполнять сканирование. nmap выводит open, если был получен ответ и соединение принято, closed, если пришёл ответ сброса (reset), и filtered, если ответа не было вовсе. Для веб-сервиса curl -sS -o /dev/null -w '%{http_code}\n' https://example.com позволяет отделить сетевую ошибку от ошибки приложения, так как код состояния подтверждает, что весь путь прохождения трафика исправен.

Почему заблокированный порт вызывает зависание, а закрытый — мгновенный отказ

Мгновенный отказ. Пакет достиг машины, и система на него ответила.

nc: connect to 203.0.113.10 port 443 (tcp) failed: Connection refused

К такому результату приводят две разные причины. Либо к данному адресу и порту не привязан ни один процесс, и ядро ответило TCP-сбросом (reset), либо правило межсетевого экрана отклонило пакет с отправкой сброса или ICMP-сообщения о недоступности порта. Отказ — это однозначный ответ, который возвращается за один цикл обмена данными.

Пауза, затем таймаут. Пакет был отброшен, и в ответ не пришло ничего.

nc: connect to 203.0.113.10 port 443 (tcp) timed out: Operation now in progress

Именно так работает правило DROP, а также межсетевые экраны провайдеров или группы безопасности в облачных средах. Тишина — признак отбрасывания, так как отправитель не может отличить отброшенный пакет от ситуации, когда хост недоступен.

Симптом указывает, где искать проблему дальше. «Отказ» означает, что пакеты успешно проходят по сети, поэтому вернитесь к ss -ltnp и проверьте адрес привязки и номер порта. «Таймаут» означает, что пакеты отбрасываются, поэтому проверяйте настройки межсетевых экранов снаружи внутрь. отказ против таймаута при подключении по SSH подробно разбирает эту ситуацию для порта 22, с которой чаще всего сталкиваются пользователи.

ufw намеренно предлагает оба варианта поведения: ufw deny 8080 отбрасывает пакеты, а ufw reject 8080 отправляет отказ. В nftables используются цели drop и reject, а в iptables — -j DROP и -j REJECT. Политики по умолчанию почти всегда настроены на отбрасывание, поэтому отсутствие правила приводит к зависанию, а не к сообщению об ошибке.

Кто блокирует порт? Работаем снаружи внутрь

sudo ufw status verbose
sudo iptables -L INPUT -n -v --line-numbers
sudo nft list ruleset

Счетчики -v — это полезный инструмент. Выполните тест nc снаружи, снова запустите команду iptables и найдите счетчик, значение которого изменилось: правило, у которого растет количество пакетов, и есть то, которое обрабатывает ваш трафик. Это позволяет заменить догадки фактами.

Решающий тест выполняется на сервере; он отслеживает сетевой интерфейс в момент вашего подключения снаружи:

sudo tcpdump -ni any tcp port 8080

Если пакет SYN приходит, а SYN-ACK не уходит, значит, пакет достиг вашего VPS, но был отброшен хостом. Это означает, что сетевой экран провайдера работает корректно, а проблема кроется в локальных правилах. Отсутствие вывода означает, что пакет вообще не дошел до сервера; причина в сетевом экране провайдера, группе безопасности (security group) или неверном IP-адресе. Это различие исключает большую часть лишней работы.

Два уровня часто дают результаты, которые кажутся невозможными. Во-первых, IPv6: если у имени хоста есть запись AAAA, клиент может подключаться по IPv6, в то время как ваше правило покрывает только IPv4. Проверяйте каждое семейство протоколов с помощью nc -4 и nc -6, прежде чем доверять результатам. В правилах ufw и портах IPv6 на VPS описано, как устранить это несоответствие. Во-вторых, Docker: опубликованный порт контейнера отвечает на запросы из Интернета, даже если ufw status показывает, что этот порт закрыт, так как такие пакеты обрабатываются до того, как попадают в цепочку ufw. В почему Docker публикует порты в обход ufw описан механизм и способ исправления, а базовые правила ufw для нового VPS содержат набор настроек, которые стоит применить в первую очередь.

Почему ответы UDP неоднозначны по своей архитектуре

Протокол UDP не предусматривает рукопожатия (handshake), поэтому зондирующему запросу не с чем устанавливать соединение. nc -zu 203.0.113.10 53 завершается с кодом 0 сразу после отправки пакета; это подтверждает лишь то, что ваша машина отправила данные, но не дает информации о состоянии удаленного узла. Когда UDP-порт закрыт, хост обычно отвечает сообщением ICMP port unreachable, однако ядро сообщает об этой ошибке подключенному сокету только при следующей операции записи, поэтому при отправке одиночного пакета эта ошибка не фиксируется. Межсетевые экраны часто отбрасывают ICMP-пакеты по умолчанию, что лишает нас даже этой подсказки. Именно поэтому nmap выводит open|filtered для большинства UDP-портов: отсутствие ответа характерно как для открытого сервиса, который не настроен на реакцию, так и для отфильтрованного порта.

Тестируйте UDP, используя протокол, который вас интересует. DNS-сервер отвечает на dig +short @203.0.113.10 example.com либо адресом, либо отсутствием ответа. Узел WireGuard показывает недавнюю строку latest handshake в sudo wg show. Затем подтвердите получение пакетов на стороне сервера:

sudo tcpdump -ni any udp port 51820

Если пакеты появляются в момент отправки клиентом, значит, они доходят до сервера, и проблема кроется в самом сервисе или во входной цепочке (input chain) правил фильтрации. Если пакеты отсутствуют, значит, они не достигают цели.

Контрольный список для быстрого поиска неисправностей

  1. На сервере выполните sudo ss -ltnp 'sport = :8080'. Отсутствие вывода означает, что порт не прослушивается, поэтому сначала исправьте сервис.
  2. При наличии вывода изучите столбец Local Address. Значение 127.0.0.1 означает, что доступ извне невозможен, пока вы не измените привязку адреса или не установите прокси перед сервисом.
  3. Из другой сети выполните nc -zv -w 3 <public ip> 8080.
  4. Ошибка соединения (refusal) возвращает вас к шагу 1. Адрес, порт или целевая машина не соответствуют ожидаемым.
  5. Тайм-аут означает отброшенные пакеты. Запустите sudo tcpdump -ni any tcp port 8080 на сервере и повторите тест.
  6. Пакет SYN приходит, но ответа нет: проблема в локальном файрволе. Найдите правило, счетчик которого увеличивается в sudo iptables -L INPUT -n -v.
  7. Пакет SYN не доходит: проблема в файрволе провайдера, группе безопасности (security group) или неверном IP-адресе.

FAQ

Как проверить, какие порты открыты на моем Linux-сервере?

Запустите sudo ss -ltnp для TCP и sudo ss -lunp для UDP. Каждая строка соответствует одному слушающему сокету, а столбец Local Address показывает, кто может к нему обратиться: 0.0.0.0 и [::] принимают запросы отовсюду, где это разрешено межсетевым экраном, тогда как 127.0.0.1 принимает запросы только с самой машины. Столбец Process требует прав root, поэтому запускайте команду с sudo, иначе он будет пустым. ss входит в состав iproute2 и установлен всегда; netstat является частью net-tools и обычно отсутствует.

Почему ss показывает, что сервис слушает порт, но я не могу подключиться?

Существует две основные причины, и одна команда позволяет их различить. Если в Local Address указано 127.0.0.1, сервис привязан к loopback и недоступен с других хостов, так как ядро маршрутизирует этот диапазон только на интерфейс обратной петли. Если указано 0.0.0.0, а соединения всё равно не проходят, запустите sudo tcpdump -ni any tcp port <port> на сервере и попробуйте подключиться снаружи. Если пакет SYN приходит, но ответа нет, значит, локальное правило межсетевого экрана отбрасывает его. Если пакеты не доходят вовсе, значит, они блокируются до достижения вашего VPS, обычно межсетевым экраном провайдера или группой безопасности (security group).

В чем разница между отказом в соединении и истечением времени ожидания?

Отказ — это ответ. Пакет достиг хоста и получил TCP reset или ICMP-сообщение о недоступности порта, что означает, что на этом адресе и порту никто не слушает, либо правило отклонило запрос. Истечение времени ожидания — это тишина: правило отбросило пакет и ничего не отправило в ответ, поэтому клиент повторяет попытки до тех пор, пока не сдастся. Отказ указывает на проблему с сервисом или его адресом привязки. Истечение времени указывает на межсетевой экран, и в первую очередь следует проверять тот, который ближе всего к внешней сети.

Как проверить, открыт ли UDP-порт?

Вы не можете получить достоверный ответ с помощью обычного сканирования, так как в UDP нет рукопожатия (handshake), и не отвечающий сервис выглядит так же, как отброшенный пакет. nc -zu сообщает об успехе сразу после отправки, а nmap по той же причине сообщает open|filtered. Проверяйте, используя протокол сервиса: dig +short @<host> example.com для DNS или sudo wg show для узла WireGuard с недавним рукопожатием. Чтобы убедиться, что пакеты доходят, запустите sudo tcpdump -ni any udp port <port> на сервере во время отправки запросов клиентом.

Можно ли по-прежнему использовать telnet host port для проверки порта?

Это работает для TCP, и Escape character is '^]' означает, что соединение было принято. Выйдите из программы с помощью Ctrl+], а затем quit. Две причины делают nc -z более подходящим инструментом: telnet не установлен в большинстве современных образов серверов, а nc позволяет задать таймаут через -w и возвращает код завершения, который можно проверить в скрипте. Если ни один из этих инструментов недоступен, timeout 3 bash -c '</dev/tcp/<host>/<port>' не требует установки никаких пакетов.