Список відкритих портів — це список способів дістатися до вашого сервера. Усе інше — брандмауери, WAF, виявлення вторгнень — будується поверх нього. Тому «що тут слухає» стоїть першим у будь-якому аудиті, і тому ж це перевірка, яка найчастіше дає неприємну відповідь: половину з того, що спливає, відкрили не ви, а інсталятор якогось пакета.

Читаємо вивід

sudo ss -tulpn

Прапорці: t — TCP, u — UDP, l — лише те, що слухає, p — процес, n — щоб числа лишалися числами. Без sudo стовпець процесу порожній, і вправа втрачає сенс.

Важливий стовпець Local Address:Port, і різниця там принципова:

  • 127.0.0.1:3306 — служба доступна лише з самої машини. Це добре;
  • 0.0.0.0:3306 — з будь-якої адреси IPv4, тобто з інтернету. Ось це треба перевіряти;
  • [::]:3306 — те саме для IPv6. Окремий рядок, і його регулярно пропускають;
  • 203.0.113.25:443 — на конкретній адресі, зазвичай навмисно.

Далі для кожного рядка з 0.0.0.0 або [::] поставте одне питання: чи має стороння людина сюди дістатися. Для 80 і 443 відповідь — так. Майже для всього іншого — ні.

Звичні знахідки

Redis, порт 6379. Найнебезпечніший рядок там. Типово Redis не вимагає пароля, а його команди дозволяють записати файл на диск — тобто чужий ключ у authorized_keys. Між появою Redis на публічній адресі та його використанням минають години, іноді менше. Перевірте, чи є в конфігурації bind 127.0.0.1 і protected-mode yes.

Memcached, 11211/UDP. Навіть якщо всередині немає нічого цінного, ваш сервер стає підсилювачем для чужих атак — і скарга прийде від вашого ж провайдера.

MySQL і PostgreSQL, 3306 і 5432. Пароль є, але перебір проти нього йде безперервно, а версії баз оновлюють рідше, ніж хотілося б. Назовні їм майже ніколи не потрібно: застосунок живе на тій самій машині, а для власної роботи вистачить SSH-тунелю.

Elasticsearch 9200, MongoDB 27017. Історично типово без автентифікації. Їхні публічні екземпляри — постійне джерело новин про витоки даних.

API Docker, 2375. Відкритий порт керування Docker — це root на хості без жодного пароля. З’являється зазвичай після експериментів із віддаленим доступом до Docker.

Панелі керування та phpMyAdmin на власних портах: 8080, 8083, 10000. Не те щоб їх не можна було відкривати ніколи, але саме вони збирають основну масу спроб.

Виправляйте на службі, а не на брандмауері

Бажання закрити кожну знахідку правилом UFW зрозуміле, але це друга лінія, а не перша. Правило можна помилково видалити, брандмауер — тимчасово вимкнути під час налагодження, а Docker публікує порти взагалі в обхід UFW. Налаштування прив’язки у власній конфігурації служби переживає все це:

  • MySQL/MariaDB — bind-address = 127.0.0.1;
  • PostgreSQL — listen_addresses = 'localhost';
  • Redis — bind 127.0.0.1 ::1;
  • Docker Compose — публікувати як "127.0.0.1:5432:5432".

Брандмауер ставиться зверху як страховка, а не замість цього.

Як знайти процес, коли незрозуміло

ss дає назву й pid. Далі:

sudo systemctl status <pid>
sudo lsof -i :8080

Перша команда називає юніт systemd, якому належить процес, — зазвичай цього досить, щоб зрозуміти, що це й чи потрібне воно. Незнайомий процес, який слухає на високому порту й запущений поза системними каталогами — скажімо, з /tmp чи /dev/shm, — це вже не питання конфігурації, а привід для окремого розслідування.

Перевірка ззовні обов’язкова

ss відповідає на «що слухає», а не на «до чого можна дістатися». Між цим стоять брандмауер, NAT і власні правила провайдера. Єдину чесну відповідь дає сканування з іншої машини:

nmap -Pn -p- 203.0.113.25
nmap -Pn -p- -6 2001:db8::1

Не пропускайте другу команду: майже в кожного VPS є адреса IPv6, її правила пишуться окремо, а служба слухає на обох версіях протоколу одночасно.

Це не разова перевірка

Список відкритих портів змінюється сам собою. Поставили пакет — він приніс службу й відкрив порт. Оновили панель — вона повернула типове значення. Запустили контейнер — він опублікував порт в обхід брандмауера. Разова перевірка відповідає за сьогодні й не більше.

Цінність не в самому списку, а в його змінах: новий порт, якого вчора не було, — короткий і надзвичайно інформативний сигнал. Саме так за ним і варто стежити — як за знімком з історією, а не як за виводом ss, згаданим з пам’яті. Демосторінка нижче показує саме це.