Adam's blog: Cloudflare Access to get to LAN

05 Oct 2024, 2833 words

Self-hosting applications at one’s home provide benefits over using their cloud-native alternatives. These benefits may include privacy (your data is stored in your hardware vs in the cloud with the second party) and overall cost (effectively paying only for electricity and hardware up-front vs paying for a subscription tier every month/annually). On the other hand, as its most prominent disadvantage, self-hosted applications at one’s home are usually only available from inside the local area network. In contrast, cloud-native applications can be accessed from anywhere with an Internet connection. This text will focus on solutions tailored for SOHO (small-office and home-office) settings.

Note: this post was originally submitted as an university subject essay, so that it uses a little more formal language than usual.

Classical solutions

To see the advantages of choosing Cloudflare Access for this task, we first need to discuss what other solutions are already present and often used. Multiple options exist for accessing LAN-only applications from the Internet, each with its custom set of up- and downsides. Please see that almost none of the classical solutions listed below discusses the problematics of IPv4 and IPv6 running simultaneously, as most of the approaches allow for only one at a time. Furthermore, no approach deals with modern security practices such as Zero Trust[s] in any way by itself.

Public IP address

With some of the largest Czech ISPs (internet service providers), it is possible to obtain a public IP address[s][s] that directs all traffic directly to a router in possession of the SOHO administrator. The IP address may be provided as a benefit from an ISP for a fixed price or, much more commonly, for a monthly price. This solution offers the most significant freedom for the administrator, as they can tailor the network stack to their liking by simply setting up port forwardings on their ingress router. On the other hand, this solution may be disadvantageous in terms of security (the administrator is fully responsible for setting correct access controls) and flexibility (if the administrator does use some form of centralized configuration, configuring the rules properly may steadily become infeasible within more complex settings).

VPN service with exposed ports

Some VPN providers like ProtonVPN[s] and ExpressVPN[s] provide an option to forward a single (TCP/UDP) port from the VPN’s public IP address to a local machine or specific LAN address. The main advantage of this approach is the ease of setup and little technical knowledge barrier compared to other solutions when the administrator can install the VPN provider’s official GUI application and enable port forwarding. The drawbacks are evident; with only a single port, the option to host multiple applications is severely limited unless the administrator decides to use additional local solutions such as a reverse proxy for multiple HTTP-based applications or a protocol multiplexer for a specialized list of supported applications. One possibility to overcome this obstacle may be to host a VPN server on the exposed port, allowing client devices to access the LAN upon connection. Nevertheless, the port number and IP address provided by the VPN service may change, which may require additional reconfiguration on client devices.

Creating a custom tunnel with VPS

Another approach may be purchasing a cheap VPS (virtual private server), typically with a public IP address. Then, it is possible to set up a custom VPN server that the services on LAN will be connected to or directly use the remote port forwarding SSH option to forward the traffic from VPS to the self-hosted application. Because the VPS acts as a proxy, this approach may be suitable for both IPv4 and IPv6, even when the ISP is IPv4-only or IPv6-only. On the other hand, using a VPS as a proxy adds a new layer of complexity – the response time is increased by the time that it takes to forward the request from VPS to LAN and back, and the connection may fail, e.g. when the VPS reboots because of applied updates. It also places additional requirements onto the administrator, who now needs to properly configure the VPS so as not to allow unauthorized access, which can be an obstacle for administrators without experience with managing remote servers.

Using a dedicated P2P software

An option that relies solely on the clients talking directly to each other, usually with the help of nodes that act as middlemen exchanging information about connected clients to each other. Examples of such software may be LogMeIn Hamachi, n2n and gsocket. Most prominently, the Hamachi targets regular users, requiring little to no technical knowledge. This makes the entry barrier almost nonexistent. On the other hand, it requires special software to be installed on both endpoints and because of its P2P nature, clients may be blocked on more restricted networks like airports or hotel lobbies.

Cloudflare Access

Cloudflare Access is primarily a web-application product from a company with the same name. Cloudflare is perhaps best known for its word-wide CDN (content delivery network), which offers both hosting static pages and acting as a reverse proxy where the inbound connections are accepted to the Cloudflare network and then internally forwarded to a real server, which will then process the request. The main benefits of using Cloudflare as a reverse proxy are the hiding locations of the real servers, which is helpful in case of DDOS attacks, which Cloudflare can filter out.

Generally, Cloudflare Access masks the actual IP address of the server by overwriting responses to DNS queries with addresses from their IP range.

