Nmap proxychains настройка: от потерянных пакетов до рабочего сканирования за NAT

На внутреннем пентесте после получения шелла на пограничном Linux-хосте запускаю proxychains4 nmap -sS 10.30.1.0/24 по закрытой подсети — и получаю «1000 closed ports» за две секунды. По ту сторону точно живёт десяток сервисов: SSH, HTTP, MySQL. Проблема не в цели и не в Nmap — SYN-пакеты ушли напрямую с моей машины, минуя прокси целиком. Ни одной ошибки, ни одного предупреждения.
Этот сценарий ловит каждого, кто впервые пытается сканировать через proxychains. И ни одна русскоязычная статья не объясняет почему это происходит на уровне TCP-стека. Разберём причину, настроим рабочую связку и научимся проверять, куда реально уходит трафик.
Место в цепочке атаки: зачем сканировать через прокси
Сканирование через прокси — не про анонимность и не про «скрыть IP». В пентесте это шаг lateral movement (латеральное перемещение): вы уже получили foothold на одной машине и хотите обнаружить сервисы во внутренней сети, до которой ваша атакующая машина (Kali) не дотягивается напрямую.
По классификации MITRE ATT&CK (открытая база тактик и техник реальных атак; T-коды вроде T1046 — идентификаторы конкретных техник) это выглядит так:
- T1046 Network Service Discovery (тактика Discovery) — само сканирование портов и сервисов
- T1572 Protocol Tunneling (тактика Command and Control) — туннелирование трафика через SSH
- T1090.001 Internal Proxy — использование скомпрометированного хоста как внутреннего прокси
Типичная ситуация: ваша Kali находится в сети 10.38.1.0/24, pivot-хост (скомпрометированная машина) имеет два интерфейса — один в вашей сети (10.38.1.121), второй во внутренней (10.30.1.122). Цель — обнаружить сервисы на 10.30.1.0/24, куда прямого маршрута нет.
[Применимо: внутренний пентест после получения foothold, любая инфраструктура с IP-маршрутизацией между подсетями. Сценарий grey box и black box.]
По данным статьи на levelup.gitconnected.com, здесь три уровня подхода, и они не взаимозаменяемы: сканирование прямо с pivot-хоста, SOCKS-прокси через SSH или Chisel с proxychains, и полноценный TUN-туннель через ligolo-ng. Proxychains — средний уровень, с конкретным набором ограничений, которые нужно знать заранее.
Почему SYN scan молча ломается через proxychains
Это тот самый момент, на котором спотыкаются все. Чтобы понять, надо знать, как proxychains работает изнутри.
Proxychains4 (proxychains-ng — активно развиваемый форк оригинального proxychains) использует механизм LD_PRELOAD. Если вы ещё не сталкивались: это переменная окружения Linux, которая позволяет подменить стандартные библиотечные функции на свои. Proxychains подменяет функцию connect() из libc — когда приложение вызывает connect() для установки TCP-соединения, proxychains перехватывает вызов и перенаправляет его через указанный SOCKS-прокси (SOCKS5 — протокол проксирования TCP-трафика через промежуточный сервер).
А теперь ловушка. Nmap по умолчанию (при запуске от root) использует SYN scan (-sS) — half-open scan. Этот тип сканирования работает через raw sockets. Raw sockets — механизм ОС для формирования сетевых пакетов вручную, минуя стандартный TCP-стек ядра. Nmap сам собирает SYN-пакет побайтово и отправляет его напрямую через сетевой интерфейс. Функция connect() при этом не вызывается — а значит proxychains нечего перехватывать.
Результат: SYN-пакеты уходят с вашей реальной сетевой карты, минуя прокси целиком. Nmap честно отрабатывает — но сканирует напрямую, а не через туннель. Если целевая подсеть недоступна напрямую — получаете «все порты закрыты/отфильтрованы». Если подсеть доступна — получаете корректный результат, но со своего настоящего IP, полностью выдавая себя.
Самое неприятное — никакого сообщения об ошибке нет. В обсуждении на security.stackexchange.com это видно наглядно: строка Raw packets sent: 1477 прямо говорит, что пакеты отправлены через raw sockets, а не через connect(). Proxychains при этом молчит.
Тот же принцип работает для UDP-сканирования (-sU), определения ОС (-O) и ICMP-пинга — все они используют raw sockets или протоколы, которые SOCKS просто не умеет проксировать.
Настройка proxychains4 и SOCKS5-туннеля для Nmap
Требования к окружению
Прежде чем лезть в конфиги:
- ОС атакующей машины: Kali Linux (proxychains4 предустановлен) или Debian/Ubuntu (установка:
sudo apt install proxychains4) - RAM: 2 ГБ минимум для Kali + Nmap
- Доступ к pivot-хосту: SSH с возможностью dynamic port forwarding (параметр
-D). Альтернатива — возможность загрузить на pivot бинарник Chisel - Права: root на атакующей машине не обязателен для proxychains +
nmap -sT, но SSH-клиент должен быть доступен текущему пользователю - Сеть: pivot-хост должен иметь сетевой доступ к целевой подсети (проверяется с самого pivot через
pingилиip route)
Конфигурация dynamic chain в proxychains4
Файл конфигурации proxychains4 лежит в /etc/proxychains4.conf. Откройте его в текстовом редакторе и приведите к такому виду:
dynamic_chain
proxy_dns
tcp_read_time_out 8000
tcp_connect_time_out 5000
[ProxyList]
socks5 127.0.0.1 9050
Что здесь что:
dynamic_chain — режим, при котором proxychains последовательно проходит по списку прокси, пропуская недоступные. Если у вас один прокси — не критично, но при цепочке из нескольких (Multi-hop Proxy, T1090.003 в MITRE ATT&CK) эта настройка спасает от обрыва всей цепочки из-за одного мёртвого узла. Убедитесь, что строки strict_chain и random_chain закомментированы (символ # в начале) — активным может быть только один режим.
proxy_dns — DNS-запросы тоже идут через прокси. Без этой строки DNS-резолвинг идёт напрямую с вашей машины, что выдаёт реальный IP и ломает всю логику туннеля.
tcp_read_time_out 8000 — таймаут на чтение данных из TCP-соединения через прокси (в миллисекундах). Дефолтные 15000 — слишком много для сканирования, Nmap будет ждать по 15 секунд на каждый порт. 8000 мс — разумный баланс: достаточно для медленных прокси, но не превращает сканирование в пытку.
tcp_connect_time_out 5000 — таймаут на установку TCP-соединения. 5 секунд вместо дефолтных 10.
socks5 127.0.0.1 9050 — адрес и порт SOCKS5-прокси. В нашем сценарии прокси создаст SSH dynamic forwarding на localhost. Порт 9050 — дефолтный для Tor, но мы используем его для SSH-туннеля (можете взять любой свободный — 9000, 1080, что угодно).
SSH dynamic forwarding как SOCKS5 proxy
SSH-туннель с динамическим портом — самый простой способ поднять SOCKS5-прокси через pivot-хост. Команда запускается на вашей Kali:
ssh -D 9050 -f -N user@10.38.1.121
Флаг -D 9050 создаёт SOCKS5-прокси на локальном порту 9050, -f отправляет SSH в фон после аутентификации, -N говорит, что интерактивный шелл не нужен — только туннель. После выполнения на вашей машине появляется локальный SOCKS5-прокси, через который весь TCP-трафик уходит на pivot и далее в целевую подсеть.
Если SSH на pivot недоступен или закрыт файрволом — альтернатива Chisel: загружаете бинарник на pivot, запускаете в режиме client с обратным подключением к вашему серверу. Chisel создаёт тот же SOCKS5-прокси, но через обратное соединение. По данным levelup.gitconnected.com, это тот же уровень функциональности, что и SSH, с теми же ограничениями proxychains.
Проверка, что туннель живой: proxychains4 curl -s http://10.30.1.111:80 (подставьте IP внутреннего хоста). Ожидаемый результат — HTML-ответ от внутреннего веб-сервера и строки вида |S-chain|-<>-127.0.0.1:9050-<><>-10.30.1.111:80-<><>-OK в stderr. Это proxychains подтверждает, что соединение прошло через цепочку.
TCP connect scan через proxychains: рабочие флаги Nmap
Совместимость типов сканирования Nmap с proxychains
Здесь нет полутонов — либо тип сканирования использует connect(), и тогда proxychains его перехватывает, либо нет.
| Тип сканирования | Флаг Nmap | Через proxychains | Причина |
|---|---|---|---|
| TCP connect | -sT |
Да | Использует connect() — перехватывается |
| SYN (half-open) | -sS |
Нет | Raw sockets — обходит прокси |
| UDP | -sU |
Нет | SOCKS не проксирует UDP |
| OS detection | -O |
Нет | Требует raw sockets |
| Ping/ICMP | -sn |
Нет | ICMP не проходит через SOCKS |
| Version detection | -sV |
Да (с -sT) |
Работает поверх TCP-соединения |
| NSE-скрипты | --script |
Частично | TCP-скрипты — да, raw/UDP — нет |
Единственный полностью рабочий вариант — TCP connect scan с флагом -sT. Два обязательных дополнения:
-Pn— пропустить host discovery. ICMP-пинг не пройдёт через SOCKS, Nmap решит, что хост мёртв, и даже не начнёт сканирование-n— отключить DNS-резолвинг. Даже сproxy_dnsв конфиге Nmap может попытаться резолвить имена напрямую
Итоговая рабочая команда:
proxychains4 nmap -sT -Pn -n -sV -p22,80,443,3306,8080 10.30.1.111
|S-chain|-<>-127.0.0.1:9050-<><>-10.30.1.111:22-<><>-OK
|S-chain|-<>-127.0.0.1:9050-<><>-10.30.1.111:80-<><>-OK
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 4.7p1
80/tcp open http Apache httpd 2.2.8
443/tcp closed https
3306/tcp open mysql MySQL 5.0.51a
8080/tcp closed http-proxy
Каждая строка |S-chain|...<><>-OK подтверждает, что конкретное соединение прошло через прокси-цепочку. Видите TIMEOUT или вообще нет строк S-chain — трафик идёт мимо прокси.
Обратите внимание на явное указание портов через -p. Сканирование всех 65535 портов через proxychains — процесс на часы. Каждый порт — полное TCP-рукопожатие через туннель. На практике ограничивайтесь набором из 20–50 наиболее интересных портов или используйте результаты предварительной разведки (ARP-таблица pivot, ip route, netstat на pivot).
Версии сервисов и NSE-скрипты через прокси
Флаг -sV (определение версий) работает через proxychains, потому что после установки TCP-соединения Nmap отправляет сервисные пробы как обычные TCP-данные — они проходят по уже установленному соединению через прокси.
Скорость при этом падает заметно. Каждый probe — отдельный цикл «запрос через туннель → ожидание ответа → парсинг». Для ускорения: --version-intensity 2 (вместо дефолтного 7) — Nmap отправит только самые вероятные пробы, сократив число запросов в 3–4 раза.
NSE-скрипты (--script) работают через proxychains, если сам скрипт использует TCP-соединения. Скрипты категории vuln, auth, default в большинстве своём работают. Скрипты на UDP или raw packets (dns-brute, snmp-brute) — нет. На pivot-хосте с устаревшим Nmap (версия 4.x) категории скриптов вроде vuln могут вообще не поддерживаться — в лабораторном тесте из того же источника --script vuln вернул ошибку «No such category» на Nmap 4.53.
Диагностика потерь пакетов при сканировании через прокси
Три типичных причины, почему сканирование через proxychains возвращает пустые или неполные результаты.
Причина 1: трафик идёт мимо прокси. Запустите Nmap с proxychains и параллельно откройте второй терминал с sudo tcpdump -i eth0 -n 'host 10.30.1.111' (подставьте целевой IP). Если tcpdump показывает SYN-пакеты с вашего реального IP на целевой хост — трафик проходит мимо прокси. Причина почти всегда — отсутствие флага -sT (Nmap ушёл в raw sockets). Проверьте также, что вы не запустили nmap вместо proxychains4 nmap — банально, но случается чаще, чем хотелось бы.
Причина 2: SSH-туннель упал. Проверьте командой ss -tlnp | grep 9050 (утилита ss показывает открытые сокеты в системе). Если порт 9050 не слушается — SSH-сессия оборвалась. Пересоздайте туннель. Для надёжности добавьте к SSH-команде параметры -o ServerAliveInterval=30 -o ServerAliveCountMax=3 — SSH будет отправлять keepalive каждые 30 секунд и закроет сессию только после трёх неответов.
Причина 3: таймауты proxychains слишком малы. Если прокси-цепочка длинная или канал медленный, соединения обрываются до того, как Nmap получает ответ. В stderr увидите строки с TIMEOUT вместо OK. Увеличьте tcp_connect_time_out и tcp_read_time_out в /etc/proxychains4.conf. Начните с 10000/15000 и уменьшайте, когда убедитесь, что соединения проходят стабильно.
Дополнительный приём: запускайте proxychains с флагом -q (quiet mode), чтобы подавить вывод S-chain в stderr — он конфликтует с выводом Nmap и делает результат нечитаемым. По данным Varonis, -q особенно полезен при работе с инструментами вроде patator или crackmapexec, которые сами активно пишут в stderr.
Выбор метода сканирования: pivot, SOCKS proxy или TUN-туннель
Proxychains — не единственный и не всегда лучший способ сканировать внутреннюю сеть. Вот decision tree для выбора метода, основанный на данных из levelup.gitconnected.com и подтверждённый практикой:
| Ситуация | Метод | Что получаете | Ограничения |
|---|---|---|---|
| Есть shell на pivot, Nmap установлен | Сканируйте прямо с pivot | Все типы сканирования, полная скорость, -sV и -O |
Версия Nmap может быть устаревшей, нет привычных скриптов |
| Есть SSH на pivot, нужны инструменты Kali | SSH -D + proxychains |
TCP-сканирование с Kali, -sV, NSE-скрипты |
Только TCP connect, медленно, нет UDP/ICMP |
| SSH недоступен, есть загрузка файлов | Chisel + proxychains | Аналогично SSH dynamic forwarding | Те же ограничения, плюс нужно загрузить бинарник |
| Нужно полноценное сканирование без ограничений | TUN-туннель (ligolo-ng) | Все типы сканирования, UDP, ICMP | Сложнее настроить, нужен бинарник на pivot |
| Есть Meterpreter-сессия | Metasploit route + socks_proxy |
TCP через proxychains | Менее стабильно, чем SSH; только SOCKS4a |
Мой подход: начинайте с самого простого — сканирование прямо с pivot (если Nmap там есть). Переходите на proxychains, когда нужны инструменты с Kali. Переходите на ligolo-ng, когда proxychains недостаточно (нужен UDP, OS detection или полный доступ к подсети как к локальной).
При сканировании прямо с pivot используйте ту же логику: nmap -sT -Pn -sV -p <ports> <target>. В лабораторном тесте Nmap 4.53 на pivot выполнил сканирование с определением версий за 6.5 секунд — против минут через proxychains. Это ваш «ground truth», с которым можно сравнивать результаты через прокси.
Ограничения и когда не использовать proxychains с Nmap
Функциональные ограничения
Повторю явно, потому что это самый частый источник боли: через proxychains вы теряете SYN scan, UDP scan, OS fingerprinting, traceroute и ICMP discovery. Если хотя бы одно из этого критично для задачи — proxychains не подходит, используйте TUN-туннель или сканируйте с самого pivot.
Скорость: TCP connect scan через SOCKS5-прокси в 5–20 раз медленнее прямого сканирования. Каждый порт — полное TCP-рукопожатие через туннель. Сканирование /24 по 1000 портов через proxychains может занять часы. Ограничивайте диапазон портов флагом -p и используйте --max-retries 1 для сокращения повторных попыток.
Обнаружение защитными средствами
Со стороны внутренней сети сканирование выглядит так, будто его выполняет pivot-хост. Это значит:
- IDS/IPS (Suricata, Snort) на внутреннем сегменте увидят множественные TCP-подключения к разным портам от одного хоста — классический паттерн сканирования
- CrowdStrike Falcon или SentinelOne на pivot-хосте (если он мониторится) зафиксируют аномальную сетевую активность: массовые исходящие TCP-соединения к внутренним IP
- SIEM (Elastic 8.x+, MaxPatrol SIEM) может скоррелировать SSH-сессию с всплеском сетевой активности от pivot-хоста
- NSM-инструменты вроде Zeek заметят нетипичные потоки данных от хоста, который «обычно с этими серверами не общается» — это прямо упоминается в рекомендациях MITRE ATT&CK по обнаружению техники T1046
Для снижения заметности: сканируйте медленно (--scan-delay 500ms), ограничивайте количество одновременных соединений (--max-parallelism 5), разбивайте сканирование на несколько коротких сессий с разными целевыми портами.
Когда техника не работает
Работает если: pivot-хост имеет сетевой доступ к целевой подсети, SSH (или альтернативный канал) доступен с атакующей машины, целевые сервисы работают на TCP.
Не работает если: между pivot и целевой подсетью стоит stateful firewall с политикой deny-all для исходящих TCP от pivot; целевые сервисы — UDP-only (DNS, SNMP, TFTP); на pivot-хосте развёрнут EDR с мониторингом процессов и вы не можете запустить SSH/Chisel без детекта; сетевые ACL на целевой подсети разрешают подключения только с определённых source IP (а pivot в список не входит).
Отдельно про Metasploit: модуль auxiliary/server/socks_proxy создаёт SOCKS4a-прокси (не SOCKS5) поверх Meterpreter-сессии. По опыту из nullsweep.com, это менее стабильно, чем SSH-туннель. SOCKS4a не поддерживает аутентификацию и DNS-резолвинг на стороне прокси (хотя имена хостов передаёт). Если Meterpreter-сессия нестабильна — сканирование будет обрываться посередине.
Самая частая ошибка при настройке nmap proxychains — не техническая, а методологическая: люди пытаются воспроизвести полноценное сканирование с атакующей машины, а proxychains для этого просто не предназначен. Это инструмент для точечной проверки конкретных портов и сервисов, когда вы уже знаете, что искать — по результатам разведки с самого pivot (ARP-таблица, netstat, ip route, ping sweep). Попытка запустить proxychains nmap -sV -sC -p- 10.0.0.0/8 — это не сканирование, это ожидание до тепловой смерти Вселенной.
Если нужен полноценный доступ к внутренней сети — поднимайте TUN-туннель через ligolo-ng. Он создаёт виртуальный сетевой интерфейс на вашей Kali, и вы получаете маршрутизацию к внутренней подсети как к локальной. Все типы сканирования, UDP, ICMP — всё работает. Но это уже другой уровень сложности и другая статья. В proxychains4 критично понять одну вещь: его потолок — TCP connect, и весь ваш workflow должен строиться вокруг этого ограничения, а не вопреки ему. Если только начинаешь разбираться в сетевой безопасности и пентесте — на IB Basics подобные вещи разбирают от самых основ, без требования «вы должны знать Linux на уровне X».
Эту тему и смежные навыки разбирают на практике в курсе «Специалист по тестированию на проникновение» Codeby Academy.