CIS Tailscale Benchmark
Security configuration benchmark for Tailscale mesh VPN
v1.0.0 03-2025Overview
▶This benchmark provides prescriptive guidance for establishing a secure configuration posture for Tailscale. It covers ACL policy configuration, device authorization, MagicDNS and HTTPS certificates, key expiry management, network flow logging, subnet route restrictions, exit node security, state file permissions, Tailscale SSH hardening, and Funnel/Serve usage controls.
| Section | Area | Focus |
|---|---|---|
| 1 | Installation & Daemon | Version, daemon config |
| 2 | Access Control & Authorization | ACLs, device auth |
| 3 | DNS & Key Management | MagicDNS, key expiry |
| 4 | Logging & Monitoring | Daemon logs, flow logs |
| 5 | Routing & Exit Nodes | Subnet routes, exit nodes |
| 6 | File System Security | State file, socket perms |
| 7 | SSH & Services Hardening | TS SSH, Funnel/Serve |
Profile Definitions
▶| Profile | Description | Intended Use |
|---|---|---|
| L1 | Level 1 — Standard | Essential security for all Tailscale deployments; minimal performance impact. |
| L2 | Level 2 — Hardened | Advanced hardening for PCI-DSS, HIPAA, or high-security environments. |
1 — Installation & Daemon
▶1.1 Version & Configuration
▶This recommendation verifies that Tailscale is running the latest stable version on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check Tailscale version tailscale version tailscale status
# Update Tailscale apt-get update && apt-get install -y tailscale # or curl -fsSL https://tailscale.com/install.sh | sh tailscale up
This recommendation verifies that the tailscaled daemon is properly configured on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check Tailscale daemon configuration systemctl status tailscaled ps -eo user,pid,args | grep tailscaled | grep -v grep
# Configure tailscaled # In /etc/default/tailscaled: FLAGS="--state=/var/lib/tailscale/tailscaled.state --socket=/var/run/tailscale/tailscaled.sock --port=41641" systemctl restart tailscaled
2 — Access Control & Authorization
▶2.1 ACLs & Device Auth
▶This recommendation verifies that ACL policies enforce least privilege on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check ACL policy (via admin console or API) tailscale status --json | python3 -m json.tool | grep -A5 'ACL' curl -s -H "Authorization: Bearer $TS_API_KEY" https://api.tailscale.com/api/v2/tailnet/-/acl
# Configure ACL policy
# In Tailscale admin console > Access Controls:
{
"acls": [
{"action": "accept", "src": ["group:engineering"], "dst": ["tag:servers:22,443"]},
{"action": "accept", "src": ["group:devops"], "dst": ["*:*"]}
],
"groups": {
"group:engineering": ["user1@example.com", "user2@example.com"],
"group:devops": ["admin@example.com"]
}
}This recommendation verifies that device authorization and key management are configured on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check device authorization
tailscale status --json | python3 -c "import sys,json; d=json.load(sys.stdin); [print(p['HostName'],p.get('KeyExpiry','')) for p in d.get('Peer',{}).values()]"# Configure device authorization policy
# In admin console:
# 1. Enable device approval: Require admin approval for new devices
# 2. Set key expiry:
tailscale up --auth-key=tskey-auth-xxx --accept-dns=true
# Configure auto-approval with tags:
{
"tagOwners": {
"tag:servers": ["group:devops"],
"tag:ci": ["group:devops"]
},
"autoApprovers": {
"routes": {"10.0.0.0/8": ["tag:servers"]}
}
}3 — DNS & Key Management
▶3.1 MagicDNS & Expiry
▶This recommendation verifies that MagicDNS and HTTPS certificates are enabled on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check MagicDNS and HTTPS
tailscale status --json | python3 -c "import sys,json; d=json.load(sys.stdin); print('MagicDNS:',d.get('MagicDNSSuffix',''))"# Enable MagicDNS and HTTPS certificates # In admin console > DNS: # 1. Enable MagicDNS # 2. Enable HTTPS Certificates # On nodes: tailscale cert machine-name.tailnet-name.ts.net # Use in nginx/caddy configuration
This recommendation ensures that key expiry is enforced for all non-server nodes on the Tailscale mesh VPN. Enforcing this requirement establishes a minimum security standard and prevents insecure configurations.
Without this enforcement, the Tailscale mesh VPN may accept insecure configurations that weaken overall security posture. Mandating this control ensures consistent protection against common attack vectors.
# Check key expiry settings
tailscale status --json | python3 -c "import sys,json; d=json.load(sys.stdin); print('Expires:',d.get('Self',{}).get('KeyExpiry',''))"# Configure key expiry
# In admin console > Settings > Keys:
# Set key expiry to 90 days or less
# Disable key expiry only for tagged servers:
{
"nodeAttrs": [
{"target": ["tag:servers"], "attr": ["funnel"]}
]
}
# Re-authenticate expired nodes:
tailscale up --force-reauth4 — Logging & Monitoring
▶4.1 Daemon & Flow Logs
▶This recommendation verifies that daemon logging is configured and forwarded on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check Tailscale logging tailscale bugreport --diagnose 2>&1 | head -20 journalctl -u tailscaled --no-pager | tail -20
# Configure logging # Tailscale logs to journald by default # Forward logs to centralized system: cat > /etc/rsyslog.d/tailscale.conf << 'EOF' if $programname == 'tailscaled' then /var/log/tailscale.log & stop EOF systemctl restart rsyslog # View network logs in admin console > Logs
This recommendation verifies that network flow logs are enabled on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check network flow logging curl -s -H "Authorization: Bearer $TS_API_KEY" https://api.tailscale.com/api/v2/tailnet/-/network-logs 2>&1 | head -5
# Enable network flow logs # In admin console > Logs > Network flow logs: # Enable and configure log streaming # Stream to SIEM: # - Splunk HEC # - S3 bucket # - Elasticsearch # Configure log retention period
5 — Routing & Exit Nodes
▶5.1 Subnets & Exit Nodes
▶This setting ensures that subnet routes are restricted to required ranges on the Tailscale mesh VPN. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.
Unrestricted access to this capability could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the Tailscale mesh VPN is essential for defense in depth.
# Check subnet routes
tailscale status --json | python3 -c "import sys,json; d=json.load(sys.stdin); [print(p['HostName'],p.get('AllowedIPs',[])) for p in d.get('Peer',{}).values() if p.get('AllowedIPs')]" 2>/dev/null# Configure subnet routes securely
# Advertise only required subnets:
tailscale up --advertise-routes=10.0.1.0/24,10.0.2.0/24 --accept-routes
# Restrict route approval in ACLs:
{
"autoApprovers": {
"routes": {
"10.0.1.0/24": ["tag:gateway"],
"10.0.2.0/24": ["tag:gateway"]
}
}
}This setting ensures that exit nodes are authorized and restricted on the Tailscale mesh VPN. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.
Unrestricted access to this capability could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the Tailscale mesh VPN is essential for defense in depth.
# Check exit node configuration
tailscale status --json | python3 -c "import sys,json; d=json.load(sys.stdin); [print(p['HostName'],'exit-node') for p in d.get('Peer',{}).values() if p.get('ExitNode')]" 2>/dev/null# Configure exit nodes securely
# Only authorize designated nodes as exit nodes:
tailscale up --advertise-exit-node
# Approve in admin console
# In ACLs, restrict who can use exit nodes:
{
"autoApprovers": {
"exitNode": ["tag:exit-nodes"]
}
}
# Users opt in: tailscale up --exit-node=<hostname>6 — File System Security
▶6.1 State & Socket Permissions
▶This setting ensures that state file permissions are restricted on the Tailscale mesh VPN. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.
Unrestricted access to this capability could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the Tailscale mesh VPN is essential for defense in depth.
# Check state file permissions
stat -c '%a %U %G' /var/lib/tailscale/tailscaled.state
find /var/lib/tailscale -type f -exec stat -c '%a %U %G %n' {} \;# Restrict state file permissions chown root:root /var/lib/tailscale/tailscaled.state chmod 600 /var/lib/tailscale/tailscaled.state chmod 700 /var/lib/tailscale
This recommendation verifies that socket permissions restrict CLI access on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check socket permissions stat -c '%a %U %G' /var/run/tailscale/tailscaled.sock
# Restrict socket access chmod 660 /var/run/tailscale/tailscaled.sock chown root:tailscale /var/run/tailscale/tailscaled.sock # Only users in tailscale group can use CLI
7 — SSH & Services Hardening
▶7.1 Tailscale SSH & Funnel
▶This recommendation verifies that Tailscale SSH enforces re-authentication and non-root users on the Tailscale mesh VPN. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the Tailscale mesh VPN vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check SSH configuration
tailscale status --json | python3 -c "import sys,json; d=json.load(sys.stdin); print('SSH:',d.get('Self',{}).get('SSH',''))" 2>/dev/null# Configure Tailscale SSH securely
# In ACLs:
{
"ssh": [
{
"action": "check",
"src": ["group:devops"],
"dst": ["tag:servers"],
"users": ["autogroup:nonroot"]
}
]
}
# Use 'check' action for re-authentication
# Restrict to non-root usersThis setting ensures that Funnel/Serve access is restricted on the Tailscale mesh VPN. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.
Unrestricted access to this capability could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the Tailscale mesh VPN is essential for defense in depth.
# Check Funnel and Serve tailscale serve status 2>/dev/null tailscale funnel status 2>/dev/null
# Restrict Funnel/Serve usage
# In ACLs, restrict who can use Funnel:
{
"nodeAttrs": [
{
"target": ["tag:web-servers"],
"attr": ["funnel"]
}
]
}
# Only enable Serve for specific services:
tailscale serve https / http://127.0.0.1:3000
# Disable when not needed:
tailscale serve reset