Відкриті порти — це мережеві “входи” на сервер. Через них працюють SSH, вебсервер, бази даних, панелі керування, поштові сервіси, Docker-застосунки та інші служби.

Чим більше портів відкрито назовні, тим більшою є потенційна поверхня атаки. Тому після встановлення VPS або dedicated server важливо перевірити, які сервіси слухають мережу, які з них доступні з інтернету і що справді потрібно залишити відкритим.

У цій статті розглянемо 5 основних рішень:

  1. Перевірити відкриті порти на сервері
  2. Перевірити, які порти видно ззовні
  3. Визначити, які порти справді потрібні
  4. Зупинити або обмежити зайві сервіси
  5. Закрити зайві порти через firewall

1. Перевірте відкриті порти на сервері

Спочатку потрібно зрозуміти, які сервіси взагалі слухають мережу на сервері.

Основна команда:

sudo ss -tulpn

Що означають параметри:

-t  — TCP-порти
-u  — UDP-порти
-l  — тільки listening-сокети
-p  — показати процес
-n  — не перетворювати порти та IP на імена

Приклад виводу:

Netid State  Local Address:Port  Process

tcp   LISTEN 0.0.0.0:22          users:(("sshd",pid=812,fd=3))
tcp   LISTEN 0.0.0.0:80          users:(("nginx",pid=1043,fd=6))
tcp   LISTEN 0.0.0.0:443         users:(("nginx",pid=1043,fd=7))
tcp   LISTEN 127.0.0.1:3306      users:(("mysqld",pid=1201,fd=21))

Важливо розуміти різницю:

0.0.0.0:PORT      — сервис слушает на всех интерфейсах
127.0.0.1:PORT    — сервис доступен только локально
PUBLIC_IP:PORT    — сервис слушает на публичном IP

Наприклад:

0.0.0.0:22       — SSH потенциально доступен извне
0.0.0.0:80       — HTTP доступен извне
0.0.0.0:443      — HTTPS доступен извне
127.0.0.1:3306   — MySQL доступен только локально

Альтернативно можна використовувати lsof:

sudo lsof -i -P -n | grep LISTEN

Ця команда зручна, якщо потрібно швидко побачити, який процес займає конкретний порт.

2. Перевірте, які порти видно ззовні

Команди ss і lsof показують, що слухає сам сервер. Але це не завжди означає, що порт доступний з інтернету. Firewall може блокувати зовнішній доступ.

Тому важливо перевірити сервер ззовні, наприклад через nmap з іншого комп’ютера:

nmap -Pn SERVER_IP

Перевірити конкретні порти:

nmap -Pn -p 22,80,443,3306,5432 SERVER_IP

Перевірити діапазон портів:

nmap -Pn -p 1-10000 SERVER_IP

Різниця проста:

ss/lsof  — показує, що слухає сервер
nmap     — показує, що видно ззовні

Якщо ss показує порт, але nmap ззовні його не бачить, значить порт слухається локально або закритий firewall.

Якщо nmap показує порт відкритим, значить він доступний ззовні.

3. Визначте, які порти справді потрібні

Не кожен відкритий порт є проблемою. Проблема виникає тоді, коли назовні доступний сервіс, який не має бути публічним.

Для звичайного вебсервера зазвичай достатньо:

22/tcp    — SSH, бажано тільки для довірених IP
80/tcp    — HTTP
443/tcp   — HTTPS

Інші порти потрібно перевіряти окремо.

Типові порти та рекомендації

Сервіс

Порт

Чи потрібно відкривати назовні

SSH

22/tcp

Краще тільки для довірених IP або через VPN

HTTP

80/tcp

Так, якщо сервер обслуговує сайти

HTTPS

443/tcp

Так, якщо сервер обслуговує сайти

MySQL/MariaDB

3306/tcp

Зазвичай ні

PostgreSQL

5432/tcp

Зазвичай ні

Redis

6379/tcp

Ні

MongoDB

27017/tcp

Зазвичай ні

Proxmox VE

8006/tcp

Краще тільки через VPN або allowlist

WHM/cPanel

2086/2087/tcp

Краще обмежити за IP

Plesk

8443/tcp

Краще обмежити за IP

Portainer

9000/9443/tcp

Краще обмежити за IP або VPN

Важливо
Бази даних, Redis, MongoDB і панелі керування зазвичай не мають бути відкриті для всього інтернету.

4. Зупиніть зайві сервіси або обмежте їх localhost

