Stop Trusting Your Local Network: A Manual for Paranoia
If you are still relying on a single OpenVPN bastion host to secure your production environment, you are operating on a security model from 2010. The perimeter is gone. Between remote developers pushing code from coffee shops in Grünerløkka and automated CI/CD pipelines hammering your API, the concept of a "trusted internal network" is a dangerous hallucination.
I recently audited a setup for a logistics firm in Oslo. They had a rock-solid firewall facing the WAN, but inside? Flat network topology. One compromised developer laptop allowed ransomware to traverse laterally from the staging environment to the production database in under four minutes. They relied on IP whitelisting, which is flimsy at best when IPs drift.
Zero Trust isn't a product you buy; it's a methodology: Never trust, always verify. Every packet, every identity, every time. Today, we are going to build a Zero-Trust implementation on Ubuntu 22.04 LTS, focusing on three layers: Network (WireGuard), Transport (NFTables), and Identity (SSH Certificates).
1. The Mesh: Replacing the VPN Gateway with WireGuard
Hub-and-spoke VPNs introduce a single point of failure and latency bottlenecks. If your VPS in Norway has to route traffic through a gateway in Frankfurt just to talk to a database in the same rack, you are wasting milliseconds. We use WireGuard because it is kernel-space (since Linux 5.6), incredibly fast, and stateless.
Instead of one gateway, we create a mesh where every server can only talk to authenticated peers. Here is a rigorous configuration for a database node that refuses to talk to anything except the app server.
Generating Keys
umask 077 && wg genkey | tee privatekey | wg pubkey > publickey
Configuration: /etc/wireguard/wg0.conf
[Interface]
Address = 10.10.0.2/32
SaveConfig = false
PrivateKey =
ListenPort = 51820
# Application Server Peer
[Peer]
PublicKey =
AllowedIPs = 10.10.0.1/32
Endpoint = 192.168.1.50:51820
# Keep connection alive through NAT
PersistentKeepalive = 25
Why this matters: By explicitly defining `AllowedIPs`, we cryptographically enforce the routing table. If a packet comes from an unknown key, it is dropped silently. No handshake, no logs, no resource consumption.
2. Micro-Segmentation with NFTables
Iptables is legacy. It suffers from sequential rule processing which kills performance under DDoS conditions. NFTables (standard in Debian 11 and Ubuntu 22.04) uses a bytecode VM for packet classification. It is faster and syntax-cleaner.
In a Zero-Trust model, the default policy must be `DROP` for everything, including outbound traffic. You only allow what is necessary. This prevents a compromised server from phoning home to a C2 server.
Pro Tip: When setting up firewalls on remote VPS instances, always run a strict apply command inside a `screen` or `tmux` session with a scheduled rollback, or you will lock yourself out. `nft -f /etc/nftables.conf || sleep 30; cp /etc/nftables.bak /etc/nftables.conf` is your safety net.
The Strict Ruleset
#!/usr/sbin/nft -f
flush ruleset
table inet zerotrust {
chain inbound {
type filter hook input priority 0; policy drop;
# Allow established/related traffic
ct state established,related accept
# Allow Loopback
iifname "lo" accept
# Allow SSH (Rate Limited)
tcp dport 22 limit rate 10/minute accept
# Allow WireGuard UDP
udp dport 51820 accept
# ICMP is necessary for MTU discovery, do not block blindly
ip protocol icmp icmp type { echo-request, destination-unreachable, time-exceeded } limit rate 1/second accept
}
chain outbound {
type filter hook output priority 0; policy drop;
# Allow established
ct state established,related accept
# Allow DNS resolution (restrict to specific resolvers if possible)
udp dport 53 accept
tcp dport 53 accept
# Allow NTP
udp dport 123 accept
# Allow WireGuard traffic out
udp dport 51820 accept
# Allow OS updates (HTTP/HTTPS)
tcp dport { 80, 443 } accept
}
}
Load this config:
nft -f /etc/nftables.conf
3. Identity: Killing Static SSH Keys
Copy-pasting `id_rsa.pub` to `authorized_keys` is unmanageable at scale. It creates static trust anchors that never expire. If a developer leaves the company, you have to scrub every server.
The solution is SSH Certificates. You act as your own Certificate Authority (CA). You sign a developer's key with a validity period (e.g., 8 hours). When the certificate expires, access is revoked automatically.
Setup the CA (On a secure, offline machine)
ssh-keygen -t ed25519 -f user_ca -C "user_ca"
Sign a User Key (Valid for 8 hours)
ssh-keygen -s user_ca -I user_identity -n root,devops -V +8h id_ed25519.pub
Server Configuration (/etc/ssh/sshd_config)
Tell your VPS to trust the CA, not individual keys.
TrustedUserCAKeys /etc/ssh/user_ca.pub
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
AuthenticationMethods publickey
PermitRootLogin prohibit-password
Inside `/etc/ssh/auth_principals/root`, you simply list the allowed roles:
devops
4. Mutual TLS (mTLS) for Application Layer
Network security is not enough. If an attacker breaches the network layer, they shouldn't be able to query your API. mTLS ensures that the client must present a valid certificate to the server, and the server to the client.
Here is how you enforce this in Nginx. This ensures that even if someone bypasses the firewall, Nginx will drop the connection during the TLS handshake.
server {
listen 443 ssl http2;
server_name internal-api.coolvds.com;
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
# Client Certificate Verification
ssl_client_certificate /etc/nginx/certs/ca.crt;
ssl_verify_client on;
location / {
proxy_pass http://localhost:8080;
# Pass details to backend
proxy_set_header X-Client-DN $ssl_client_s_dn;
}
}
Infrastructure Integrity and Norwegian Compliance
Software Zero Trust is useless if the hardware underneath is compromised. This is where the "Noisy Neighbor" problem of cheap VPS hosting becomes a security risk. If a hypervisor is overcommitted, side-channel attacks (like the remnants of Spectre/Meltdown variants) become a theoretical vector.
At CoolVDS, we utilize KVM (Kernel-based Virtual Machine) for strict isolation. Unlike container-based virtualization (LXC/OpenVZ) often found in budget hosting, KVM ensures your kernel is yours alone. Furthermore, for businesses operating in Norway, data residency is a legal requirement under GDPR and the Schrems II ruling. Hosting on CoolVDS ensures your encrypted volumes reside physically in Oslo, within the jurisdiction of the EEA, keeping the Datatilsynet happy.
Performance is a security feature. High availability involves mitigating DDoS attacks. Our upstream network blends include path optimization that detects anomalies before they saturate your interface. Combined with the NVMe storage standard on our nodes, your cryptographic operations (which are heavy on I/O during handshakes) won't become a bottleneck.
Summary
True security requires layering.
- Physical: CoolVDS KVM Isolation (Oslo Datacenter).
- Network: WireGuard Mesh (No central gateway).
- Transport: NFTables (Default Drop).
- Identity: SSH Certificates (Short-lived access).
Stop hoping your perimeter firewall holds. Assume you are already breached and build your architecture to limit the blast radius. If you need a sandbox to test this configuration, spin up a high-frequency compute instance on CoolVDS. The deployment takes less than 60 seconds.