Zero trust is not a product you buy — it is a security architecture philosophy that assumes no user, device, or network segment is inherently trustworthy, even inside your perimeter. The old model: trust everything inside the firewall. Zero trust: verify everything, always, regardless of location. This guide explains how to implement zero trust principles using free and low-cost tools.
The Core Principles of Zero Trust
Zero trust is built on three core principles from NIST SP 800-207:
- Verify explicitly: Authenticate and authorize every request based on all available data points — user identity, device health, location, service/workload, data classification
- Use least privilege access: Limit user access with just-in-time and just-enough-access, risk-based adaptive policies, and data protection
- Assume breach: Minimize blast radius, segment access, verify end-to-end encryption, use analytics to get visibility and drive threat detection
Zero Trust vs. Traditional Perimeter Security
# Traditional (Castle-and-Moat) model:
# Internet -> Firewall -> "Trusted" Internal Network
# Everything inside = trusted
# Problem: Once an attacker breaches the perimeter, they move laterally freely
# SolarWinds, Colonial Pipeline - both demonstrated perimeter failure
# Zero Trust model:
# Internet -> Identity Verification -> Device Compliance Check -> Policy Engine -> Resource
# Every request = re-verified, regardless of source IP
# Even employees on corporate LAN are not automatically trustedImplementing Zero Trust with Free Tools
1. Identity: Conditional Access with Keycloak
Keycloak is a free, open-source Identity and Access Management (IAM) solution that implements OIDC and SAML. It provides SSO, MFA, and conditional access policies.
# Deploy Keycloak with Docker
docker run -d --name keycloak -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin123 quay.io/keycloak/keycloak:latest start-dev
# Access at http://localhost:8080
# Create realm, clients, users
# Enable MFA (OTP) for all users
# Realm Settings > Authentication > Required Actions > Configure OTP (mark as Default Action)
# Conditional access policies via Keycloak Authentication Flows:
# Create flow: "ZeroTrust_Flow"
# Step 1: Username/Password
# Step 2: OTP (required)
# Step 3: Device fingerprint check (custom authenticator)
# Block login from non-compliant countries
# Create authentication condition: Browser flow > Add condition > Client Scopes
# Or use IP restriction via network policies at reverse proxy level2. Device Trust with OpenZiti (Zero Trust Networking)
OpenZiti (formerly NetFoundry) is an open-source zero trust network overlay. Instead of a VPN, it embeds zero trust authentication directly into the application or via a proxy. No implicit trust based on IP address — identity is the network boundary.
# Deploy OpenZiti controller and router
docker run -d --network ziti-network --name ziti-controller openziti/quickstart:latest
# Create identity (zero trust credential for a user or service)
ziti edge create identity user alice -o alice.jwt
# Enroll the identity on Alice's device
ziti edge enroll --jwt alice.jwt
# Create a service (application endpoint)
ziti edge create service "corporate-app" --encryption REQUIRED
# Create policy: only alice's enrolled device can access corporate-app
ziti edge create service-policy "alice-can-access-app" Bind --identity-roles '#alice' --service-roles '@corporate-app'
# Result: corporate-app is completely dark on the internet
# Only devices with valid, enrolled identities can even find it3. Network Micro-Segmentation
# Traditional: One big flat network
# Zero Trust: Every workload in its own segment, explicit allow-list rules only
# Example: Implement micro-segmentation with iptables (Linux)
# Default deny everything between segments
iptables -P FORWARD DROP
# Allow only specific, necessary flows
# Web server can talk to database on port 5432 only
iptables -A FORWARD -s 10.0.1.10 -d 10.0.2.10 -p tcp --dport 5432 -j ACCEPT
iptables -A FORWARD -s 10.0.2.10 -d 10.0.1.10 -p tcp --sport 5432 -j ACCEPT
# Database cannot initiate connections to web server
iptables -A FORWARD -s 10.0.2.10 -d 10.0.1.10 -p tcp --dport 80 -j DROP
# Using Calico for Kubernetes micro-segmentation
# Apply NetworkPolicy: deny all ingress by default, allow only specific
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- port: 80804. Privileged Access Management with CyberArk Conjur (Free)
# Conjur Open Source: Free PAM for secrets management
docker-compose -f docker-compose.yml pull
docker-compose up -d
# Initialize Conjur
docker-compose exec conjur conjurctl account create myorg | tee conjur.out
# Save admin API key from output!
# Store a secret
conjur variable set -i "production/db_password" -v "$(openssl rand -base64 32)"
# Retrieve secret (applications use short-lived tokens, not stored passwords)
conjur variable get -i "production/db_password"
# Machine identity: Each service gets a unique machine identity
# Humans use human identities (with MFA)
# Services use machine identities (no passwords in code/config)Zero Trust Implementation Roadmap
Zero trust is a journey, not a deployment. Here is a practical roadmap:
Phase 1: Visibility (Months 1-3)
# Inventory EVERYTHING
# Users: Get-ADUser -Filter * | Measure-Object (count all accounts)
# Devices: nmap -sV 10.0.0.0/8 | grep "Nmap scan report" | wc -l
# Applications: netstat -tulnp on all servers
# Data: Find sensitive data locations with DLP scan
# Connections: Zeek + SIEM to map all network flows
# You cannot protect what you cannot see
# Build the inventory before designing the architecturePhase 2: Protect Most Critical Assets First (Months 4-9)
# Tier 0 (most critical): Domain Controllers, PKI, PAM
# Apply zero trust controls to Tier 0 first
# - Require MFA for ALL access
# - Limit admin access to dedicated jump servers
# - Log ALL administrative actions
# - Review all access quarterly
# Jump server configuration (Linux)
# /etc/ssh/sshd_config additions:
AllowGroups Tier0_Admins
MaxAuthTries 2
ForceCommand /bin/bash # Force command logging
Banner /etc/legal_notice.txt
# Log all commands via script wrapper
# /etc/profile.d/record_session.sh
if [ "$SSH_ORIGINAL_COMMAND" == "" ]; then
SCRIPT_LOGFILE="/var/log/sessions/$USER-$(date +%Y%m%d-%H%M%S).log"
script -q -f $SCRIPT_LOGFILE
fiPhase 3: Device Trust and Compliance (Months 10-18)
# Implement device compliance checking before granting network access
# MDM (Mobile Device Management) for device health verification
# Open-source MDM: JAMF Community, Mosyle, or simple Python checks
# Compliance check script (run before VPN allows connection)
#!/bin/bash
COMPLIANT=true
# Check OS patch level
PATCH_DAYS=$(( ($(date +%s) - $(stat -c %Y /var/lib/apt/periodic/update-success-stamp 2>/dev/null || echo 0)) / 86400 ))
[ $PATCH_DAYS -gt 30 ] && COMPLIANT=false && echo "FAIL: Patches overdue by $PATCH_DAYS days"
# Check disk encryption
lsblk -o NAME,FSTYPE,MOUNTPOINT | grep -q "crypto_LUKS" || { COMPLIANT=false; echo "FAIL: Disk not encrypted"; }
# Check firewall
ufw status | grep -q "Status: active" || { COMPLIANT=false; echo "FAIL: Firewall disabled"; }
# Check antivirus last scan
# Check for malware indicators
$COMPLIANT && echo "COMPLIANT: Device passes all checks" || { echo "BLOCK: Device not compliant"; exit 1; }Zero trust dramatically reduces the blast radius of any breach. When Colonial Pipeline’s VPN was compromised, the attacker had access to the entire network because the perimeter model trusts everyone inside it. In a zero trust architecture, that compromised VPN credential would only grant access to specific, explicitly authorized resources — not the entire company network. Zero trust is not a silver bullet, but it is the most impactful architectural change an organization can make to reduce breach impact.