Zero Trust Networking: Principles and Practical Tools
The old security model had a simple premise: build a strong perimeter, and trust everything inside it. A thick firewall at the network edge, a VPN to get through that firewall, and then — once you were in — broad access to internal resources. The castle had a moat. You either crossed the moat or you didn’t.
That model is dead. It was killed by cloud computing, remote work, SaaS applications, mobile devices, and the uncomfortable reality that attackers who breach the perimeter — or malicious insiders who were always inside it — face almost no resistance once they’re in. The 2020 SolarWinds breach moved laterally across networks for months before detection. The 2021 Colonial Pipeline ransomware spread from a compromised VPN account. In both cases, once past the moat, the castle interior was wide open.
Zero Trust is the replacement architecture. This guide covers the philosophy, the core principles, and two practical tools — Tailscale and Cloudflare Access — that let you implement Zero Trust from a homelab to a production environment without a six-figure budget.
What Is Zero Trust?
The term was coined by John Kindervag at Forrester Research in 2010, but the most influential implementation came from Google. In 2014, Google published the BeyondCorp paper, describing how they rebuilt their entire access model after the Operation Aurora attacks. The core insight was radical: remove privilege from the network. Stop treating the corporate network as a trusted zone. Move authentication and authorization to every individual service. An employee on the corporate LAN should get the same access decision as an employee at home — because the network they’re on proves nothing about who they are or whether their device is safe.
NIST formalized this in Special Publication 800-207 (2020), defining Zero Trust Architecture as:
“Zero trust (ZT) is the term for an evolving set of cybersecurity paradigms that move defenses from static, network-based perimeters to focus on users, assets, and resources. A zero trust architecture (ZTA) uses zero trust principles to plan industrial and enterprise infrastructure and workflows.”
NIST identifies three core tenets:
- All data sources and computing services are considered resources.
- All communication is secured regardless of network location.
- Access to individual enterprise resources is granted on a per-session basis.
The colloquial summary: never trust, always verify.
Why the Perimeter Model Fails
The perimeter is gone. Your data lives in AWS, your email is in Google Workspace, your developers SSH into GitHub. There is no single network boundary to defend.
VPNs grant broad network access. A compromised VPN credential gives an attacker the same network visibility as a legitimate employee — often that means access to everything on the internal subnet, not just the one service they needed.
Lateral movement is the real threat. In most major breaches, the initial compromise is a small foothold. The damage comes from moving laterally through the network. Perimeter security does nothing to slow this once an attacker is inside.
Devices are unmanaged and diverse. BYOD, contractors, IoT sensors, and cloud instances all need access to internal resources. The old model required a VPN client and corporate-managed device. The Zero Trust model authenticates the specific service request, not the network session.
Core Zero Trust Principles
1. Verify Explicitly
Every access request must be verified against multiple signals, not just “is this person on the VPN”:
- Identity: Who is this user? Verified via IdP (Okta, Azure AD, Google). MFA required.
- Device posture: Is this device enrolled, up to date, encrypted, running EDR? A valid user on an unmanaged device may get reduced access.
- Location: Is this login from an expected country/region? Unusual locations trigger additional verification.
- Behavior: Is this normal for this user? Accessing 10,000 files at 3 AM is anomalous even with valid credentials.
2. Use Least-Privilege Access
Grant the minimum access required for the task, for the minimum time required:
- Just-In-Time (JIT) access: Elevated privileges are provisioned on demand and expire automatically. An engineer requesting production database access gets a 4-hour credential, not permanent access.
- Just-Enough-Access (JEA): A developer needs to read logs but not modify database records. Separate those permissions explicitly.
- Application-level segmentation: Access is granted to specific applications, not network ranges. A user authorized for the internal wiki cannot automatically reach the admin panel on the same server.
3. Assume Breach
Operate as if the network is already compromised:
- Microsegmentation: Divide the network into small zones. Workloads can only communicate with the specific other workloads they need to. A compromised web server cannot reach the payment database.
- Encrypt everything in transit: East-west traffic (server to server inside the network) is encrypted, not just north-south traffic from client to server.
- Log and monitor everything: Every access request is logged with full context. Anomaly detection runs continuously, not just at login time.
4. The VPN vs. Zero Trust Distinction
This is the critical difference that trips people up:
| Traditional VPN | Zero Trust |
|---|---|
| Grants network-level access | Grants application-level access |
| Trust on connection | Verify on every request |
| Binary: in or out | Granular: per-user, per-app, per-device |
| Static credentials | Continuous verification |
| Lateral movement possible | Microsegmentation prevents spread |
| One auth event at login | Ongoing behavioral signals |
A VPN creates an encrypted tunnel — but once connected, the user is on the network. Zero Trust means each service makes its own access decision. You can be “on” the Zero Trust network and still be denied access to any specific service that your policy doesn’t authorize you for.
Zero Trust Architecture Components
A complete ZTA involves several functional components:
Identity Provider (IdP)
The source of truth for user identity. Common choices:
- Okta — The market leader for enterprise IdP. SCIM provisioning, adaptive MFA, extensive integrations.
- Azure Active Directory (Entra ID) — Required if you’re already in the Microsoft ecosystem. Strong Conditional Access policies.
- Google Workspace — Simple integration for Google-first orgs. OAuth2 and SAML support.
- Authentik / Authelia — Self-hosted SSO options for homelabs (more on these below).
The IdP issues tokens (OIDC/SAML) that downstream services verify. It enforces MFA and feeds device context into policy decisions.
Device Posture Checking
Before granting access, the policy engine verifies:
- OS version — Is the device running a supported, patched OS?
- Disk encryption — Is FileVault / BitLocker / LUKS enabled?
- EDR agent — Is CrowdStrike, SentinelOne, or similar running and healthy?
- Certificate enrollment — Does the device have a valid device certificate issued by the corporate CA?
- Screen lock — Is the device set to lock after inactivity?
Devices that fail posture checks get reduced access or are denied entirely, even if the user’s identity is valid.
Policy Engine and Policy Enforcement Point
The policy engine evaluates all signals (identity + device + location + behavior) and issues an access decision. The policy enforcement point sits in front of each resource and enforces that decision on every request.
In Cloudflare Access, this is the Cloudflare edge + your tunnel. In Tailscale, this is the ACL policy engine in the coordination server combined with node-level enforcement.
Microsegmentation
Instead of flat networks where everything can reach everything, microsegmentation creates isolated zones with explicit allow rules between them. In practice this means:
- Separate VLANs or network namespaces per workload tier (web, app, database)
- Firewall rules that are default-deny, with only required communication paths opened
- In containerized environments: network policies in Kubernetes, or Tailscale ACLs between nodes
Continuous Verification
Zero Trust is not a one-time authentication event. Session validity is continuously re-evaluated:
- Short-lived tokens (15 minutes to a few hours) that require re-validation
- Revocation lists that take effect immediately when a device is reported lost or a user is deprovisioned
- Behavioral anomaly detection that can revoke a session mid-flight
Tailscale Deep Dive
Tailscale is the most practical Zero Trust tool for individuals, homelabbers, and small teams. It builds a WireGuard mesh network with a hosted coordination server on top, adding identity, ACL policy, device management, and a pile of useful features that raw WireGuard lacks.
How Tailscale Works
At its core, Tailscale is WireGuard. Each device in your tailnet (Tailscale network) gets a WireGuard keypair and a stable IP in the 100.64.0.0/10 range (Carrier-Grade NAT space).
The coordination server handles key exchange and node discovery — it never sees your traffic. When Node A wants to talk to Node B:
- Node A contacts the coordination server to get Node B’s public key and candidate endpoints.
- Tailscale attempts direct peer-to-peer connection using STUN (NAT traversal).
- If NAT traversal fails (double-NAT, strict firewalls), traffic is relayed through DERP (Designated Encrypted Relay for Packets) servers. DERP traffic is end-to-end encrypted — DERP servers are relays, not proxies; they cannot read your traffic.
The result: seamless encrypted connectivity between all your devices regardless of where they are, without any port forwarding.
Installation
Linux:
|
|
macOS / Windows: Download from tailscale.com. GUI app handles authentication via browser.
Docker:
|
|
Raspberry Pi:
|
|
Essential Commands
|
|
ACL Policy (HuJSON)
Tailscale ACLs are defined in HuJSON (JSON with comments). This is the heart of Zero Trust policy for your tailnet. Access the ACL editor at https://login.tailscale.com/admin/acls.
Here is a realistic homelab ACL policy:
|
|
Exit Nodes
An exit node routes all outbound internet traffic from other tailnet members through itself. Useful for:
- Routing remote devices through your home IP
- Accessing geo-restricted content
- Securing connections on untrusted networks
|
|
Subnet Routes
Expose an entire LAN subnet to your tailnet without installing Tailscale on every device. Useful for accessing printers, NAS devices, IoT gear, and legacy systems.
|
|
MagicDNS and Custom DNS
MagicDNS assigns each node a DNS name like myserver.yourtailnet.ts.net. Enable it in the admin console under DNS settings. You can also configure custom nameservers for specific domains:
# In admin console DNS settings:
# Global nameserver: 100.100.100.100 (Tailscale's DNS)
# Custom nameserver for internal domain:
# home.arpa → 192.168.1.1 (your Pi-hole or router DNS)
MagicDNS also resolves split-brain DNS — internal and external names can resolve differently for Tailscale-connected devices.
Tailscale SSH
Tailscale SSH replaces traditional SSH key management and jump hosts. It authenticates users via their Tailscale identity (and therefore your IdP) rather than SSH keys in authorized_keys.
|
|
In the ACL policy, you can define fine-grained SSH access rules:
|
|
Tailscale Funnel
Funnel exposes a tailnet service to the public internet without port forwarding, dynamic DNS, or a public IP. Tailscale handles the ingress routing through their infrastructure.
|
|
Funnel is available on HTTPS (443), with your node accessible at https://mynode.yourtailnet.ts.net. It is rate-limited on free plans and intended for development/homelab use, not high-traffic production.
Self-Hosting: Headscale
Headscale is an open-source re-implementation of the Tailscale coordination server. It gives you full control over the control plane while still using the Tailscale clients.
|
|
Headscale trades the ease of the hosted coordination server for full self-sovereignty. It is well-maintained and production-ready for personal and small team use.
Cloudflare Zero Trust / Cloudflare Access
Cloudflare’s Zero Trust product (formerly Cloudflare for Teams) is a full ZTNA platform built on Cloudflare’s global edge network. It is a different approach from Tailscale: instead of a mesh network, it puts Cloudflare between your users and your services, making access decisions at the edge.
What It Is
Cloudflare Zero Trust has three main components:
- Cloudflare Tunnel (cloudflared): Creates an outbound-only encrypted tunnel from your server to Cloudflare’s edge. No inbound ports required.
- Cloudflare Access: Identity-aware proxy that sits in front of your tunneled applications. Every request is authenticated before reaching your origin.
- Cloudflare Gateway: DNS and HTTP filtering, threat intelligence, DLP.
The architecture:
User → Cloudflare Edge (Access policy enforced) → Tunnel → Your Server
↑
Identity check (Google/GitHub/Azure/OTP)
Device posture check
IP/country rules
Cloudflare Tunnel (cloudflared)
The tunnel daemon creates a persistent outbound connection from your server to the nearest Cloudflare PoP. Traffic flows through this connection — your server needs no open inbound ports.
Installation:
|
|
Tunnel configuration (~/.cloudflared/config.yml):
|
|
DNS routing:
|
|
Running as a systemd service:
|
|
If you prefer to manage it yourself:
|
|
Cloudflare Access: Protecting Applications
Access is configured in the Cloudflare Zero Trust dashboard (one.dash.cloudflare.com). Here’s the workflow for protecting a self-hosted app:
Step 1: Create an application
In Zero Trust dashboard: Access → Applications → Add an application → Self-hosted.
Set:
- Application name:
Gitea - Application domain:
gitea.yourdomain.com - Session duration:
24 hours
Step 2: Configure an identity provider
Zero Trust dashboard → Settings → Authentication → Add new.
Options include:
- Google — OAuth2, uses existing Google accounts. Zero setup for personal use.
- GitHub — Great for developer teams.
- Azure AD — Enterprise IdP integration.
- One-time PIN (OTP) — Cloudflare emails a 6-digit code to the user. No IdP required. Excellent for granting access to specific email addresses without an account.
Step 3: Create an Access policy
On the application, add a policy:
Policy name: Allow engineers
Action: Allow
Include:
- Emails ending in: @yourcompany.com
- Identity provider: Google
Policy name: Allow specific guests
Action: Allow
Include:
- Emails: contractor@external.com
- Identity provider: One-time PIN
Policies are evaluated top-to-bottom. You can stack conditions:
- Email + identity provider
- Country (allow/block by geography)
- IP ranges
- Device posture (requires WARP client)
- Valid certificate
Step 4: Test it
Visit https://gitea.yourdomain.com from a browser. You’ll see the Cloudflare Access login page. Authenticate with Google (or OTP), and Cloudflare issues a JWT cookie that grants access for the session duration.
From this point, your service is protected. Someone who discovers the URL gets the Access login page — not your application — unless they authenticate with an allowed identity.
Cloudflare WARP
WARP is the Cloudflare device client. When enrolled in Zero Trust:
- Encrypts all device traffic and routes it through Cloudflare Gateway
- Enables device posture checks (OS version, serial number, certificate)
- Lets Access policies require WARP enrollment before granting access
|
|
Cloudflare Gateway
Gateway provides DNS and HTTP-level filtering across all enrolled devices:
- DNS filtering: Block malware, phishing, adult content, or specific categories at the resolver level. Works without WARP — just point your DNS to
1.1.1.2/1.0.0.2for the free “Families” tier. - HTTP inspection: Deep packet inspection on HTTP traffic. Block specific URLs, file types, or data patterns.
- DLP: Prevent sensitive data (credit card numbers, SSNs) from leaving managed devices.
For homelabs, Gateway DNS filtering is a solid Pi-hole alternative that works across all roaming devices without needing a self-hosted DNS server.
Free Tier Limits
Cloudflare Zero Trust free tier (as of early 2026):
- Up to 50 users
- Unlimited applications and tunnels
- Basic Access policies with most IdP integrations
- Gateway DNS filtering
- WARP client (basic posture checking)
The paid tier adds: CASB, advanced DLP, Browser Isolation, Access for Infrastructure (SSH/RDP proxying), and higher seat counts. For a homelab or small team, the free tier is genuinely sufficient.
Practical Homelab Zero Trust Architecture
Here is a concrete architecture that combines both tools, segmenting by access pattern:
INTERNET
│
┌─────────────┴──────────────┐
│ │
[Cloudflare Edge] [Tailscale Network]
Public-facing apps Admin/infrastructure
Access policy enforced ACL policy enforced
│ │
[cloudflared] [tailscaled]
tunnel on server subnet router + nodes
│ │
└─────────────┬──────────────┘
[Home Server]
192.168.1.10
│
┌──────────────┼──────────────┐
│ │ │
[Jellyfin] [Gitea/Forgejo] [Homeassistant]
:8096 :3000 :8123
Public-facing services (Jellyfin, Gitea, Nextcloud) get a Cloudflare Tunnel with Access policies. Users authenticate with Google or OTP before reaching the service. No ports open on your router.
Admin/infrastructure access (SSH, database, Proxmox console, monitoring dashboards) is only reachable via Tailscale. ACLs enforce that only your admin user account can reach these services. There is no public URL — the services are invisible unless you’re on the tailnet.
Subnet routing: One Tailscale node on the home server advertises 192.168.1.0/24. This means all your homelab devices (NAS, printer, network gear) are reachable from anywhere via their LAN IP, without Tailscale installed on each one.
Segmentation logic:
- LAN devices: accessible to
group:adminsvia subnet route - Homelab servers (tagged
tag:homelab): accessible togroup:adminson all ports,group:familyon ports 22, 80, 443 - Containers (tagged
tag:container): only communicate with each other on defined ports, no access fromgroup:family - Public apps: routed via Cloudflare Tunnel, no Tailscale exposure
This design means:
- A compromised Cloudflare Access session exposes only the public app, not your admin interfaces
- A compromised Tailscale device (if it’s
tag:container) can’t pivot to SSH intotag:server - Your admin SSH access requires both Tailscale (network layer) and Tailscale SSH (identity layer)
Other Tools Worth Knowing
Authelia
Self-hosted authentication and authorization server. Acts as a ForwardAuth middleware for Nginx, Traefik, and Caddy — any service behind the reverse proxy can be gated behind Authelia’s login page with MFA support (TOTP, hardware keys, Duo).
|
|
Authelia integrates with LDAP/AD for user storage and supports fine-grained policies per domain. Good for: protecting all your self-hosted apps with SSO when you don’t want to pay for Cloudflare Access or hand your data to Google.
Authentik
A more feature-rich self-hosted IdP. Supports SAML, OIDC, LDAP, SCIM, and RADIUS. Can serve as a full identity provider for other Zero Trust tools (including Cloudflare Access and Tailscale). Steeper setup than Authelia but supports more protocols and more complex flows like Just-In-Time provisioning.
HashiCorp Boundary
Session-based infrastructure access control. Instead of permanent credential distribution (SSH keys everywhere), Boundary issues time-limited, audited sessions to specific targets. Supports dynamic host catalogs from AWS, Azure, and GCP. An engineer requests a session, Boundary verifies their identity via your IdP, and issues a short-lived credential for exactly the database or SSH target they need.
Teleport
A full access plane for SSH, Kubernetes, databases, and web applications. Includes a certificate authority, session recording, audit logs, and role-based access control. Teleport sits in front of your infrastructure and proxies all access. Significantly more complex than Tailscale to operate, but the session recording and compliance features make it attractive for regulated environments.
NetBird
An open-source Tailscale alternative built on WireGuard. Self-hostable coordination server (the Management service), similar mesh networking, ACL policies, and multi-platform clients. Good choice if you want Tailscale’s UX with no dependency on an external service and you don’t want to manage Headscale’s more limited feature set.
|
|
Comparison Table
| Feature | Tailscale | Cloudflare Zero Trust | Headscale + Authelia |
|---|---|---|---|
| Type | Mesh VPN (ZTNA) | Edge ZTNA proxy | Self-hosted mesh + SSO |
| Identity source | Tailscale/your IdP | Google/GitHub/Azure/OTP | LDAP/local/OIDC |
| Setup complexity | Low | Low-Medium | High |
| Self-hosted option | Headscale | No | Yes (fully) |
| Public app exposure | Funnel (limited) | Tunnel (production-grade) | Reverse proxy + Authelia |
| SSH management | Tailscale SSH | Access for Infrastructure ($) | Standard SSH + ACLs |
| Device posture | Basic (OS, keys) | Advanced (with WARP) | Manual/external |
| Subnet routing | Yes | No | Yes |
| MagicDNS | Yes | No | Manual |
| Free tier | Up to 3 users / 100 devices | 50 users | Unlimited (self-hosted) |
| Best for | Admin/infra access | Public app protection | Full sovereignty |
The pragmatic answer: use Tailscale for internal admin access and Cloudflare Tunnel + Access for public-facing services. They complement each other and the combination covers nearly every homelab and small team use case at zero cost.
Getting Started Checklist
Zero Trust adoption doesn’t have to be a big-bang project. Incrementally replace legacy access patterns:
Week 1 — Inventory and connect
- Install Tailscale on all your servers and personal devices
- Verify all nodes appear in the admin console and can communicate
- Enable MagicDNS
Week 2 — Lock down ACLs
- Replace the default “allow all” ACL with an explicit policy
- Create tag groups:
tag:server,tag:homelab,tag:container - Tag all nodes appropriately
- Test that ACL rules are working (
tailscale pingand port connectivity tests)
Week 3 — Admin access via Tailscale only
- Remove public SSH access (close port 22 in your firewall/router)
- Enable Tailscale SSH on servers
- Add a subnet router if you have LAN devices that can’t run Tailscale
- Close any VPN ports you were using before
Week 4 — Public apps via Cloudflare Tunnel
- Set up Cloudflare Tunnel on the server hosting public services
- Create Access applications for each service
- Configure at least Google or OTP as an IdP
- Test Access from a device not on your Tailscale network
- Close any previously open inbound ports (80/443) on your router
Week 5 — Harden and observe
- Set up Cloudflare Gateway DNS filtering for enrolled devices
- Review Tailscale audit logs for unexpected access
- Review Cloudflare Access logs for authentication attempts
- Set session expiry on Cloudflare Access applications (8-24 hours)
- Enable Tailscale SSH recording if you need audit trails
Ongoing
- Rotate pre-auth keys periodically
- Review ACL policies when users join or leave
- Monitor for deprecated Tailscale client versions in the admin console
- Test your access patterns after making policy changes — a default-deny policy should fail loudly when misconfigured
Zero Trust is not a product you buy — it’s a set of principles you implement incrementally. Start with the biggest wins: eliminating open SSH ports (Tailscale), protecting public apps with identity verification (Cloudflare Access), and writing explicit ACL policies that express exactly who should be able to reach what. Each step reduces your blast radius. A single compromised credential should open one door, not all of them.
The tools are mature, the free tiers are generous, and the configuration is genuinely manageable. There is no reason a homelab or a small team should still be relying on a shared VPN credential and hoping nobody on the network misbehaves.
Comments