r/CloudFlare: Cloudflared tunnel for SSH

r/CloudFlare: Cloudflared tunnel for SSH
This article archives a conversation, which took place in a subreddit post (original source linked below) and to which I contributed a solution or answer (with the u/MasterofSynapse handle), in a Q&A format.

Original Reddit post: https://www.reddit.com/r/CloudFlare/comments/wvx72c/cloudflared_tunnel_for_ssh/


Is there any trick to get a cloudflared tunnel to render SSH in a browser? I have followed many guides I was able to find on the web & YouTube, but I can't get it working.

I did get the tunnel to work on Docker containers that run on the same box on port 80 and 8080 (separately, not at the same time). I was able to use my phone on 4G, not Wi-Fi, to connect to the web sites. However, when I configure the tunnel and the application to render SSH, it either fails, or just sits there and then eventually timeout.

The box is running on Debian 11 and cloudflared is version 2022.8.2.


There is no trick. It actually is really straightforward, just as you described.

I use cloudflared with a subdomain for each of my servers in my datacenter and then put an application with "Browser rendering: SSH" in front of it and it works flawlessly.

Where is the public hostname you have configured pointing to?

For SSH in the browser to work it has to point to the actual SSH host and port.

If we assume that cloudflared is running on the server directly and the server also hosts the SSH server, you would point to "ssh://localhost".

If you run cloudflared in a docker container, things get a bit more complicated since if you point the hostname to an actual IP address you have to configure your servers firewall to allow "external" incoming traffic on the SSH port. That is necessary since localhost can communicate through the kernel only, any other IP has to run through the / a network interface which is governed by the servers firewall.

Is there a special reason you dont just run cloudflared on the host?

Comment 1 on Answer

cloudflared is running natively on the Debian box, not in Docker.

I have tried setting it to ssh://localhost, ssh://localhost:22, ssh://, and ssh:// and none of them worked.

I have also tried to set it up manually through creating the json file, config.yml file, creating the certificate, as well as just through the Cloudflare Teams dashboard. I did see the hostname (terminal.example.com) points to the UUID of the tunnel in Cloudflare DNS, but I still can't figure out why it doesn't work for me.

My response to comment 1

I assume you wanted to reply to my comment?

Can you connect to SSH with a local SSH client pointing to the public hostname on port 443, without the Access Application in place? I suggest you first make sure that the tunnel itself actually transports the traffic correctly before you put ZTNA in front of it to limit it down.

If you prefer, hit me up through DMs and we could arrange a short troubleshooting session.

Comment 1.1 on Answer

Thanks for the offer. I think I will give up on this and maybe re-visit it in a few months.

For now, I discovered Guacamole. I now have it running in Docker on a VPS that I already have and I also installed Tailscale. I can use my VPS as an SSH jumpbox and get to where I need. I have protected Guacamole with 2FA, as well as putting Authelia in front of it. SSH on my VPS has fail2ban in front of it and is also set to only accept SSH keys, so I think I am okay. I am sure I can do more, but I think it's pretty secure. Thanks.