Skip to content
Search Rocky Linux

    Browse this documentation

    Rocky 10: why sshd -T does not show your Match settings

    A Rocky Linux 10.2 Server VM with OpenSSH_9.9p1.

    Experiment: read the global effective config, add a source-scoped Match block, evaluate two addresses with sshd -T -C, then clean up. Screenshot: public/evidence/sshd/rocky-match.png.

    $ sshd -T -C user=labuser,host=localhost,addr=192.168.2.241 | grep -E '^(maxauthtries|x11forwarding|passwordauthentication)'
    maxauthtries 6
    passwordauthentication yes
    x11forwarding yes
    CommandAnswersUse it when
    sshd -tis the syntax validright after editing
    sshd -Tglobal effective valueschecking defaults
    sshd -T -C user=…,host=…,addr=…values for that connectionproving a Match applies

    Concluding “my config did nothing” from sshd -T alone is the classic mistake.

    /etc/ssh/sshd_config.d/50-lab-match.conf
    Match Address 192.168.2.240
    MaxAuthTries 2
    X11Forwarding no
    $ sshd -t && echo "config OK"
    config OK
    $ sshd -T -C user=labuser,host=localhost,addr=192.168.2.240 | grep -E '^(maxauthtries|x11forwarding)'
    maxauthtries 2
    x11forwarding no
    $ sshd -T -C user=labuser,host=localhost,addr=192.168.2.241 | grep -E '^(maxauthtries|x11forwarding)'
    maxauthtries 6
    x11forwarding yes

    That is what Match means: one config evaluated per condition, not rules piled onto every connection.

    Rocky Linux 10.2: Match and the per-connection effective config

    Everything after Match belongs to that block, until the file ends or the next Match starts:

    Match Address 192.168.2.0/24
    PasswordAuthentication no
    X11Forwarding no ← absorbed into the Match, affects only that subnet

    Drop-ins are loaded in filename order, so “this setting only affects some clients” usually means a directive meant to be global landed inside a Match block.

    Locate it with:

    Terminal window
    sudo sshd -T -C user=labuser,host=localhost,addr=<suspect> | diff - <(sudo sshd -T) | head

    Match changes parameter values, not reachability:

    • To keep a subnet out entirely, use firewalld — not a Match block with a non-existent user;
    • To allow only certain accounts, use AllowUsers (which can be refined inside Match);
    • Authentication still goes through PAM; MaxAuthTries only limits retries.
    • Assuming sshd -t proves it works: it only checks syntax;
    • Forgetting the reload: systemctl reload sshd;
    • Writing global directives after Match: they become block-local;
    • Inconsistent address syntax: 192.168.2.0/24 and 192.168.2.* both work, mixing them causes oversights.
    Terminal window
    sudo tee /etc/ssh/sshd_config.d/70-user.conf >/dev/null <<'EOF'
    Match User labuser
    MaxSessions 1
    EOF
    sudo sshd -t
    sudo sshd -T -C user=labuser,host=localhost,addr=192.168.2.10 | grep maxsessions
    sudo sshd -T -C user=root,host=localhost,addr=192.168.2.10 | grep maxsessions
    sudo rm /etc/ssh/sshd_config.d/70-user.conf

    Checks:

    1. labuser reports 1, root keeps the default 10;
    2. No reload needed for -T -C (it reads files, never touches sessions);
    3. Both return to the default after removal;
    4. user= and addr= dimensions can be combined.

    常见问题

    Which conditions can Match use?

    Address, User, Group, Host, LocalAddress, LocalPort, RDomain and more; comma-separated values are OR, separate keywords are AND.

    Does sshd -T -C affect live connections?

    No — it parses the config and prints the result; no session is created and nothing is reloaded.

    What if my OpenSSH lacks -T -C?

    -T exists since OpenSSH 6.8 and -C since 7.x; EL8 and later are fine, EL7 needs an upgrade.