Port forwarding is amazingly useful. If you’ve never used this feature before, the tl;dr is you can bind a port on your local system to a port on a remote system. This allows you to interact with a service as if it were running on your computer (eg, connect to a database that is firewalled off).

ssh can also perform “dynamic” port forwarding. This creates a SOCKS http proxy through the remote host. Any tool that respects the https_proxy environment variable can access services on (or access the internet through) the remote server.

Example: accessing remote Kubernetes API

I run k3d on my desktop as a local kubernetes “cluster”. Sometimes I want to sit on the couch and keep working on a project. It’s easy enough to use either method to get access working as if I were sitting at my desk!

⚠️ k3d binds to 0.0.0.0 on a random port by default. I prefer to set it to 127.0.0.1 and a known port, making simple port binding more predictable.

Dynamic (socks proxy)

Easy to setup, but requires https_proxy environment variable to be set. Not all applications work out of the box.

# Starting out on my laptop, can't access kubernetes API
❯ kubectl --context k3d-blog-example get node
The connection to the server 127.0.0.1:6550 was refused - did you specify the right host or port?

❯ screen -S k3d-tunnel
...
# Inside screen window
❯ ssh -NnD 127.0.0.1:9001 $user@$desktop
...
# `Ctrl+a d` to detach from screen 
[detached from 53775.k3d-tunnel]

❯ kubectl --context k3d-blog-example get node
The connection to the server 127.0.0.1:6550 was refused - did you specify the right host or port?

# THAT'S MORE LIKE IT
❯ https_proxy=socks5://127.0.0.1:9001 kubectl --context k3d-blog-example get node
NAME                        STATUS   ROLES                  AGE    VERSION
k3d-blog-example-server-0   Ready    control-plane,master   111s   v1.20.6+k3s1

Local port binding

A little more basic, but this binds the desired port locally – effectively behaving as if the service was truly on my local system. The downside is I need to bind a new port for every service I wish to access (e.g., 8080 & 8443 to access the loadbalancer service of my local cluster).

# Starting out on my laptop, can't access kubernetes API
❯ kubectl --context k3d-blog-example get node
The connection to the server 127.0.0.1:6550 was refused - did you specify the right host or port?

❯ screen -S k3d-tunnel
...
# Inside screen window
❯ ssh -NnT -L 6550:localhost:6550 $user@$desktop
...
# `Ctrl+a d` to detach from screen 
[detached from 53775.k3d-tunnel]

❯ https_proxy=socks5://127.0.0.1:9001 kubectl --context k3d-blog-example get node
NAME                        STATUS   ROLES                  AGE    VERSION
k3d-blog-example-server-0   Ready    control-plane,master   1m   v1.20.6+k3s1