Руководства

Как проверить и открыть порты в Linux

Как проверить, что порт в Linux действительно слушает, и как его открыть: команды ss и lsof, правила UFW и firewalld, и тест доступности порта снаружи сервера.

Опубликовано ~9 мин чтения

Короткий ответ: чтобы проверить открытые порты в Linux, выполните sudo ss -tulpn. Команда выводит каждый TCP- и UDP-порт, который слушает какая-нибудь программа, адрес, на котором он слушает, и сам процесс. Но «слушает» — это только половина ответа: порт доступен из интернета только тогда, когда совпали три вещи: процесс его слушает, слушает он на публичном адресе (0.0.0.0 или [::], а не 127.0.0.1), и файрвол пускает трафик. Последнюю проверку всегда делают с другой машины.

все прослушиваемые порты с их процессами
$ sudo ss -tulpn
Netid State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
udp   UNCONN 0      0      127.0.0.53%lo:53         0.0.0.0:*     users:(("systemd-resolve",pid=587,fd=14))
tcp   LISTEN 0      4096   127.0.0.53%lo:53         0.0.0.0:*     users:(("systemd-resolve",pid=587,fd=15))
tcp   LISTEN 0      4096         0.0.0.0:22         0.0.0.0:*     users:(("sshd",pid=1021,fd=3))
tcp   LISTEN 0      511          0.0.0.0:80         0.0.0.0:*     users:(("nginx",pid=1340,fd=5))
tcp   LISTEN 0      151        127.0.0.1:3306       0.0.0.0:*     users:(("mysqld",pid=1188,fd=21))
tcp   LISTEN 0      4096            [::]:22            [::]:*     users:(("sshd",pid=1021,fd=4))
tcp   LISTEN 0      511             [::]:80            [::]:*     users:(("nginx",pid=1340,fd=6))

Читайте так: SSH (22) и nginx (80) слушают на всех адресах, и IPv4, и IPv6, поэтому они открыты для сети, если файрвол не говорит иначе. MySQL (3306) слушает только на 127.0.0.1, поэтому снаружи сервера до него не достать — файрвол тут вообще ни при чём. Строки порта 53 на 127.0.0.53 разобраны ниже.

Как посмотреть прослушиваемые порты?

ss входит в iproute2 и уже установлен в Debian, Ubuntu, Rocky и Alma. В Alpine добавьте его через apk add iproute2-ss, либо используйте netstat -tulpn из BusyBox. Ключи прямо называют, что вы спрашиваете:

опции ss
-t   TCP
-u   UDP
-l   только прослушиваемые сокеты
-p   показать процесс (нужен sudo, чтобы видеть процессы других пользователей)
-n   цифрами, а не именами: 22 вместо "ssh"

sudo ss -tlnp                   # только TCP
sudo ss -ulnp                   # только UDP
sudo ss -tlnp | grep ':443'     # слушает ли что-то 443?

Важный столбец — Local Address:Port; столбец peer для прослушиваемого сокета — просто *. netstat -tulpn показывает то же самое, но принадлежит старому пакету net-tools, который современные образы Debian, Ubuntu и Rocky уже не ставят по умолчанию.

В Ubuntu 24.04 порт 22 может показывать systemd рядом с sshd или вместо него. SSH там активируется через сокет: systemd держит порт и запускает sshd, когда кто-то подключается.

Что значат 0.0.0.0, [::] и 127.0.0.1?

  • 0.0.0.0:80: любой IPv4-адрес сервера, включая публичный. Доступен снаружи, если файрвол не блокирует.
  • [::]:80: любой адрес IPv6. В Linux такой сокет обычно принимает и соединения по IPv4, если программа не попросила именно IPv6. *:80 означает то же самое: все адреса.
  • 127.0.0.1:3306 или [::1]: только loopback. Подключиться могут только программы на этом же сервере. Здесь должны жить базы данных, кеши и админ-панели.
  • Конкретный адрес, например 203.0.113.10:443: только этот один адрес — важно на серверах с несколькими IP.