Cloudflare Access Application types

Cloudflare Access supports three main application types.

SaaS (Software as a Service)

Cloudflare Acess supports integration with SaaS[s] directly, but this solution is more focused on enterprise applications than SoHo, so I will consider it out-of-scope for this project. However, it has a significant advantage for some self-hosted applications in the form of SAML (Security Assert Markup Language[s]) provider.

Private network

With this application type, the administrator can specify a private IP that should be exposed through Cloudflare private network. Because access to this network always requires additional software installed on endpoint devices, I consider this out-of-scope for this project.

Self-hosted

In the self-hosted application type, the administrator is supposed to enter which subdomains (and optionally paths) should be redirected to the LAN. Setting up this application is the basis for further creation of processes, like access policy and the actual tunnels to the LAN.

Example self-hosted application configuration

Cloudflare Zero Trust

Zero trust[s] is a design philosophy in which a user is required to authenticate before accessing resources (e.g., web application), which is mainly in contrast to a more classical approach where a user is granted access to an application based on e. g. being in the correct network. With zero trust implemented, even if the attacker can get access to the network (for example, by compromising a remote code vulnerability within an IoT (Internet of Things) device like IP cam [s]), their impact is limited by still missing credentials that are required to access protected resources.

Whereas generally, when accessing a web application, the Zero Trust is implemented directly as a login system to said web application, the Cloudflare Zero Trust acts as a middleware that will prevent access to the target application until the user complies with the set access policy. Because we cannot expect the average hobbyist who is a self-hosting administrator to follow the latest security-related news, this approach may be beneficial when a vulnerability is discovered within the target web application because the attacker would still need to satisfy the access policy, which in turn gives more time to the administrator to patch the vulnerability.

Access policy

As referenced above, access policy[s] is a set of rules that any party must fulfil to be granted access to the target resource. At least one policy must be configured for each Cloudflare Access application, and each policy needs to be assigned to at least one group of users to which it applies. The policy may be set to approve access or block access. In its most basic form, the access policy allows access to any known user. However, the access policy may contain much more focused controls – e.g., based on the current user’s country, OIDC claim[s] and more. Unfortunately, it is impossible to specify controls based on time (e.g., only allowing access to the application during business hours) directly through policy specifications inside the web UI. If the administrator requires such functionality, it must be implemented directly within each application or by modifying an OIDC proxy, as hinted in the Appendix.

An example of an allow access policy with group and country selection

Identity management

We have already touched on users and their groups inside an Access policy chapter. Cloudflare itself does not provide any identity management (with a tiny exception of one-time mail password), while instead relying on external services using the single sign-on principle (SSO, [s]). The administrator can configure multiple identity sources from predefined providers or specify custom OIDC[s] settings. This approach has several advantages – for individuals/SoHo, most users already have their Google or Microsoft accounts. For enterprises, it is possible to reuse, e.g., their already set up Microsoft AD tenant, making the onboarding process effortless for regular users. Furthermore, Cloudflare provides step-by-step guides on how to set up each provider. Whenever user authenticates to the Cloudflare Zero Trust page with any configured provider for the first time, they are assigned a seat. The free tier has a total of 50 active seats[s]; after a seat is taken, it is possible to free it again.

For this project, I have tested setting up Microsoft Azure AD® and Google as identity providers. The initial setup took about 30 minutes, primarily because of my minimal experience with both environments. Both providers offer modern MFA solutions for securing target user accounts; their only significant difference is that when setting up the providers with personal accounts, with Microsoft Azure AD I was able to select which user accounts are allowed to authenticate to my AD tenant instance. With Google as an identity provider, any valid user can authenticate. To counter this, I have had to set up a particular group only with selected user seat accounts inside the Cloudflare Zero Trust dashboard. Still, it may be possible for a malicious actor to log in with as many Google accounts as possible. While they are still unable to access the resources because of manual group filtering, they can fill up all seats available with the free tier.

Cloudflare Tunnels

After setting up the self-hosted application records, the next step is to launch a local tunnel. The tunnel is a server process or docker container that accepts requests from the Cloudflare network and forwards them to specified local addresses[s]. To initialize a new tunnel on LAN, all the user has to do is to copy a pre-generated command that already contains all required configurations. Afterwards, creating a new forwarding from WAN to LAN is only a matter of selecting a subdomain (same as in configuring a self-hosted application), protocol (by default HTTP, but can be anything TCP-based), and local address with port to which will the tunnel be forwarding remote requests. Optionally, selecting an access policy that must be satisfied before the request can pass through is also possible. The only limitation is that the same subdomain cannot be used for multiple protocols (e.g. sub.example.org cannot be set up to forward both HTTP and SSH; another subdomain like sub-ssh.example.org must be used instead).

