In the ever evolving landscape of cyber threats, it’s increasingly important to protect your applications from attackers, but protection can often be a hassle to setup, maintain, and integrate.
My homelab runs on VMWare ESXi, and I wanted to be able to access it remotely. Years ago, I simply hosted a subdomain that went straight to my hypervisor control panel, accessible by anyone from anywhere. Of course it had basic login, but that didn’t stop bots and attackers from trying to access my server and effectively DDoSing my home internet connection.
Reading articles online, everyone always says, never publish your control panel online. So that leaves two primary options: either access the server locally, or remote in with a VPN. My homelab is ironically not located in my home, so local access requires a 30 minute drive to another town. A VPN is a viable option, but it’s a bit of a hassle. Not only do I have to allocate some of my tight budget and limited resources to a VPN server, but that also means that any device I want to access my server with needs to have a compatible VPN client installed, and I need to have my credentials (ideally a private key and secret phrase) memorized or accessible.
I used a VPN for years, hopping from solution to solution, but was never satisfied. The built in Windows VPN server uses PPTP which doesn’t work on Macs. Windows Remote Access Service was better but always messed up internal routing and used Microsoft DNS Server and Active Directory, which were more tools I didn’t want to maintain. OpenVPN access server requires the OpenVPN client which is inconvenient when I want to connect from a friends computer or an office PC where I don’t want to install extra software. Every solution seemed to have a major flaw that made it unusable for me.
I wanted a secure, frictionless way to access my server from any device with no server, client software, or hard to remember credentials. Tough ask, right?
Then Cloudflare Access came along.
Cloudflare Access is a zero trust network service that uses Cloudflare’s existing proxy system to act as a secure tunnel to your Cloudflare hosted services. Best of all, it’s free.
Cloudflare DNS already sits in front of your sites and acts as a web application firewall, so it makes perfect sense to use as an access control service too.
Setup
First things first, you need to configure your apps to use Cloudflare DNS. I’ve been a long time customer of Cloudflare and already had my sites running through their DNS, but if you don’t, just head over to https://dash.cloudflare.com/sign-up to create a free account.
After you’ve added a zone and pointed your domain to Cloudflare’s DNS servers, you can enable the Cloudflare proxy by clicking the little cloud next to your DNS record.
When the cloud is orange, that means that your requests are being proxied through Cloudflare’s servers, hiding your IP and applying all of their special magic (DDoS protection, WAF, SSL, etc.).
When the cloud is greyed out, that means that your requests are being sent directly to your server, exposing your IP, acting as a traditional DNS server.
In order to use Cloudflare Access, you must ensure that the Cloudflare proxy is enabled so all requests will be intercepted by Cloudflare before they can access your servers. You also want to make sure that your service is not accessible directly via your IP address. In my case I use NGINX as my web proxy (with NGINX Proxy Manager) to handle requests. This way all requests must be proxied through the specified domain.
Next we need to setup Cloudflare Access. Create a new Cloudflare Access team at https://dash.teams.cloudflare.com/.
Once you have a team, you can setup your authentication provider by heading to “Settings” then “Authentication”. You can use Cloudflare’s built in one-time PIN authentication, but if you want real Multi-Factor Authentication, you’ll need to add another provider.
Luckily, Microsoft Azure Active Directory is a completely free, although somewhat confusing solution for authentication.
Azure Active Directory
First, head over to the Azure Dashboard. Click “Create a resource” then search up “Azure Active Directory”.
Use the default tenant type, enter your domain and organization name, then create your new Active Directory tenant.
Once your tenant is created, head over to the “Custom domain names” section and add your own domain (if desired). If you don’t want to specify your own domain, you can still login with the [email protected] format.
Next, let’s create our first user, head to the “Users” section and add a new user. You can also invite an existing Microsoft account to be authorized on your new tenant and Cloudflare apps.
Now, we need to set up Multi-Factor Authentication. In order to use Multi-Factor Authentication on a free tenant, you need to have security default enabled. Verify that security defaults are enabled by going to your tenant properties, and clicking “Manage security defaults” at the bottom of the page.
Then, head to Security -> Authentication Methods. Choose Microsoft Authenticator (or your desired authentication method), and enable for all users.
Now, head to https://aka.ms/MFASetup, login as your new user, and setup your Multi-Factor Authentication method.
Once MFA has been setup and enabled, we need to connect our Azure AD tenant to Cloudflare.
Head to “App Registrations” and create a new registration.
Enter a name for the app, leave the account type as single tenant, set the Redirect URI platform to “web” and the URI to “https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/callback”.
Next, open the “API Permissions” section, choose Microsoft Graph, delegated permissions, and choose:
- offline_access
- openid
- profile
- User.Read
- Directory.Read.All
- Group.Read.All
Save the permissions, then hit the “Grant admin consent for …” button on the next page.
Finally, open the “Certificates & Secrets” section, and create a new client secret.
Head back to the Cloudflare Teams settings page, open Authentication, add a new provider, choose “Azure AD”, then copy the values from the Azure “Certificates and Secrets” page to Cloudflare.
You can find the application secret value from the secrets section and the Application ID (client) and Directory ID (tenant) from the “Overview” section, head back to Cloudflare, and fill these details into the form.
If you want to use Active Directory groups as access control lists, toggle the “Support groups” switch, then save the form.
That’s it, authentication is setup and ready to use.
Protecting Applications
Now, let’s add and protect an application in Cloudflare Access.
In Cloudflare Access, go to Access -> Applications -> Add an application -> Self-hosted.
Enter your app name, as it will be displayed in Cloudflare Access, the domain, subdomain, and/or path of the application that is proxied through Cloudflare DNS (orange cloud), and your desired login session duration.
At the bottom of the page, choose your new Azure AD identity provider. By default, users will be shown a Cloudflare login page where they can choose which identity provider to use. To skip this page and redirect users directly to your new Azure login, enable “Instant Auth”.
Next, create a new access policy, to allow or block users from accessing your app. By default, I create a new “Allow” policy and include all users. If you enabled Active Directory Groups support, you can also specify a group in Azure AD to allow access to and manage access control from inside of Azure.
Finally, configure any desired cookie settings (I just use the default), and save your application.
All done! Head to your domain and test it out. Your request should be intercepted by Cloudflare where you are redirected to a Microsoft login page. When logging in with your new Azure AD account, you should be required to provide your specified MFA before being allowed to access the application.
For more information on how to configure Cloudflare Access, check out the Cloudflare Zero Trust documentation: https://developers.cloudflare.com/cloudflare-one/.