Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save prateekrajgautam/29ae64a89a30352817633b214993acd6 to your computer and use it in GitHub Desktop.

Select an option

Save prateekrajgautam/29ae64a89a30352817633b214993acd6 to your computer and use it in GitHub Desktop.
cloudflared zerotrust tunnel and ssh

Cloudflare Zero Trust Tunnel for SSH Access

ssh over cloudflared in 3 steps

This guide uses a Cloudflare Dashboard-managed tunnel to securely access an SSH server without opening port 22 on your router.

Step 1: Configure Cloudflare Tunnel (Dashboard)

  1. Log in to your Cloudflare account.

  2. Navigate to:

    Zero Trust → Networks → Tunnels
    
  3. Create a new tunnel.

  4. Choose Cloudflared as the connector type.

  5. Follow the installation instructions to connect your server to the tunnel.

  6. After the tunnel is online, add a Public Hostname:

Setting Value
Subdomain ssh
Domain example.com
Service Type TCP
URL 127.0.0.1:22

Result:

ssh.example.com
    └── TCP → 127.0.0.1:22

Save the configuration.


Step 2: Configure the SSH Server

Install and connect the Cloudflare tunnel connector on the server.

Install cloudflared

Debian / Ubuntu

curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb \
-o cloudflared.deb

sudo dpkg -i cloudflared.deb

Verify Installation

cloudflared --version

Connect the Server to the Tunnel

Cloudflare Dashboard provides a command similar to:

sudo cloudflared service install <TOKEN>

Start and enable the service:

sudo systemctl enable cloudflared
sudo systemctl restart cloudflared
sudo systemctl status cloudflared

Verify SSH Service

sudo systemctl status ssh

Confirm SSH is listening locally:

ss -tlnp | grep :22

Expected output:

LISTEN 0 128 0.0.0.0:22

Step 3: Configure the SSH Client

Install cloudflared

Install cloudflared on the client machine.

Verify:

cloudflared --version

Configure SSH

Edit SSH configuration:

mkdir -p ~/.ssh
vim ~/.ssh/config

Add:

# Cloudflare Tunnel SSH endpoint
Host ssh.example.com

    # Use cloudflared as a proxy to connect through Cloudflare Zero Trust
    # %h is automatically replaced with the hostname (ssh.example.com)
    ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h```

or for old server with rsa

# Cloudflare Tunnel SSH endpoint
Host ssh.example.com

    # Use cloudflared as a proxy to connect through Cloudflare Zero Trust
    # %h is automatically replaced with the hostname (ssh.example.com)
    ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h

    # Allow the legacy RSA host key algorithm.
    # Required only when the SSH server offers an old ssh-rsa host key.
    # Modern servers should use rsa-sha2-256, rsa-sha2-512, ed25519, or ecdsa instead.
    HostKeyAlgorithms +ssh-rsa

    # Allow authentication using legacy ssh-rsa public key signatures.
    # Usually needed only for older OpenSSH servers (typically OpenSSH < 8.8)
    # or legacy network devices.
    PubkeyAcceptedKeyTypes +ssh-rsa

If cloudflared is installed in a custom location:

Host ssh.example.com
    ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h

Set proper permissions:

chmod 600 ~/.ssh/config

Test Connection

ssh username@ssh.example.com

Example:

ssh prateek@ssh.example.com

If Cloudflare Access policies are configured, you may be prompted to authenticate through your browser before the SSH session starts.


Troubleshooting

Check Tunnel Status

Server:

sudo systemctl status cloudflared

View Tunnel Logs

sudo journalctl -u cloudflared -f

Test SSH Locally

On the server:

ssh localhost

Verify DNS Resolution

Client:

nslookup ssh.example.com

Debug SSH Connection

ssh -vvv username@ssh.example.com

Add comments like this in ~/.ssh/config:

# Cloudflare Tunnel SSH endpoint
Host ssh.example.com

    # Use cloudflared as a proxy to connect through Cloudflare Zero Trust
    # %h is automatically replaced with the hostname (ssh.example.com)
    ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h

    # Allow the legacy RSA host key algorithm.
    # Required only when the SSH server offers an old ssh-rsa host key.
    # Modern servers should use rsa-sha2-256, rsa-sha2-512, ed25519, or ecdsa instead.
    HostKeyAlgorithms +ssh-rsa

    # Allow authentication using legacy ssh-rsa public key signatures.
    # Usually needed only for older OpenSSH servers (typically OpenSSH < 8.8)
    # or legacy network devices.
    PubkeyAcceptedKeyTypes +ssh-rsa

Why are the last two lines needed?

Since OpenSSH 8.8, the ssh-rsa signature algorithm is disabled by default because it relies on SHA-1, which is considered weak.

If your SSH server is old, you may see errors such as:

Unable to negotiate with server:
no matching host key type found. Their offer: ssh-rsa

or

userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms

Adding these lines temporarily re-enables support for legacy RSA keys.

Should you keep them?

  • Yes: If your server, router, NAS, or embedded device only supports ssh-rsa.

  • No: If your server supports modern algorithms such as:

    • ssh-ed25519
    • ecdsa-sha2-nistp256
    • rsa-sha2-256
    • rsa-sha2-512

You can check what the server offers:

ssh -vvv user@ssh.mgeek.in

or from the server:

sshd -T | grep hostkey

For a modern Linux server (Ubuntu 22.04+, Debian 12+, NixOS, etc.), these two lines are usually not required and can be omitted. They are commonly added when connecting to older routers, NAS devices, or legacy Linux installations.


References

This version separates the process into the three stages you requested: Cloudflare Dashboard, SSH Server, and SSH Client.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment