<aside>
đź’ˇ Linux host setup for cloudflared
to allow Zero Trust access to a running web application, using one-time OTP to email, and alternative rules such as country blocking.
</aside>
Revision: 20240721-0 (init
: 20240713)
This content, an extension of the “VPS hardening” post, introduces a method for granting conditional access to web services enabled on this VPS without opening any additional ports through the VPS firewall.
Ubuntu 24.04 VPS Hardening (Rev: 20240922-0)
We will discuss using Cloudflare Zero Trust to access resources running on a VPS without opening any of the new service ports through the VPS firewall.
We will use cloudflared
, a command-line tool and daemon that connects our infrastructure to Cloudflare's global network, enabling secure tunnels (with HTTP to HTTPS upgrades) for accessing resources behind firewalls.
Most self-hosted web applications should be compatible with the tool. We will use Dockge, a Docker compose service manager, to enable straightforward web app deployments. We will demonstrate accessing it with Cloudflare Zero Trust (using cloudflared
).
Our VPS is an Ubuntu 24.04 host, and we configured it following the steps in:
, where only ssh
is accessible remotely on this host; every other port is blocked by the ufw
firewall (we also covered changing the ssh
port to an alternate port and setting up fail2ban
).
For this additional setup, we propose Dockge using Docker to support installing a subset of applications (stacks) using docker compose
. To add those on our Ubuntu 24.04 VPS:
Follow the “Docker setup (from docker.io)” section, as this section provides only the steps to install Docker:
Follow the “Setup (with Docker)” section from the “Dockge” post. In the following, we will not install additional stacks, but the tools will enable us to add many should we decide to.
After following those instructions, the Dockge service will be available on localhost only. It will not be remotely accessible since our VPS firewall configuration limits access to any port other than the modified SSH port.
To confirm that the service is working, we can connect to the remote host’s localhost interface on Dockge’s port (5001) and forward it locally to a port, for example, 4001 (here vps
is a Host
entry in our .ssh/config
):
ssh vps -L 4001:127.0.0.1:5001 -N
With this command, there will be no shell prompt (-N
); the tunnel will be active until we Ctrl+C
the command. While the tunnel is active, we can open Firefox to http://127.0.0.1:4001/, which will open the Dockge setup interface.
<aside> 👉 Cloudflare will require you to have a credit card on file with your account. Given our limited usage, the free tier offered by Cloudflare has been sufficient for our use of their tools.
</aside>
For the next steps to be functional, we need to own a domain name with a registar, and to have its DNS servers pointed to Cloudflare’s resolvers. For this document, we will use example.com
Please see https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/ for detailed instructions on how to get a domain’s DNS handled by Cloudflare.
Moving your domain’s DNS to Cloudflare involves:
Note that the process only moves your DNS management to Cloudflare and your domain registration remains with your current registrar.
Here are a few recommended settings for a more secure configuration; adapt according to your preferences.
On the main Dashboard, select example.com in “Websites”
Zero Threat
Threat Score
”Field”, greater than
”Operator”, 0
”value”Block
Also on the main dashboard for our site (in the “Overview” section, under “Quick Actions”), it is possible to “Activate” some “Basic Features”; the list of those features can be found at https://developers.cloudflare.com/fundamentals/basic-tasks/basic-features/. Given that some of those (”WebSockets”, “Onion Routing”, “Hotlink Protection”) might not be part of the settings needed for your host, we leave the decision to enable all of those to the end user. If all are desired, “Activate” will enable those on your site; otherwise Cloudflare’s documentation detail how to enable those on a per feature basis.
Once our example.com
domain’s DNS is hosted at Cloudflare, the next step is to set up a Cloudflare tunnel. To better understand the idea of what used to be called “Argo”, please see https://blog.cloudflare.com/argo-tunnel/ (from 2018). The modern “Cloudflare tunnels” is described in https://www.cloudflare.com/products/tunnel/:
From the moment an application is deployed, developers and IT spend time locking it down — configuring ACLs, rotating IP addresses […] Your origin IP addresses and open ports are exposed and vulnerable to advanced attackers, even when they’re behind your cloud-based security services. […] Cloudflare Tunnel is tunneling software that lets you quickly secure and encrypt application traffic to any type of infrastructure, so you can hide your web server IP addresses, block direct attacks […] The Tunnel daemon creates an encrypted tunnel between your origin web server and Cloudflare’s nearest data center, all without opening any public inbound ports.
We will use it with “Zero Trust Web Access” which provides “Secure access to internal web applications without a device client”. Cloudflare has a well written “learning path” on their site and we encourage readers to review https://developers.cloudflare.com/learning-paths/zero-trust-web-access/. The ideas are:
“Zero Trust is a security approach built on the assumption that threats are already present within an organization. In a Zero Trust approach, no user, device, or application is automatically trusted — instead, strict identity verification is applied to every request anywhere in a corporate network, even for users and devices already connected to that network. […] Zero Trust only grants access to a specific application and denies access to all other resources by default”
“Zero Trust Web Access (ZTWA), also known as Zero Trust Application Access (ZTAA), provides users with secure access to internal applications using Zero Trust principles. ZTWA authenticates users to applications by integrating with identity providers, encrypting connections, considering each access request for an application individually, and blocking or allowing on a request-by-request basis.”
<aside> 🚧 Note: the following steps follows the Dashboard available as of July 2024; components on Cloudflare’s WebUI have changed from time to time.
</aside>
For our purpose, we have added our example.com domain (a “Zone” following Cloudflare’s terminology) to our Dashboard.
Once on our dashboard, select the “Zero Trust” entry on the left side.
If this is our first time setting it up:
On the onboarding screen, choose a team name. The team name is a unique, internal identifier for your Zero Trust organization […] it will be the subdomain for your App Launcher […] Complete your onboarding by selecting a subscription plan and entering your payment details. If you chose the Zero Trust Free plan, this step is still needed but you will not be charged.
Configure an identity provider (if preferred); in our setup we will use the One-time PIN login method (free up to 50 users); when end users go the the application’s url (for our setup we will name it dockge.example.com):
Connecting the web application is done by using cloudflared
which connects an host and port to Cloudflare’s global network.
Heading over to https://dockge.example.com/ is now possible. Note that the access is now using HTTPS and we have not open any additional ports on our VPS. After answering the ZeroTrust challenge, we are presented with the admin account creation page for Dockge.
Because this is an internet accessible site (protected by Cloudflare’s Zero Trust) with a defined url, when creating the username and password, we have the ability to store the details in a password manager and expect no collision of URL with other self-hosted components.
Beyond the ability to create a one-time OTP, it is also possible to allow access with alternate limitations. In the following we will use an access policy, following the list detailed at https://developers.cloudflare.com/cloudflare-one/policies/access/
We have a web application that we want only people in the United States to be able access. Since we are testing this from the USA, we will first set the access to only Canada to confirm the block works:
usa access web
and match the application to the web
subdomain and the example.com
domain.Bypass
type, then deselect any email option, instead in “Configure rules” “Include” the Country
”Selector” and set its value to Canada
United States
After saving, going to the url allows us to see the web application without being blocked by the geolocation filter.
There are many other options such as “Emails ending in” or “IP ranges”, as can be seen in the “Selectors” section of https://developers.cloudflare.com/cloudflare-one/policies/access/#selectors (please see the “Order of Execution” right below to set more complex rules).