127.0.0.53:53 (а на новых системах ещё и 127.0.0.54:53) — локальный DNS-stub systemd-resolved. Программы на сервере отправляют туда свои DNS-запросы, а он пересылает их настоящим резолверам. Это нормально, работает только на loopback и не является открытым DNS-сервером.

Какой процесс занимает порт?

ss уже показывает имя и PID. Чтобы спросить про один конкретный порт или воспользоваться другими утилитами:

кто сидит на порту 80?
sudo ss -ltnp 'sport = :80'                # ss с фильтром
sudo lsof -nP -iTCP:80 -sTCP:LISTEN         # lsof: прослушиваемые TCP-сокеты на 80
sudo lsof -i :80                            # любой сокет, использующий порт 80
sudo fuser 80/tcp                           # только PID (пакет psmisc)
systemctl status 1340                       # какой службе принадлежит PID 1340

Последняя строка удобна: systemctl status принимает PID и называет юнит, которому он принадлежит, так что сразу ясно, что останавливать или перенастраивать.

Пускает ли трафик файрвол?

Прослушиваемый порт всё равно закрыт снаружи, если его режет файрвол хоста. Спросите у своего файрвола:

статус файрвола
sudo ufw status verbose                    # Ubuntu, Debian с UFW
sudo firewall-cmd --list-all               # Rocky, Alma (firewalld)
sudo nft list ruleset                      # всё, как видит nftables
sudo iptables -L INPUT -n -v --line-numbers    # классический вид

Status: inactive в UFW и пустой набор правил значат, что файрвола хоста нет и каждый порт на публичном адресе открыт. Чтобы и открыть порт, и сразу закрыть всё остальное:

открыть конкретный порт
sudo ufw allow 8080/tcp
sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload

Как проверить, открыт ли порт снаружи?

Проверяйте с другой машины — своего ПК или второго сервера. Проверка с самого сервера по его публичному IP идёт через интерфейс loopback, который большинство файрволов пускает всегда, поэтому она может показать порт открытым, хотя из интернета до него не достать.

с другой машины
# Linux или macOS
nc -zv 203.0.113.10 443
# Connection to 203.0.113.10 443 port [tcp/https] succeeded!

# нет nc? bash умеет открыть TCP-соединение сам
timeout 3 bash -c '</dev/tcp/203.0.113.10/443' && echo open || echo closed

# веб-сервисы: настоящий ответ, вместе с TLS
curl -v https://example.com/

# Windows PowerShell
Test-NetConnection 203.0.113.10 -Port 443          # TcpTestSucceeded : True

# несколько портов за раз (только свои серверы)
nmap -Pn -p 22,80,443 203.0.113.10
  • Succeeded / open: что-то ответило, порт доступен.
  • Connection refused / closed: сервер ответил, но порт никто не слушает, либо правило файрвола его явно отклоняет.
  • Timed out / filtered: ответа вообще нет. Файрвол отбросил пакеты молча (по умолчанию UFW именно так отбрасывает запрещённое), адрес неверный, либо сервер не работает.

Направляйте nmap только на свои собственные машины. Для авторизованного тестирования чужих хостов нужно отдельное разрешение и сервер, где такая работа допускается правилами, например Pentesting KVM.

Почему порт открыт локально, но закрыт снаружи?

  • Он слушает на 127.0.0.1. ss показывает 127.0.0.1:ПОРТ. Поменяйте адрес привязки в настройке программы (bind-address для MySQL и MariaDB, аргумент хоста у приложения на Node или Python), перезапустите её и откройте порт в файрволе — но только если он действительно должен быть публичным.
  • Его режет файрвол. ss показывает 0.0.0.0:ПОРТ, а проверка снаружи виснет по таймауту. Добавьте правило: sudo ufw allow 8080/tcp или sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload.
  • IPv4 против IPv6. Программа, слушающая только IPv6 ([::] с флагом только-IPv6 или [::1]), недоступна по IPv4, а клиент, который предпочитает IPv6, падает, если у сервера нет ни слушателя IPv6, ни правила файрвола. Проверяйте оба явно: nc -4 -zv и nc -6 -zv.
  • Что-то между вами и сервером. Ваша собственная сеть может блокировать исходящие порты; проверьте с другого подключения, например с телефона в режиме модема.

