Kali Linux Zero-Trust Network Posture: Design, Checks, and Failure Modes
Kali Linux boots with all network-facing daemons masked, enforcing a strict zero-trust boundary for offensive work. This guide walks through the design, operational checks, and common failure modes.
04 Aug 2025, 12:16 UTC

Problem Statement: Unintended Exposure in Offensive Labs
Penetration testers often run Kali Linux on laptops, live USBs, or virtual machines. If the OS automatically starts network services, the tester’s machine becomes an attack surface: SSH, databases, web servers, or mDNS can be discovered by defenders, leaking presence and providing footholds. Kali’s design goal is to boot into a “clean” state—no listening sockets, no advertising on the network—until the operator explicitly enables a service for a job.
Requirements
- Zero-trust network boundary: the host must not assume any network context at boot.
- Explicit enablement: every network-facing daemon must be started only when the operator deems it safe.
- Minimal state change: the design should not alter the base Debian system beyond masking units.
- Verifiability: operators must be able to audit the current state with simple commands.
Smallest Suitable Design
The design relies on systemd, the init system used by Debian and its derivatives. Kali ships a preset file /usr/lib/systemd/system-preset/90-kali.preset that masks a curated list of services. Masking in systemd means the unit file is symlinked to /dev/null, preventing systemctl start from pulling it in automatically via dependencies or boot targets. The preset is applied at boot via the /usr/lib/systemd/system-preset directory, which systemd checks before loading any unit.
# /usr/lib/systemd/system-preset/90-kali.preset
# Disable all units by default
disable *
# Mask specific network daemons
mask ssh.service postgresql.service apache2.service smbd.service avahi-daemon.service
Because Kali is built on Debian, no custom init system is required. The preset file is the single source of truth; any package that ships a unit file for a network service will be masked unless the operator overrides it.
Trust / Data Boundaries
- Trust boundary: Only the local
rootuser is trusted at boot. No network trust is assumed. - Data boundary: All data generated by Kali tools (pcaps, logs, loot) resides locally. The operator must explicitly enable services that would expose data, e.g., starting PostgreSQL for Metasploit or an HTTP listener for a reverse shell.
Operational Checks
After a fresh boot (live or installed), operators should confirm that no network services are running and that the preset is in effect.
- Verify masked units:
# Run as root systemctl list-unit-files --state=masked # Expected output includes # ssh.service # postgresql.service # apache2.service # smbd.service # avahi-daemon.service - Check listening sockets:
# ss -ltn # (empty output on a clean boot)If any line appears, a service is listening. Investigate with
systemctl status <service>. - Inspect kernel hardening parameters:
# journalctl -b -u systemd-sysctl | grep net.ipv4.conf.all.accept_redirects # Expected: net.ipv4.conf.all.accept_redirects=0Other parameters (e.g.,
net.ipv4.conf.all.send_redirects=0) are also set by thekali-defaultspackage. - Confirm preset file contents:
# cat /usr/lib/systemd/system-preset/90-kali.preset - Test enablement path:
# systemctl start ssh # systemctl status ssh # (service starts, but remains masked for future boots) # systemctl is-enabled ssh # Output: maskedStarting the service is allowed; it is not automatically started again on the next boot.
Failure Modes and Mitigation
Even with a robust design, certain events can re-enable services or expose the host.
- Package upgrades dropping the preset:
Some upgrades may remove
90-kali.presetor replace it with a newer version that does not mask all services. Mitigation: usedpkg-divertto keep the original file or pin the package version. - Third-party tools installing new units:
Tools like
metasploit-frameworkmay ship their own systemd units. Operators should runsystemd-analyze verifyin CI or manually audit/etc/systemd/systemafter installing new tools. - Operator forgetting to stop services:
Once a service is started, it remains active until stopped. Use session-scoped
--userunits or scripts that stop services on exit to prevent lingering listeners. - Live USB persistence overlay:
When enabling a service on a persistent live USB, the change is written to the overlay. Verify with
systemctl is-enabled sshafter each session; if it returnsenabled, disable it again or clear persistence. - Container networking:
Docker containers launched with
--network hostshare the host namespace, bypassing the mask. Use--network bridgeor create a dedicated network, and ensure container services are also masked if needed.
Conditions That Would Change the Design
- Immutable or atomic base images: Preset files would be replaced by image-policy layers. The design would shift to image signing and policy enforcement rather than local masks.
- Regulatory requirement for auditd logging: Enabling
auditdwith network listeners would require a different approach: the service would remain masked but be explicitly enabled in contexts that require audit logs. - Layered tooling with systemd-sysext: If Kali adopts
systemd-sysextfor optional toolsets, the design would need to ensure that extensions do not override the preset unless explicitly allowed.
Practical Verification Checklist
# 1. Boot into Kali (live or installed)
# 2. Verify no listening sockets
ss -ltn
# 3. List masked units
systemctl list-unit-files --state=masked | grep -E 'ssh|postgresql|apache2|smbd|avahi-daemon'
# 4. Confirm preset file
cat /usr/lib/systemd/system-preset/90-kali.preset
# 5. Test starting a service
systemctl start ssh
# 6. Verify it is masked for future boots
systemctl is-enabled ssh
If any step fails, consult the logs (journalctl -b) and check package integrity. Remember that masking is not a firewall; if you start a service, it will listen until you stop it.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.