Короткий ответ
На host.example или Windows-сервере в LISTEN оказался порт, которого нет в матрице: снимите PID, бинарь, адрес bind (0.0.0.0 vs 127.0.0.1 vs LAN). Закройте слушателя: остановить сервис, bind на localhost, firewall drop с WAN. Не ufw disable и не Windows Firewall Off «чтобы сравнить». Не оставляйте reverse-shell порт «на пять минут для отладки».
Связка: процесс, brute если это 22/3389, изоляция.
Симптомы и как отличить
- Скан периметра: на белом IP открыто то, чего не должно.
ss -lntp::4444,:8089,:9200на*:.- Windows:
Get-NetTCPConnection -State Listenнеожиданный LocalPort. - Приложение «временно» слушает 0.0.0.0.
| Bind | Смысл |
|---|---|
127.0.0.1:3306 | только локально, не «открыто в интернет» пока нет проброса |
10.0.10.55:445 | LAN, всё равно ACL |
0.0.0.0:2375 | Docker API без TLS — инцидент |
[::]:22 | IPv6 тоже WAN, если нет фильтра |
Возможные причины
- Malware / reverse listener.
- Админ открыл debug (
python -m http.server, Docker 2375). - Новый микросервис без заявки.
- Проброс на периметре забыли, на хосте слушали давно.
- Kubelet/node-exporter на всех интерфейсах.
- Легитимный, но не занесён в матрицу.
Диагностика
1. Список слушателей
Linux host.example:
ss -lntup
sudo lsof -iTCP -sTCP:LISTEN -P -n
sudo nft list ruleset | head
sudo ufw status verboseWindows:
Get-NetTCPConnection -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess |
Sort-Object LocalPort
Get-NetFirewallProfile | Select-Object Name, Enabled
Get-NetFirewallRule -Direction Inbound -Enabled True | Where-Object { $_.Action -eq 'Allow' } |
Select-Object DisplayName, Profile -First 402. Сопоставить PID
sudo lsof -nP -iTCP:4444 -sTCP:LISTEN
tr '\0' ' ' < /proc/$(sudo lsof -t -iTCP:4444 -sTCP:LISTEN | head -1)/cmdline; echo
sudo sha256sum /proc/$(sudo lsof -t -iTCP:4444 -sTCP:LISTEN | head -1)/exe$conn = Get-NetTCPConnection -State Listen -LocalPort 4444
Get-Process -Id $conn.OwningProcess | Format-List Id, Path, ProcessName
Get-FileHash -Algorithm SHA256 -Path (Get-Process -Id $conn.OwningProcess).Path3. Доступен ли с WAN
Со своего внешнего канала, свой белый IP. Если с LAN порт виден, с WAN нет — проблема bind+firewall всё равно для IR, если bind 0.0.0.0.
Не используйте случайные онлайн-сканеры третьих лиц как единственную истину (они же видят вас).
Решение
Сценарий A. Чужой процесс
Изоляция, артефакты, остановка процесса, firewall deny на всякий. Переустановка по решению.
Сценарий B. Своё приложение, ошибочный bind
- Перевести listen на
127.0.0.1или внутренний IP. - Firewall: WAN drop этот порт.
- Перезапуск сервиса штатным unit, не kill.
- Обновить матрицу портов.
# пример ограничения UFW (порт подставьте свой из ss)
sudo ufw deny 4444/tcp
sudo ufw statusNew-NetFirewallRule -DisplayName 'IR deny 4444' -Direction Inbound -LocalPort 4444 -Protocol TCP -Action BlockСценарий C. Нужен доступ только с jump
Allow list 10.0.99.0/24 (mgmt), не 0.0.0.0/0. Не «открыть на час с любого».
WAN, IPv6 и «временно для отладки»
Сверьте матрицу портов с фактическим ss на host.example и, если веб крутится рядом, с IIS на Windows. Часто «неизвестный порт» — забытый docker -p 0.0.0.0:8080, а не C2. Это всё равно инцидент конфигурации: с WAN его видно как открытый сервис. IPv6 ([::]:порт) обходит правила, написанные только для IPv4: проверьте ss -lntup и nft ip6.
С внешнего LTE сканируйте свой белый, не соседний. Результат open при LAN-фильтре «закрыто» = DNAT на шлюзе: чините периметр, не только unit. Пользователь ivan.petrov мог поднять python3 -m http.server на WS-042 — тогда это ПК, не сервер; изоляция ПК, не ufw disable на host.example.
После закрытия слушателя повторите скан через 15 минут: compose/Restart= поднимает bind снова. Запрет в unit (BindTo/RestrictAddressFamilies) и firewall — оба слоя.
Как проверить, что проблема устранена
ss/Get-NetTCPConnection: порта нет или bind только localhost.- Скан своего WAN: порт filtered/closed.
- Firewall Enabled.
- Hash/процесс в тикете, если был чужой.
- Матрица обновлена.
Повторный внешний скан с LTE через 15 минут — обязателен, IPv6 отдельно.
Не оставляйте «debug listen» до понедельника: к утру сканеры интернета уже в логах. Если порт нужен бизнесу — allow list jump WS-042 админов (лучше mgmt VLAN), не 0.0.0.0/0. Пользователь ivan.petrov без заявки не имеет права держать LISTEN на сервере. Повторите ss -lntup после reboot: @reboot cron и Restart=always вернут bind. Сверьте firewall profile Domain vs Public на Windows — после смены сети правило Allow могло включиться само не то.
Если не помогло
- WAN всё ещё открыт — DNAT на периметре, чините шлюз, не только хост.
- Слушает UDP, вы смотрели TCP —
ss -lntup. - Docker публикует
-p 0.0.0.0снова после compose up — правьте YAML, не только nft. - Windows dynamic RPC — не каждый высокий порт зло; сверяйте приложение. Не открывайте RPC на WAN.
Профилактика
- Матрица порт–сервис–владелец.
- Дефолт deny WAN.
- CI/ansible не публикует debug-порты.
- Регулярный свой скан периметра.
- IPv6 в тех же правилах, что IPv4. Повторный скан своего WAN после закрытия bind обязателен, в том числе UDP.
FAQ
localhost:8080 — тоже инцидент?
Низкий приоритет, если нет проброса и нет локального untrusted user. На shared-хосте — смотрите, кто ещё на машине.
Можно ли оставить порт и «спрятать» смены номером?
Нет. Security through obscurity не заменяет фильтр.
ss без sudo не показывает PID
Это нормально. Для IR нужны права, иначе не закроете чужой bind.
Слушает на 10.0.10.55, не на 0.0.0.0
Всё ещё LAN-риск. ACL между VLAN. Для «интернета» проверьте NAT.
Windows «порты миллионов» в Listen
Много HTTP.sys/IIS/WinRM. Сверяйте с ролью сервера, не баните 80 на внутреннем веб.