I had always wanted to access my home server, running on a Raspberry Pi 4, from outside the local network. The most straightforward answer seemed to be getting a static IP from the ISP; however, both of my ISPs did not help me with that. I forgot about it for a while but when I flashed my Pi a couple of days ago I knew that I had to do it. Being able to SSH and rsync into my Pi on the fly is pretty cool! Today we will learn how to create an SSH Tunnel using Cloudflare’s Argo and Access.

I tried this script to update the Cloudflare DNS records with my public IP. In addition to the script, I used crons to automically handle updates every minute, but it did not work. It turns out that my ISPs are using CGNAT and I have to create port forwarding rules in ISP’s router for this method to work, which will never be allowed. I came across Cloudflare Argo which lets you tunnel services running locally to Cloudflare.

Installing Cloudflared

Cloudflared (pronounced: cloudflare-dee) is a light-weight server-side daemon which lets you connect your infrastructure to Cloudflare. Using cloudflared we will create an ssh tunnel. The installation is straightforward, and you can find the compatible package here. We will install ARM cloudflared .deb package on our Raspberry Pi.

Once downloaded, we will use dkpg to install the package.

$ dkpg -i <path_to_the_deb_package>

We can verify the installation using this command:

$ cloudflared -V
cloudflared version 2021.9.2 (built 2021-09-28-1343 UTC)

Setting up Cloudflare Access

Next, we will create a subdomain and secure it with Cloudflare Access. Access secures SSH connections and other protocols with Cloudflare’s global network, with a Zero-Trust Approach.

Login to your Cloudflare account and choose your domain. On the Dashboard, click on ‘Access‘.

Cloudflare Account Dashboard

Next, we need to create an ‘Access Policy’. Click on ‘Create Access Policy Button’ in the ‘Access Policies’ section.

Creating a Cloudflare Access Policy

The users will be able to attempt to gain access to ‘Raspberry Pi Server’ on pi.danishshakeel.me and each session will expire after 24 hours.

Creating SSH Tunnel

Before we can create a tunnel, we need to login to cloudflared.

$ cloudflared tunnel login

This command will provide a link using which you can authorize the Argo tunnel. Select the domain on which you wish to authorize Argo. Now, we can create an Argo SSH Tunnel using the following command:

$ cloudflared tunnel --hostname <subdomain> --url <url_to_service>

We want to tunnel SSH on localhost to pi.danishshakeel.me. The command will look like this:

$ cloudflared tunnel --hostname pi.danishshakeel.me --url ssh://localhost:22

To verify, we can check our DNS records in Cloudflare. They should have an AAAA record for our subdomain.

Cloudflare DNS Records

Connecting to the SSH Tunnel

In order to connect to the tunnel, we need to install cloudflared on the client. After installing, we need to run:

$ cloudflared access ssh-config --hostname pi.danishshakeel.me

This will give the required configuration that we need to add to SSH configuration. The configuration will look like this:

Host pi.danishshakeel.me
  ProxyCommand /opt/homebrew/bin/cloudflared access ssh --hostname %h

Now, to connect to the SSH, we will do ssh [email protected]. For my Raspberry Pi, username is pi and hostname is pi.danishshakeel.me. This command will also output a link using which we need to authorize the connection.

Cloudflare Access Login

You should be able to successfully ssh into your server. Remember that you need to start the tunnel before trying to access it.

SSH Access to Raspberry Pi