Conditional SSH configuration enables different security policies for specific users, groups, or network locations on the same server, while still using a single /etc/ssh/sshd_config file.

The Match keyword in OpenSSH switches the parser into a conditional context based on attributes such as User, Group, Address, LocalAddress, or Host, so directives inside the block override earlier global settings only for sessions that satisfy the conditions. Evaluation starts with global directives at the top of the file, then proceeds through each Match block in order, with later matches taking precedence over earlier ones when the same directive appears again.

Careful ordering and testing of Match blocks prevents accidental lockouts or overly permissive access, because a misplaced block can shadow later configuration or leave some connections without the intended restrictions. The examples below target a typical Linux server with systemd where the service name is ssh, although some distributions use sshd; root or sudo access on the server is required before altering the configuration.

Steps to apply conditional SSH settings with Match blocks:

  1. Open a terminal session on the SSH server with access to sudo.
    $ whoami
    sysadmin
  2. Create a timestamped backup of the current /etc/ssh/sshd_config file.
    $ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F-%H%M)

    A missing backup complicates recovery if a new Match block blocks remote logins or prevents sshd from starting.

  3. Open /etc/ssh/sshd_config in a text editor with elevated privileges.
    $ sudo nano /etc/ssh/sshd_config

    sudoedit or vim can replace nano based on local preference.

  4. Move to the end of the file so new Match blocks follow global directives and existing comments.

    Match causes subsequent directives to be conditional until a new Match line, so any unconditional settings must appear before the first conditional block.

  5. Insert a Match block that permits password authentication only for a trusted internal subnet by using the Address condition.
    # Global authentication policy
    PasswordAuthentication no
    PubkeyAuthentication yes
    
    # Allow password auth from internal subnet only
    Match Address 192.0.2.0/24
      PasswordAuthentication yes

    The example assumes a baseline of PasswordAuthentication no earlier in the file so password logins stay disabled for all other sources.

  6. Insert a Match Group block that disables forwarding features and forces SFTP for members of a deployment group.
    # Restrict forwarding for deploy group and force internal SFTP
    Match Group deploy
      X11Forwarding no
      AllowTcpForwarding no
      PermitTTY no
      ForceCommand internal-sftp

    Replace group name deploy with an existing system group that owns automation or SFTP-only accounts on the server.

  7. Save the updated /etc/ssh/sshd_config file in the editor so the new conditional blocks persist on disk.
  8. Validate the sshd configuration syntax before restarting the service.
    $ sudo sshd -t

    Silent output indicates a syntactically valid configuration; error messages reference the line that requires correction.

  9. Inspect the effective settings for a simulated connection from a deploy user in the internal subnet.
    $ sudo sshd -T -C "user=deploy,addr=192.0.2.50,host=internal.example.test" | grep -E "passwordauthentication|pubkeyauthentication|allowtcpforwarding|x11forwarding|permittty|forcecommand"
    passwordauthentication yes
    pubkeyauthentication yes
    allowtcpforwarding no
    x11forwarding no
    permittty no
    forcecommand internal-sftp

    sshd -T -C evaluates Match conditions without opening a network socket, which simplifies verification for different users and source addresses.

  10. Restart the ssh service so the new configuration takes effect for incoming connections.
    $ sudo systemctl restart ssh

    An incorrect Match block can prevent new sessions from authenticating, so console or out-of-band access is important before restarting a heavily used server.

  11. Check the ssh service status after the restart to confirm an active state.
    $ sudo systemctl status ssh
    ● ssh.service - OpenBSD Secure Shell server
         Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
         Active: active (running) since Thu 2025-12-11 10:15:01 UTC; 5s ago
    TriggeredBy: ● ssh.socket
    ##### snipped #####
  12. Open an SSH session from a host that matches one of the configured conditions to confirm the observed authentication and forwarding behaviour.
    $ ssh -v deploy@server.example.test
    ##### snipped #####
    debug1: Authentications that can continue: publickey,password
    debug1: Authentication succeeded (publickey).
    debug1: channel 0: new [client-session]
    ##### snipped #####

    Combine verbose client logs with server-side journalctl -u ssh output to debug unexpected Match selections or overlapping conditions.

Discuss the article:

Comment anonymously. Login not required.