Skip to main content

SSH Tunneling

·300 words·2 mins
Yilin Fang
Author
Yilin Fang
PhD Student @ OSU CSE

SSH tunneling (also called port forwarding) allows you to access services running on a remote machine as if they were running locally. It is widely used for Jupyter Notebook, TensorBoard, databases, and internal web services on clusters.

What problem does SSH tunneling solve?
#

Assume:

  • A remote server runs a Jupyter Notebook on port 8888.
  • The server is not directly accessible from your local browser.
  • Opening firewall ports is not allowed or not safe.

SSH tunneling lets you forward a local port to a remote port through an encrypted SSH connection.

From your browser point of view:

localhost:8888  <==SSH TUNNEL==>  remote_server:8888

No public exposure of the remote server is needed.

Local port forwarding (-L)
#

The most common form of SSH tunneling is local port forwarding:

ssh -L LOCAL_PORT:REMOTE_HOST:REMOTE_PORT user@remote_server

Example:

ssh -L 8888:localhost:8888 user@remote_server

Meaning:

  • SSH listens on localhost:8888 on your local machine.
  • Any connection to localhost:8888 is forwarded to localhost:8888 on remote_server.
  • REMOTE_HOST is resolved on the remote side.

Tunnel-only connection (-N)
#

By default, SSH opens a shell session after establishing the tunnel. If you only want to create the tunnel without opening a shell, use the -N option:

ssh -N -L 8888:localhost:8888 user@remote_server

-N means:

  • Do not run a remote command.
  • Do not open a shell
  • Keep the connection open for tunneling only.

-N is required if you also use -f to run SSH in the background.

Jump hosts and bastion nodes (-J)
#

Many clusters require connecting through a login or bastion node.

Network layout:

local_machine  <==SSH==>  bastion_node  <==SSH==>  remote_server

You can use the -J option to specify a jump host:

ssh -J user@bastion_node -L 8888:localhost:8888 user@remote_server

Important notes:

  • localhost in -L refers to the final target (remote_server), not the jump host.
  • You can chain multiple jump hosts by separating them with commas: -J user@host1,user@host2.