Because a single tunnel can forward multiple subdomains, adding new forwarding from WAN to LAN takes tens of seconds after the initial setup is finished, which is a significant simplification for the network administrator.

Preventing double-logging

After the user authenticates themselves against the Cloudflare Zero trust login page, they may still be required to log into the target web application, which leads to several weak points. Firstly, the user’s comfort is reduced as they must go through another login process right after finishing the previous one. Secondly, either the administrator of the web application needs to set up the same SSO options as for the Cloudflare Zero trust login page, which places additional complexity on the application management, or the users need an additional account just for this web application, which in turn may increase risk of password compromise, as users may not follow security best practices for all their accounts.

If the administrator could configure the web application to always accept the same login credentials as the Cloudflare Zero Trust page, it would increase the overall user comfort and application security while decreasing administration costs.

SAML

Security Assert Markup Language[s] can be leveraged to provide an SSO[s], but this standard is more prevalent for enterprise-oriented applications. For NextCloud, an official application can be installed, which adds the possibility of using SAML as a backend for user management. As Cloudflare provides SAML endpoints only for SaaS applications[s], we need to create a new virtual SaaS application within the dashboard and then use the provided details to configure SAML within NextCloud correctly.

Unfortunately, SAML for smaller open-source applications like Gitea is not supported, so it is only an option for some of this paper’s target self-hosted applications.

Every request sent to the target application behind Cloudflare Zero Trust protection includes a CF_Authorization cookie [[@cloudflareAuthorizationCookie]]. This cookie contains a signed JSON web token (JWT [s]) with the user’s email. If the developers of target applications were to implement authentication using this cookie, it would be possible to log in directly to the application. Still, this would require developers to implement a non-standard login mechanism. Another approach may be to verify the provided JWT on a reverse proxy and set a header with a user name, which is supported, for example, on Gitea[s].

The main drawback of using the cookie for authentication is that it requires the user to always log in through WAN through Cloudflare Zero Trust, even when the user may prefer to access the application through LAN for considerably faster response speeds (e.g. by using DNS masking).

Accessing SSH

So far, we have discussed only accessing HTTP-based applications, but Cloudflare tunnels support any TCP-based protocol, with SSH being explicitly stated. If the user only wants to access the LAN-only SSH server from WAN, creating a new record in the Cloudflare tunnel, which will forward all requests, is possible.

Though, if the user would also want to protect the SSH server with Zero Trust (e.g. requiring logging in with MFA-protected Microsoft Account), they first need to install a cloudflared client on their device[s]. Then, by modifying their local SSH config to use cloudflared as a ProxyCommand, it will first launch the cloudflared command whenever they try to assess the SSH server. The command opens a web browser with a Cloudflare Zero Trust page, where users can log in with their accounts. After a successful authentication, an SSH connection proceeds as usual. Furthermore, thanks to the modification of the user’s local SSH config file, this whole procedure needs to be done only once, making the authentication process after initial setup effortless. However, the apparent disadvantage of this approach is that the user needs to install the Cloudflare client on every machine from which they plan to access the SSH server.

To solve this disadvantage, Cloudflare Access offers an option to render the SSH terminal inside the web browser. This setting can be enabled within the Additional Settings section of the self-hosted application. This browser terminal is again protected with Cloudflare Zero Trust, and the rendered terminal supports classical keyboard shortcuts and function keys, making it a reasonably usable alternative. Unfortunately, this approach requires the user to manually input a password or copy a private key unless additional settings like short-lived certificates are used.

Conclusion

In conclusion, Cloudflare Access offers a helpful alternative to access LAN-only resources from WAN. The complexity of the solution and the time spent configuring it for the first time is well-balanced, with easy scalability for adding new resources and following security best practices like Zero Trust. The way in which the Cloudflare Zero Trust is implemented may also increase the overall security of the LAN network, e.g., even when an inexperienced administrator exposes a vulnerable application, a malicious actor is still unable to access it. Furthermore, relying almost solely on external identity management services increases user comfort as they can reuse their already existing accounts. Finally, the Cloudflare Zero Trust is free for up to 50 users/seats, which should be plenty for common SOHO requirements.