Що таке порти та як працюють сервіси Linux
Дізнайтеся, як працюють TCP та UDP порти. Навчіться перевіряти відкриті порти за допомогою команди ss та розрізняти well-known порти від динамічних.
Що таке порт насправді
Порт — це число, яке дозволяє одному серверу одночасно запускати багато сервісів без змішування їхнього трафіку. Ваш VPS має одну IP-адресу, але на ньому одночасно можуть працювати web-сервер, SSH-сервер і база даних. Коли приходить пакет, операційна система має визначити, якому саме сервісу він призначений. Номер порту є відповіддю. Веб-трафік іде на порт 443, SSH — на порт 22. IP-адреса доставляє пакет до вашого сервера; порт доставляє його до потрібної програми на цьому сервері.
Порт — це 16-бітне число: 16 біт дають діапазон від 0 до 65535. Число 0 зарезервовано, тому на практиці порти працюють від 1 до 65535. Порти нижче 1024 є "відомими" (well-known) портами, для відкриття яких потрібні права root. Саме тому стандартні сервіси розміщуються саме там: 22 для SSH, 80 для HTTP, 443 для HTTPS, 53 для DNS. Будь-який порт вище 1024 доступний для звичайних програм.
Існує два типи: TCP та UDP. Номер порту в одному типі відокремлений від того самого номера в іншому. TCP — це протокол з встановленням з'єднання, який використовує більшість сервісів, таких як SSH, HTTP та бази даних. UDP — це протокол без встановлення з'єднання, який використовується для таких речей, як DNS та деякі VPN. Коли ви налаштовуєте firewall, ви зазвичай вказуєте тип протоколу, наприклад 22/tcp.
Listening означає, що програма очікує на порту
Програма, яка хоче отримувати з'єднання, просить ядро "слухати" (listen) певний порт. З цього моменту порт на машині відкривається, і програма відповідає на все, що туди надходить, за умови дозволу firewall. Порт, на якому ніхто не "слухає", просто відхиляє з'єднання. Тому перше питання при будь-якій перевірці безпеки: що саме слухає порт і де.
Команда для отримання цієї відповіді — ss:
sudo ss -tlnpПрапори означають: TCP (t), лише listening-сокети (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, якщо firewall дозволяє.
[::]:80 означає те саме для IPv6: слухати на всіх IPv6-адресах, включаючи публічні. Багато програм за замовчуванням прив'язуються до цієї адреси, а в Linux сокет :: часто також приймає IPv4.
127.0.0.1:5432 означає "слухати тільки на loopback". 127.0.0.1 — це адреса, яку машина використовує для зв'язку з самою собою; вона не є маршрутизованою ззовні. Сервіс, прив'язаний до цієї адреси, доступний лише з того самого сервера, ніколи — з інтернету, незалежно від налаштувань firewall. Вищезгаданий рядок з Postgres є безпечним за своєю структурою.
Практичне правило випливає з цього: база даних, кеш або панель адміністратора, які використовують лише ваші власні додатки, мають бути прив'язані до 127.0.0.1, а не до 0.0.0.0. Якщо сервіс ніколи не слухає публічну адресу, зловмисник не зможе до нього підключитися.
Listening не означає доступність (reachable)
Ще одне розмежування допоможе уникнути плутанини. Те, що порт відкритий на машині (програма слухає порт), відрізняється від того, що порт доступний ззовні (firewall дозволяє з'єднання). Для підключення від віддаленого клієнта мають виконуватися обидві умови.
Отже, існує два рівні контролю. Ви вирішуєте, що саме слухає порт, встановлюючи адресу прив'язки (bind address) для кожного сервісу. І ви вирішуєте, що може досягти зовнішній світ, за допомогою firewall. На добре налаштованому сервері використовуються обидва методи: сервіси прив'язуються лише там, де це необхідно, а firewall забороняє все, що ви не дозволили явно. Перевірка того, що саме слухає порт за допомогою ss — це перший крок; визначення дозволів firewall — це другий крок, про який розповідається у firewalls 101 with UFW.
Тут є нюанс, на якому часто помиляються. IPv4 та IPv6 — це різні протоколи. Firewall, який налаштований лише для IPv4, залишає сервіси [::] відкритими через IPv6. Про цю конкретну пастку є окремий матеріал: the IPv6 firewall trap.
FAQ
Як побачити, які порти відкриті на моєму Linux-сервері?
Запустіть sudo ss -tlnp для TCP або sudo ss -ulnp для UDP. Це виведе список усіх listening-сокетів, їхніх портів, локальних адрес прив'язки та процесів-власників. Дивіться стовпець 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, щоб вони ніколи не були доступні ззовні.
Чи потрібно відкривати порт у firewall, щоб сервіс працював?
Тільки для сервісів, до яких мають доступ інші машини. Сервісу, прив'язаному до 127.0.0.1, не потрібні правила firewall, оскільки зовнішній доступ до нього неможливий у будь-якому разі. Сервісу на 0.0.0.0 або [::] потрібне правило firewall для дозволу трафіку; за замовчуванням доступ має бути заборонено, доки ви не додасте правило.
Яка різниця між TCP-портом та UDP-портом?
TCP — це протокол з встановленням з'єднання, який використовується більшістю сервісів, таких як SSH, web-сервери та бази даних. UDP — це протокол без встановлення з'єднання, який використовується DNS та деякими VPN. Однакові числа в TCP та UDP — це різні порти, тому 53/tcp та 53/udp — це різні порти. Коли ви пишете правила firewall, ви вказуєте протокол, наприклад 22/tcp.