local-forward
02 — Local forward -L
Learning objectives
- Build a loopback
-Lforward with-NandExitOnForwardFailure=yes. - Validate with one benign request and confirm who reached the destination (B).
Intuition
-L is "bring that one internal port to my 127.0.0.1."
Friend annotation — -L in one breath
You type this on A (laptop). Listener sits on your :8080. Hitting it makes B dial their :80.
ssh -N -L 127.0.0.1:8080:127.0.0.1:80 user@B
sequenceDiagram participant You as A your laptop participant B as B bastion participant C as C service :80 Note over You: Listener on A :8080 You->>You: curl 127.0.0.1:8080 You->>B: SSH channel (-L) B->>C: B dials C:80 C-->>B: response B-->>You: back through SSH
Compare with -R on whiteboard / remote-forward / the SSH Tunneling handout.
Why 127.0.0.1 here is not "my laptop"
In -L …:127.0.0.1:80, that address is resolved on B. It means "B's loopback port 80," not yours. The service on the far side sees the connection from B. Port order: left = your listen port; right = what B dials. Full myth list: whiteboard FAQ / SSH Tunneling FAQ.
Practitioner
Goal: Pull one remote service to a loopback port on A.
Shape: Listener on A; real connect opened by B.
Pattern
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:8080:INTERNAL_IP_OR_127.0.0.1:PORT \
user@B
-N— no remote shell (forwarding only; easier to watch)- Left side of
-L= where you listen - Right side = where B connects (name/IP resolved from B)
Demo steps
- Confirm what C is (lab IP/port from Academy / Poison / home lab).
- Start the command above; leave the terminal visible.
- Validate:
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080or browser to that URL. - Ask: "Who reached C?" → B.
Jump host (optional contrast)
When the need is "shell on private host," prefer jump, not a pile of -Ls:
ssh -J user@B admin@PRIVATE_HOST
Hop chain
- App on A →
127.0.0.1:LOCAL_PORT - Listener on A (loopback)
- SSH → JUMPBOX:22
- B dials
TARGET:TARGET_PORT(C’s IP, or127.0.0.1= B’s own loopback)
ssh -N -L 127.0.0.1:8080:TARGET_IP_OR_127.0.0.1:80 user@JUMPBOX
Checkpoint
- Listener shows on A:
lsof -nP -iTCP:8080 -sTCP:LISTEN - One benign request succeeds
- Ctrl-C → listener gone
Evidence: artifacts/evidence/02-L-check.md (command, ports, start/end, HTTP/TCP result).
Cite: [S-PC-01], [S-OSS-01].
Deep dive
Destination names in -L resolve on B, not A — surprises people when /etc/hosts differs [S-OSS-01 | high | primary].
Check
Listener up → benign hit → Ctrl-C → listener gone. Evidence file started.