How to Configure OpenSSH for Public Key Authentication on External Networks While Allowing Password Auth Internally


1 views

In enterprise environments, it's common to have different authentication requirements for internal vs external SSH access. Public key authentication provides stronger security for internet-facing connections, while password authentication might be acceptable (and more convenient) for trusted internal networks.

The modern way to implement this in OpenSSH is using Match blocks in your sshd_config file. Here's how to structure it:

# Global settings apply to all connections
Port 22
Protocol 2
LoginGraceTime 2m
PermitRootLogin no
MaxAuthTries 3

# Match internal network connections
Match Address 192.168.1.0/24,10.0.0.0/8
    PasswordAuthentication yes
    AuthenticationMethods publickey,password

# Match everything else (external connections)
Match all
    PasswordAuthentication no
    AuthenticationMethods publickey

For more complex network configurations, you can combine multiple matching criteria:

Match Address 192.168.1.0/24,10.0.0.0/8 User *,!root
    PasswordAuthentication yes
    PubkeyAuthentication yes

After making changes, always test your configuration before restarting the SSH daemon:

sudo sshd -t

If no errors are reported, apply the changes:

sudo systemctl restart ssh

If you're having problems, check these common pitfalls:

  • Ensure your network ranges are correctly specified
  • Verify that the Match blocks appear after global directives
  • Check for typos in the configuration file

To verify the policy is working as intended, monitor your auth.log:

sudo tail -f /var/log/auth.log | grep sshd

In enterprise environments, it's common to need different authentication methods for SSH based on network origin. Public key authentication provides stronger security for external connections, while password authentication might be acceptable (or even required) for internal networks due to existing authentication systems.

The solution involves using Match Address directives in the sshd_config file to apply different authentication rules based on the client's IP address. Here's how to implement it:

# /etc/ssh/sshd_config
# Global settings apply to all connections
Port 22
Protocol 2
LoginGraceTime 60
PermitRootLogin no
MaxAuthTries 3

# Default: require public key authentication for all
AuthenticationMethods publickey
PubkeyAuthentication yes
PasswordAuthentication no

# Internal network exception (192.168.1.0/24 in this example)
Match Address 192.168.1.0/24
    PasswordAuthentication yes
    AuthenticationMethods publickey,password

For more complex network setups, you can combine multiple conditions:

Match Address 192.168.1.*,10.0.0.*
    PasswordAuthentication yes
    AuthenticationMethods publickey,password
    PermitEmptyPasswords no

After modifying the configuration, always test and validate:

# Test configuration syntax
sudo sshd -t

# Reload SSH service
sudo service ssh reload

# Verify from internal network (should accept password)
ssh -o PreferredAuthentications=password user@server

# Verify from external network (should reject password)
ssh -o PreferredAuthentications=password user@public-ip

When implementing this configuration:

  • Ensure internal network ranges are properly specified
  • Monitor authentication attempts for brute force attacks
  • Consider additional protections like fail2ban for public interfaces
  • Regularly rotate SSH host keys and user keys

If authentication isn't working as expected:

# Check authentication logs
tail -f /var/log/auth.log

# Verify PAM configuration isn't overriding SSH settings
cat /etc/pam.d/sshd

# Check SELinux/AppArmor permissions if applicable