{
  "id": "ssh-access-controls",
  "title": "SSH Server Access Controls",
  "category": "access",
  "tags": ["ssh", "sshd_config", "AllowUsers", "AllowGroups", "security", "hardening"],
  "updated": "2025-10-29",
  "summary": "Restricting who can SSH in using sshd_config directives.",
  "sections": [
    {
      "heading": "The Config File",
      "body": "<p>SSH server configuration lives in <code>/etc/ssh/sshd_config</code>. Drop-in overrides can go in <code>/etc/ssh/sshd_config.d/*.conf</code>.</p><p><strong>Always test your config before reloading:</strong></p>",
      "code": "sshd -t\n# If it prints nothing and exits 0, the config is valid.\nsystemctl reload ssh"
    },
    {
      "heading": "AllowUsers and AllowGroups",
      "body": "<p>These are whitelist directives. If either is set, only matching users or group members can log in. If neither is set, all users may try.</p>",
      "code": "# Only these users may log in\nAllowUsers alice bob deploy\n\n# Only members of these groups may log in\nAllowGroups sshusers ops\n\n# Combining: user must match AllowUsers AND (if AllowGroups is set) be in an allowed group\n# These are independent filters—if both are set, a user must satisfy both."
    },
    {
      "heading": "DenyUsers and DenyGroups",
      "body": "<p>Blacklist alternatives. <code>DenyUsers</code> and <code>DenyGroups</code> are checked before Allow rules.</p><p>Prefer <code>AllowUsers</code>/<code>AllowGroups</code> over Deny lists—it is safer to enumerate who <em>can</em> in rather than who cannot.</p>"
    },
    {
      "heading": "Other Common Restrictions",
      "body": "",
      "code": "# Disable root login entirely (recommended)\nPermitRootLogin no\n\n# Disable password authentication (once keys are working)\nPasswordAuthentication no\n\n# Change the listening port (minor obscurity, not real security)\nPort 2222\n\n# Restrict to specific network interface\nListenAddress 10.42.0.1\n\n# Idle session timeout (seconds × count before disconnect)\nClientAliveInterval 300\nClientAliveCountMax 2"
    },
    {
      "heading": "Match Blocks",
      "body": "<p>You can apply different rules to specific users, groups, or source addresses:</p>",
      "code": "# Allow password auth only from the management network\nMatch Address 10.42.0.0/24\n    PasswordAuthentication yes\n\n# Give one user a restricted shell\nMatch User backup-agent\n    ForceCommand /usr/local/bin/backup-only\n    AllowTcpForwarding no"
    },
    {
      "heading": "Checking Who Has Access",
      "body": "<p>There is no built-in command to list all users who currently satisfy the access rules. Check manually:</p>",
      "code": "# Current AllowUsers/AllowGroups settings\ngrep -iE '(AllowUsers|AllowGroups|DenyUsers|DenyGroups)' /etc/ssh/sshd_config\n\n# Members of a group\ngetent group sshusers\n\n# All users with a valid shell (can SSH in if no restrictions)\ngrep -v '/nologin\\|/false' /etc/passwd"
    }
  ]
}
