Когда говорят о безопасности сервера, чаще всего спрашивают про фаервол, но сначала нужно понять, что вообще доступно извне. Служба может слушать порт и при этом быть недоступной из интернета, а может быть открытой по забытой причине. В статье — как увидеть список слушающих портов изнутри, проверить их снаружи, разобрать типичные находки и закрыть лишнее.
«Слушает» и «доступен снаружи» — не одно и то же
Служба слушает порт, когда привязана (bind) к адресу и ждёт соединений. Доступность снаружи зависит ещё от адреса привязки, фаервола на сервере и сетевых правил перед ним. Если служба привязана к 127.0.0.1, соединиться с ней можно только с самого сервера. Если к 0.0.0.0 — она принимает соединения на всех адресах, и защитить её от интернета может только фаервол. Основы портов и сокетов разобраны в статье порт, сокет и служба.
Смотрим изнутри: ss -tulpn
Команда ss из пакета iproute2 показывает сокеты. Ключи: -t — TCP, -u — UDP, -l — только слушающие, -p — процесс, -n — числовые адреса и порты. Чтобы видеть имена чужих процессов, запускайте от root.
sudo ss -tulpn
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3))
tcp LISTEN 0 80 0.0.0.0:3306 0.0.0.0:* users:(("mysqld",pid=1044,fd=21))
tcp LISTEN 0 511 127.0.0.1:8080 0.0.0.0:* users:(("nginx",pid=930,fd=6))
tcp LISTEN 0 511 [::]:80 [::]:* users:(("nginx",pid=930,fd=7))
| Адрес в Local Address | Значение |
|---|---|
| 0.0.0.0 | Все IPv4-адреса сервера; доступ ограничивает только фаервол |
| [::] | Все IPv6-адреса сервера, то же самое для IPv6 |
| 127.0.0.1 | Только петля: подключиться можно лишь с этого же сервера |
| 192.0.2.10 | Один конкретный адрес сервера |
В примере SSH и MySQL привязаны к 0.0.0.0, Nginx на порту 8080 — к 127.0.0.1, а на порту 80 слушает и на IPv6. Вопрос к такому списку один: для каждой строки с 0.0.0.0 или [::] должно быть объяснение, зачем она открыта миру.
Смотрим снаружи
Итоговая картина видна только с другой машины: с домашнего компьютера или другого сервера. Сканируйте исключительно собственные серверы. Утилита nmap покажет состояние портов, а nc — быстро проверит один порт:
nmap -Pn -p 22,80,443,3306 203.0.113.10
nc -zv 203.0.113.10 3306
Состояние open означает, что порт принимает соединения; closed — что хост отвечает, но служба не слушает; filtered — что пакеты отбрасываются фаерволом. Расхождение между ss и внешней проверкой — повод разобраться: либо фаервол работает, либо правила не применились. Другие приёмы диагностики описаны в статье диагностика сети в Linux.
Типичные находки
| Находка | Чем опасна | Что делать |
|---|---|---|
| База данных на 0.0.0.0 | Порт открыт для подбора паролей и эксплуатации уязвимостей | Привязать к 127.0.0.1 |
| Панель на нестандартном порту | Смена порта не скрывает панель от сканеров | Закрыть фаерволом или вынести за туннель |
| Забытый тестовый сервис | Часто без паролей и обновлений | Остановить и отключить из автозапуска |
| Порт Docker, опубликованный наружу | Docker сам правит правила iptables и может обойти правила фаервола | Публиковать как 127.0.0.1:порт |
Как закрывать
Лучший вариант — не открывать порт вовсе: привязать службу к 127.0.0.1. Фаервол — второй рубеж, а не замена. Типовые параметры, после правки которых службу нужно перезапустить:
bind-address = 127.0.0.1
listen_addresses = 'localhost'
bind 127.0.0.1
docker run -p 127.0.0.1:3306:3306 image
Строки относятся по порядку к MySQL (раздел [mysqld]), PostgreSQL (postgresql.conf), Redis (redis.conf) и запуску контейнера Docker. Затем включите фаервол с запретом входящих по умолчанию и разрешите только нужное: настройка показана в статье UFW для VPS. Перед включением убедитесь, что порт SSH разрешён, иначе вы потеряете доступ.
Если к закрытой службе всё же нужен доступ, публиковать порт не обязательно. Для базы подойдёт SSH-туннель: порт на вашем компьютере пробрасывается на 127.0.0.1 сервера. Для веб-панелей есть Cloudflare Tunnel.
ssh -L 3307:127.0.0.1:3306 user@203.0.113.10
Пока туннель открыт, подключайтесь клиентом базы к 127.0.0.1:3307. После любых изменений повторите ss -tulpn и внешнюю проверку: результат должен совпасть с замыслом.
Частые вопросы
Как узнать, какие порты открыты на моём сервере?
Изнутри выполните sudo ss -tulpn: команда покажет все слушающие порты и процессы. Затем проверьте сервер снаружи с другой машины через nmap или nc. Итоговой считается внешняя проверка, потому что только она учитывает фаервол и сетевые правила, а ss показывает лишь то, что слушает сама система.
Что значит 0.0.0.0 в выводе ss?
Это значит, что служба принимает соединения на всех IPv4-адресах сервера, то есть потенциально из интернета. Запись [::] означает то же для IPv6. Адрес 127.0.0.1 ограничивает доступ самим сервером. Для баз данных и служебных сервисов нужен именно 127.0.0.1, если им не требуются внешние клиенты.
Достаточно ли фаервола, чтобы закрыть лишние порты?
Фаервол необходим, но надёжнее убрать причину: служба, привязанная к 127.0.0.1, недоступна снаружи даже при ошибке в правилах. Фаервол стоит рассматривать как второй слой. Учтите и контейнеры: Docker сам меняет правила iptables, поэтому опубликованный порт может оказаться открытым вопреки настройкам UFW.
Как подключиться к закрытой базе данных с моего компьютера?
Используйте SSH-туннель: команда ssh с ключом -L пробрасывает локальный порт вашего компьютера на 127.0.0.1 сервера. Клиент базы затем подключается к локальному порту. Так порт базы остаётся закрытым для интернета, а доступ получают только те, у кого есть SSH-доступ к серверу.