Contents

ssh-via-cloudflare-tunnel: Alternative way to expose machines behind NAT

Contents

I have an intermittent issue where one of my machines on a specifc network seems to be operational locally on network but not accessible over netbird some of the time. I could not tell if the problem was due to the network the problematic machine was on or due to netbird.

So to debug this I:

  1. Setup a grafana node agent to report journald logs to https://grafana.com/

  2. Setup to docker to log to journald

  3. Wrote ssh-via-cloudflare-tunnel docker-compose stack to tunnel ssh over websocat to internet over cloudflared . Set docker compose to restart-on-failure.

Today netbird had some downtime (tailscale had theirs just a few days before that). I was able to log into grafana, look up the temporary hostname cloudflare assigned to me and ssh in using

ssh -o ProxyCommand="websocat -E --binary - -v %h" -o ServerAliveInterval=10 wss://library-won-nt-gauge.trycloudflare.com

Architecture

Conclusion

This turned out trivial to do. However it took me over 5 years of pondering, discovering ssh ProxyCommand, cloudflared, websocat and deciding to combine them to conveniently expose ssh over web.

I think it’s pretty cool how Cloudflare allows one expose geographically distributed tunnels without requiring any signups. I wish their UX simpler so it was equally easy to expose tunnels with fixed dns. Cloudflare actually has something similar as an official ssh feature , but it requires more hoop jumping.

websocat is amazing. I use websockets a lot more now that I have a robust way to utilize them without writing any code.

Why Would I Want To Do This?

  • As a fallback to tailscale/netbird that uses a completely different network topology as in this case
  • To temporarily grant ssh to some machine without requiring end-users to install a vpn
  • To bypass restrictive gsm/wifi networks that block access to ssh
  • As an alternative to port-knocking to obscure ssh (eg hide ssh behind http basic-auth)

How would you improve this?

Checkout ssh-via-cloudflare-tunnel on github.