SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor

Как работают порты и прослушивание сервисов в Linux

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

Что такое порт на самом деле

Порт — это число, которое позволяет одному серверу запускать множество сервисов одновременно, не допуская смешивания их трафика. Ваш VPS имеет один IP-адрес, но на нем могут одновременно работать веб-сервер, SSH-сервер и база данных. Когда поступает пакет, операционная система должна понять, для кого он предназначен. Номер порта — это ответ. HTTPS-трафик обычно идет на порт 443, SSH — на порт 22. IP-адрес доставляет пакет на ваш сервер, а порт направляет его нужной программе на этом сервере.

Порт — это 16-битное число: 16 бит дают значения от 0 до 65535, при этом 0 зарезервирован, поэтому на практике порты используются в диапазоне от 1 до 65535. Порты ниже 1024 называются «хорошо известными» (well-known), и по умолчанию Linux позволяет открывать их только пользователю root (или программе, наделенной возможностью CAP_NET_BIND_SERVICE). Именно поэтому стандартные сервисы живут там: 22 для SSH, 80 для HTTP, 443 для HTTPS, 53 для DNS. Параметр net.ipv4.ip_unprivileged_port_start в sysctl может изменить эту границу, но по умолчанию она равна 1024. Все, что выше 1024, доступно для обычных программ.

Существует два типа портов: TCP и UDP, и номер порта в одном типе не связан с таким же номером в другом. TCP — это протокол с установлением соединения, который используют большинство сервисов, таких как SSH, HTTP и базы данных. UDP — протокол без установления соединения, используемый для таких задач, как DNS и некоторые VPN. При настройке брандмауэра вы обычно указываете тип протокола, например 22/tcp.

Состояние listening означает, что программа ожидает соединений на порту

Программа, которой необходимо принимать входящие соединения, запрашивает у ядра разрешение «слушать» порт. С этого момента порт становится открытым на машине, и программа обрабатывает все поступающие на него данные, если это разрешено межсетевым экраном. Если на порту нет слушающего процесса, он просто отклоняет соединения. Поэтому первый вопрос при любой проверке безопасности звучит так: что именно слушает порты и где это происходит.

Команда для получения ответа на этот вопрос — ss:

sudo ss -tlnp

Флаги означают использование протокола TCP (t), отображение только слушающих сокетов (l), использование числовых значений портов (n, чтобы вы видели 22, а не ssh) и вывод идентификатора процесса-владельца (p). Типичный результат выглядит так:

State   Recv-Q  Local Address:Port   Process
LISTEN  0       0.0.0.0:22           sshd
LISTEN  0       127.0.0.1:5432       postgres
LISTEN  0       [::]:80              nginx

Столбец Process показывает, какая программа владеет каждым портом. Это позволяет отследить процессы, которые вы не планировали оставлять запущенными.

Столбец Local Address — это то, что имеет значение

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

0.0.0.0:22 означает «слушать на всех IPv4-адресах, которые есть у этой машины», включая публичный. Сервис доступен из интернета по IPv4, если это разрешено брандмауэром.

[::]:80 означает то же самое для IPv6: слушать на всех IPv6-адресах, включая публичные. Многие программы по умолчанию привязываются к этому адресу, и в Linux сокет :: часто принимает и IPv4-трафик.

127.0.0.1:5432 означает «слушать только на loopback». 127.0.0.1 — это адрес, который машина использует для связи с самой собой, и при стандартных настройках ядра он недоступен извне. Сервис, привязанный к этому адресу, доступен только с того же сервера, а не из интернета, даже если брандмауэр разрешает этот порт. Упомянутая выше строка Postgres по умолчанию безопасна. Исключением является настройка ядра route_localnet: по умолчанию она выключена, но некоторые инструменты (например, kube-proxy в Kubernetes) включают её. В сочетании с правильными правилами маршрутизации или NAT трафик loopback может приходить извне. sysctl -a | grep route_localnet должен показывать = 0 в каждой строке.

Практическое правило вытекает из этого напрямую: база данных, кэш или панель администратора, которые используют только ваши собственные приложения, должны привязываться к 127.0.0.1, а не к 0.0.0.0. Если сервис никогда не слушает на публичном адресе, злоумышленнику не к чему подключаться.

«Слушает» не значит «доступен»

Еще одно различие помогает избежать путаницы. Открытый порт на машине (то есть программа слушает его) — это не то же самое, что доступность порта извне (то есть брандмауэр разрешает его). Для подключения удаленного клиента должны выполняться оба условия. Эти два типа сбоев выглядят по-разному со стороны клиента: отказ в соединении обычно означает, что никто не слушает, а зависание с последующим таймаутом обычно означает, что брандмауэр отбросил пакет, что в точности соответствует тому, о чем говорят эти две ошибки SSH.

Таким образом, существуют два уровня контроля. Вы решаете, что слушать, настраивая адрес привязки для каждого сервиса. И вы решаете, что доступно внешнему миру, с помощью брандмауэра. На хорошо настроенном сервере используются оба уровня: сервисы привязываются только там, где это необходимо, а брандмауэр запрещает все, что вы явно не разрешили. Просмотр прослушиваемых портов с помощью ss — это первый шаг; определение правил брандмауэра — второй, он описан в основах работы с брандмауэром UFW.

Здесь есть тонкий момент. IPv4 и IPv6 разделены, и брандмауэр, который покрывает только IPv4, оставляет сервисы [::] открытыми в IPv6. У этой ловушки есть отдельная статья: ловушка брандмауэра IPv6.

FAQ

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

Запустите sudo ss -tlnp для TCP или sudo ss -ulnp для UDP. Это выведет список всех прослушиваемых сокетов, порт, локальный адрес, к которому они привязаны, и процесс, которому они принадлежат. Читайте столбец Local Address: 0.0.0.0 или [::] означают, что сервис открыт для сети, а 127.0.0.1 означает, что он слушает только на самой машине.

В чем разница между 0.0.0.0 и 127.0.0.1?

0.0.0.0 означает «слушать на всех IPv4-адресах», включая публичный, поэтому сервис доступен из сети. 127.0.0.1 — это loopback, адрес, который машина использует для связи с самой собой. При стандартных настройках ядра он не маршрутизируется извне, поэтому сервис, привязанный к нему, доступен только локально. Привязывайте внутренние сервисы к 127.0.0.1, чтобы они оставались вне сети.

Нужно ли открывать порт в брандмауэре для работы сервиса?

Только для сервисов, к которым нужно обращаться с других машин. Сервису, привязанному к 127.0.0.1, не нужно правило разрешения, так как при стандартных настройках ядра никто извне не сможет к нему подключиться. Сервису на 0.0.0.0 или [::] потребуется правило разрешения, если ваш брандмауэр по умолчанию запрещает входящий трафик (что и должно быть). Если брандмауэр не активен или его политика разрешает все, сервис доступен и без правил.

В чем разница между TCP-портом и UDP-портом?

TCP — это протокол с установлением соединения, используемый большинством сервисов, таких как SSH, веб-серверы и базы данных. UDP — протокол без установления соединения, используемый DNS и некоторыми VPN. Один и тот же номер в TCP и UDP — это разные порты, поэтому 53/tcp и 53/udp — это разные вещи. При написании правил брандмауэра вы указываете протокол, например 22/tcp.