Обратный сюрприз — порт открыт, хотя UFW должен бы его закрывать, — почти всегда дело в Docker: опубликованные порты контейнеров обходят правила UFW напрямую через iptables.

Почему UDP сложнее проверить?

У UDP нет установления соединения. С TCP закрытый порт отвечает отказом; с UDP открытый порт часто молчит, и порт за файрволом молчит точно так же. Обычная проверка поэтому не может их различить:

проверки UDP
nc -zvu 203.0.113.10 51820          # "succeeded" значит лишь то, что ошибки не было
sudo nmap -sU -p 51820 203.0.113.10  # часто пишет open|filtered по той же причине

# лучше: говорить на самом протоколе
dig @203.0.113.10 example.com        # DNS-сервер на порту 53
sudo wg show                         # WireGuard, на сервере: было ли недавнее рукопожатие?

Для UDP-сервисов надёжная проверка — настоящий клиент: DNS-запрос, подключение игрового клиента, завершённое рукопожатие VPN.

Как проверить открытые порты в Windows?

PowerShell · командная строка
netstat -ano | findstr LISTENING                   # последний столбец — PID

Get-NetTCPConnection -State Listen | Sort-Object LocalPort |
  Format-Table LocalAddress, LocalPort, OwningProcess
Get-NetUDPEndpoint | Sort-Object LocalPort         # UDP
Get-Process -Id 1234                               # какая программа — PID 1234

Чтобы открыть порт в брандмауэре Windows, добавьте входящее правило в его настройках. Проверка снаружи та же, что и для Linux: Test-NetConnection или nc с другой машины.

Как закрыть порт, который не нужен?

Остановите программу, которая его слушает. Правило файрвола прячет порт, а служба, которая не запущена, вообще не может быть атакована. По порядку предпочтения:

закрыть порт
# 1. остановить и отключить службу (и её .socket-юнит, если есть)
systemctl status 1340                    # найти юнит по PID
sudo systemctl disable --now SERVICE

# 2. оставить службу, но только локально: привязать к 127.0.0.1 в её конфиге, например
#    bind-address = 127.0.0.1           (MySQL / MariaDB)
sudo systemctl restart mariadb

# 3. убрать правило файрвола, которое его открыло
sudo ufw status numbered
sudo ufw delete 4

После этого запустите sudo ss -tulpn ещё раз и проверьте снаружи повторно. Именно эта вторая проверка и имеет значение.

Частые вопросы

Как проверить, какие порты открыты в Linux?

Выполните sudo ss -tulpn — команда выводит каждый TCP- и UDP-порт, который слушает какая-нибудь программа, адрес, на котором он слушает, и сам процесс. Порт доступен из интернета только когда совпали три вещи: его слушает процесс, слушает на публичном адресе (0.0.0.0 или [::], а не 127.0.0.1), и файрвол пускает трафик — последнее проверяют с другой машины.

Как открыть порт в Linux через UFW?

sudo ufw allow 8080/tcp открывает порт 8080 для TCP; в firewalld (Rocky, Alma) то же самое делают sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload. Status: inactive в UFW или пустой набор правил значат, что файрвола хоста нет и всё, что слушает на публичном адресе, уже открыто.

Как проверить, открыт ли порт снаружи сервера?

Проверка с самого сервера по его публичному IP идёт через loopback и может показать порт открытым, хотя из интернета до него не достать, — проверяйте с другой машины: nc -zv АДРЕС ПОРТ, Test-NetConnection в PowerShell, либо curl -v для веб-сервисов. «Connection refused» значит, что порт никто не слушает; «Timed out» — что файрвол отбросил пакеты молча.

Читайте также

Все статьи раздела