Якщо сервіс не потрібен, його краще зупинити й вимкнути з автозапуску.

Перевірити запущені сервіси:

systemctl --type=service --state=running

Перевірити конкретний сервіс:

systemctl status SERVICE_NAME

Зупинити сервіс:

sudo systemctl stop SERVICE_NAME

Вимкнути автозапуск:

sudo systemctl disable SERVICE_NAME

Зупинити й вимкнути одразу:

sudo systemctl disable --now SERVICE_NAME

Наприклад, якщо Apache не використовується:

sudo systemctl disable --now apache2

Після цього знову перевірте порти:

sudo ss -tulpn

Якщо сервіс потрібен, але тільки локально, його краще прив’язати до 127.0.0.1.

Наприклад, для MariaDB/MySQL:

bind-address = 127.0.0.1

Для PostgreSQL:

listen_addresses = 'localhost'

Для Redis:

bind 127.0.0.1 ::1
protected-mode yes

Після зміни конфігурації перезапустіть сервіс і перевірте порт:

sudo systemctl restart SERVICE_NAME
sudo ss -tulpn | grep PORT

Очікуваний результат для локального сервісу:

127.0.0.1:PORT

Хороша практика
Якщо база даних використовується тільки сайтом або застосунком на цьому ж сервері, не відкривайте її на публічну IP-адресу.

5. Закрийте зайві порти через firewall і перевірте Docker

Навіть якщо сервіс має працювати, це не означає, що він має бути доступний усьому інтернету. Зайві порти потрібно закрити через firewall.

Якщо використовується UFW, спочатку перевірте статус:

sudo ufw status verbose

Дозвольте тільки потрібні порти:

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Якщо SSH має бути доступний тільки з вашої IP-адреси:

sudo ufw allow from YOUR_TRUSTED_IP to any port 22 proto tcp
sudo ufw deny 22/tcp

Закрити зайвий порт, наприклад MySQL:

sudo ufw deny 3306/tcp

Увімкнути firewall:

sudo ufw enable

Перевірити правила:

sudo ufw status numbered

Попередження
Перед увімкненням firewall переконайтеся, що SSH-порт дозволений для вашої IP-адреси. Інакше можна втратити доступ до сервера.

Окремо перевірте Docker, якщо він встановлений:

docker ps

Небезпечний приклад:

0.0.0.0:5432->5432/tcp
0.0.0.0:6379->6379/tcp

Це означає, що PostgreSQL або Redis опубліковані назовні.

Якщо база даних потрібна тільки іншим контейнерам, не публікуйте її через ports.

Погано:

ports:
  - "5432:5432"

Краще:

services:
 postgres:
   image: postgres:16
   networks:
     - internal
networks:
  internal:

Важливо
Docker може публікувати порти на хості. Після запуску контейнерів завжди перевіряйте docker ps, ss -tulpn і зовнішній nmap.

Часті помилки

Відкрита база даних

Порт 3306, 5432, 6379 або 27017 відкритий на 0.0.0.0 і доступний з інтернету. Це небезпечно, особливо якщо пароль слабкий або сервіс не налаштований із додатковим захистом.

Закрили SSH і втратили доступ

Перед зміною firewall-правил завжди перевіряйте, що SSH дозволений для вашої IP-адреси. Не закривайте поточну SSH-сесію, доки не відкрили нову й не переконалися, що вхід працює.

Зупинили сервіс, але не вимкнули автозапуск

Після перезавантаження сервер знову відкриває порт, тому що сервіс залишився в автозапуску.

Docker відкрив порт назовні

У docker-compose.yml вказали:

ports:
  - "5432:5432"

У результаті база даних стала доступною з публічної IP-адреси. Якщо доступ потрібен тільки між контейнерами, використовуйте внутрішню Docker-мережу без публікації порту.

Сервіс слухає 0.0.0.0 замість 127.0.0.1

Якщо сервіс потрібен тільки локально, краще прив’язати його до localhost.

Підсумок

У цій статті ми розглянули тільки 5 основних рішень.

Для звичайного вебсервера найчастіше достатньо залишити відкритими:

22/tcp   — SSH, бажано тільки для довірених IP
80/tcp   — HTTP
443/tcp  — HTTPS

Усі інші порти мають бути або закриті, або доступні тільки з довіреної мережі, VPN чи внутрішньої Docker-мережі. Такий підхід знижує ризик атак і робить сервер безпечнішим для production-навантажень.

Tagged: