SSH Tunneling
Overview
SSH tunneling routes traffic through an encrypted SSH connection. It requires SSH access to the pivot host and provides three modes: local port forwarding (access a remote service through a local port), remote port forwarding (expose a local service to the remote network), and dynamic port forwarding (SOCKS proxy for routing arbitrary traffic). SSH tunneling is the most reliable pivoting method when SSH access is available — no additional tools needed.
ATT&CK Mapping
- Tactic: TA0011 - Command and Control
- Technique: T1572 - Protocol Tunneling
Prerequisites
- SSH access to the pivot host (password or key)
- Target internal network reachable from the pivot host
Techniques
Local Port Forwarding (-L)
Access a service on the internal network through a local port on the attacker machine:
# Forward local port 8080 to internal_target:80 through pivot_host
ssh -L 8080:<internal_target>:80 <user>@<pivot_host>
# Now access the internal web server:
curl http://127.0.0.1:8080
# Forward local port 3306 to internal MySQL server
ssh -L 3306:<internal_db>:3306 <user>@<pivot_host>
# Multiple forwards in one command
ssh -L 8080:<web>:80 -L 3306:<db>:3306 -L 445:<dc>:445 <user>@<pivot_host>
# Background the tunnel (no interactive shell)
ssh -L 8080:<internal_target>:80 -N -f <user>@<pivot_host>
Flags:
- -L [local_port]:[target]:[target_port] — local port forwarding
- -N — do not execute remote command (tunnel only)
- -f — background the SSH process
Remote Port Forwarding (-R)
Expose a service from the attacker (or pivot host) to the remote network. Useful when the pivot host cannot initiate outbound SSH:
# Expose attacker's port 8080 on the pivot host's port 9090
ssh -R 9090:127.0.0.1:8080 <user>@<pivot_host>
# Now internal users can access attacker's service at pivot_host:9090
# Reverse SOCKS proxy (attacker's SOCKS available on pivot)
ssh -R 1080 <user>@<pivot_host>
Dynamic Port Forwarding (-D) — SOCKS Proxy
Create a SOCKS4/5 proxy that routes any traffic through the pivot host:
# Create SOCKS proxy on local port 1080
ssh -D 1080 -N -f <user>@<pivot_host>
# Use with proxychains
# Edit /etc/proxychains4.conf:
# socks5 127.0.0.1 1080
# Route any tool through the tunnel
proxychains nmap -sT -Pn -p 80,443,445 <internal_target>
proxychains nxc smb <internal_target> -u <user> -p <password>
proxychains curl http://<internal_target>
SSH over SSH (Double Pivot)
Chain SSH tunnels through multiple hosts:
# Jump through two hosts to reach a deep internal target
ssh -J <user1>@<pivot1>,<user2>@<pivot2> <user3>@<final_target>
# Dynamic SOCKS through double pivot
ssh -J <user1>@<pivot1> -D 1080 -N -f <user2>@<pivot2>
sshuttle (VPN over SSH)
sshuttle routes entire subnets through SSH without configuring individual port forwards:
# sshuttle
# https://github.com/sshuttle/sshuttle
# Route an entire subnet through the pivot
sshuttle -r <user>@<pivot_host> 10.10.10.0/24
# Multiple subnets
sshuttle -r <user>@<pivot_host> 10.10.10.0/24 172.16.0.0/16
# With SSH key
sshuttle -r <user>@<pivot_host> --ssh-cmd 'ssh -i /path/to/key' 10.10.10.0/24
# Exclude certain addresses
sshuttle -r <user>@<pivot_host> 10.10.10.0/24 -x 10.10.10.1
sshuttle uses iptables on the attacker to transparently redirect traffic — no proxychains needed.
Detection Methods
Network-Based Detection
- Long-lived SSH connections with sustained data transfer (tunnel indicators)
- SSH connections from servers that don't normally use SSH outbound
Host-Based Detection
- SSH processes with
-L,-R, or-Dflags in the command line - Multiple connections originating from a single SSH session to diverse internal hosts
Mitigation Strategies
- Disable SSH port forwarding — set
AllowTcpForwarding noinsshd_config - Disable gateway ports — set
GatewayPorts noto prevent remote port forwarding to non-localhost - Monitor SSH sessions — alert on long-lived SSH connections with unusual traffic patterns
- Network segmentation — limit which systems can be reached from SSH-accessible hosts