SSHD Configuration Guide: Using AllowUsers and AllowGroups Together Effectively


2 views

When configuring SSH access control, it's crucial to understand how AllowUsers and AllowGroups interact. These directives don't override each other but work in conjunction with the following logic:

# User must satisfy BOTH conditions when both directives are present:
1. User must be listed in AllowUsers (if present)
2. User must belong to a group listed in AllowGroups (if present)

The core issue emerges from the unexpected interaction between these directives. Take this example configuration:

AllowUsers user1 user2
AllowGroups ssh-users

Even though testuser belongs to ssh-users, access is denied because:

  • The user isn't explicitly listed in AllowUsers
  • SSHd requires BOTH conditions to be true by default

Option 1: Use Only AllowGroups

The simplest approach for group-based access control:

# Comment out or remove AllowUsers
# AllowUsers user1 user2
AllowGroups ssh-users

Option 2: Match Directive for Conditional Logic

For more complex scenarios, use Match blocks:

Match Group ssh-users
    AllowUsers *
    
Match All
AllowUsers user1 user2

Option 3: Special Case Handling

When you need to maintain both:

AllowUsers user1 user2 %ssh-users

The % prefix indicates group membership (Debian/Ubuntu specific syntax)

After making changes, always verify:

# Check config syntax
sshd -t

# Reload configuration
systemctl reload sshd

# Test connection
ssh -v testuser@server
  • Prefer group-based access for scalability
  • Document all access rules in configuration comments
  • Consider using SSH certificates for large deployments
  • Regularly audit active users and group memberships

When configuring SSH server access, many administrators need to implement both user-level and group-level restrictions simultaneously. The core issue arises when trying to make AllowUsers and AllowGroups directives work in conjunction rather than conflicting with each other.

The OpenSSH server evaluates access rules in this order:

1. DenyUsers
2. AllowUsers
3. DenyGroups
4. AllowGroups

A user must pass all applicable checks - meaning when both AllowUsers and AllowGroups are specified, the user must be listed in AllowUsers (if the directive exists) and belong to a group in AllowGroups (if specified).

For the described scenario with user testuser in group ssh-users, here's a working configuration:

# /etc/ssh/sshd_config snippet:
AllowUsers user1 user2
AllowGroups ssh-users

# Important: The user must be in BOTH lists:
# 1. Either explicitly in AllowUsers OR not restricted by AllowUsers
# 2. Member of a group in AllowGroups

When troubleshooting, check these critical points:

  • Verify group membership with id <username>
  • Confirm the user's primary group isn't interfering
  • Check for typos in group names (case-sensitive)
  • Ensure PAM isn't overriding SSH rules

For our test case, running:

id testuser
# Should show: uid=1001(testuser) gid=1001(testuser) groups=1001(testuser),1002(ssh-users)

For more flexible management without modifying sshd_config:

# Option 1: Match blocks
Match Group ssh-users
    AllowUsers user1 user2 testuser

# Option 2: LDAP integration
AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys
AuthorizedKeysCommandUser nobody
  • Use centralized authentication (LDAP/AD)
  • Implement certificate-based authentication
  • Combine with Match Address for network-based restrictions
  • Regularly audit access logs (/var/log/auth.log)

Remember to always test configurations with a secondary session before logging out of your primary SSH connection.