Free Tool

sshd_config Verifier: Paste Effective Config, Get the Hardening Verdict

Paste the output of sshd -G (or sudo sshd -T) and the verifier grades the effective values your server actually runs — not the text of the config file. It flags password auth left open through PAM, root login, forwarding, and algorithm lists that are not in your OpenSSH version's default set, then emits a drop-in with only the fixes you pick. Runs entirely in your browser. No signup, no upload.

Pasted output can contain AllowUsers host patterns, Banner paths, and hostnames. Nothing leaves your browser — there is no server round-trip.

Check your sshd_config

Paste the output of sshd -G (preferred — no sudo needed) or sudo sshd -T below, pick your OpenSSH version, and get the verdict. A second paste box takes sudo sshd -T -C user=...,host=...,addr=... output to grade one user or address against its Match blocks.

How to get the paste

Run one of these on the server and copy the whole output, all lines, into the box above.

sshd -G

sshd -G parses the config and prints the effective configuration — every directive with its default filled in, one lowercase keyword value per line. It needs no sudo and no host-key access.

sudo sshd -T

sshd -T prints the same effective configuration and additionally runs the -t validity and key check. That key check is why it fails without sudo on a normal host:

sshd: no hostkeys available -- exiting.

The host keys in /etc/ssh are readable only by root. Run it with sudo, or use sshd -G instead. The two outputs are identical except for the hostkey lines.

For one user or address, add -C:

sudo sshd -T -C user=alice,host=example.com,addr=192.0.2.5

-C applies the Match blocks for that connection before printing. On OpenSSH 9.6, -C only works with -T — sshd -G -C ... fails with:

Config test connection parameter (-C) provided without test mode (-T)

Newer releases also accept -G -C. Check your version first:

sshd -V

Do not paste the raw /etc/ssh/sshd_config file. The verifier grades effective values only, and raw-file text is not effective output: the first obtained value wins, Include files at the top of the main file override later settings, and unset directives are invisible until sshd -G fills in their defaults. If you paste raw-file text by mistake, the tool tells you and refuses to grade it.

What the verdicts mean

Auth closure — the verdict that matters most. Password login is closed only when passwordauthentication no and kbdinteractiveauthentication no. With usepam yes, password prompts can still arrive through keyboard-interactive even when PasswordAuthentication no, because PAM authentication runs through KbdInteractiveAuthentication and PasswordAuthentication — the man page says so directly, and warns to disable one of the two. The tool states the UsePAM value next to this verdict. authenticationmethods any means any single enabled method is enough; an explicit list means every method in at least one list must complete.

Root login. permitrootlogin no means root cannot log in at all. prohibit-password — printed as without-password in effective output — means root can log in with a key but never with a password or keyboard-interactive auth. forced-commands-only means root key login only when the key carries a command= option, which is the remote-backup shape. yes means root password login is allowed. prohibit-password is the default; it is not "root login enabled".

Public-key auth and empty passwords. pubkeyauthentication yes is the default and the login method the lockout-safe order keeps. If it is no while password auth is also off, no login method is left — the tool flags that as a lockout, not a hardening win. permitemptypasswords yes is a fail on its own; the default is no.

AllowUsers and AllowGroups. If neither appears in the output, login is allowed for all users — that is the default, and the tool says so instead of grading the absence as a gap. Absent allowusers means "default: allow all", because directives with no setting and no default do not appear in sshd -G output at all. When present, the tool lists the patterns. DenyUsers is processed before AllowUsers, and DenyGroups before AllowGroups.

Forwarding. x11forwarding, allowtcpforwarding, allowagentforwarding, allowstreamlocalforwarding, disableforwarding, permittunnel, permitopen, and permitlisten are reported with their values. Disabling a forwarding option does not stop users with shell access from installing their own forwarders — the man page says so for each of them — so a no here is reported, not celebrated as a boundary.

Algorithm lists. ciphers, macs, kexalgorithms, pubkeyacceptedalgorithms, hostkeyalgorithms, and casignaturealgorithms are compared against the default set for the OpenSSH version you picked. An entry that is in neither the 9.6 nor the 10.0 default set is flagged as not-default: the man page lists it as supported, but the server offers an algorithm no default build offers. The lists are printed verbatim alongside the verdict, so you can see exactly what is offered.

Values reported, not graded. maxauthtries (default 6) and logingracetime (default 120 seconds) are reported with their values and their defaults. No "ideal" threshold is claimed for either, because no dated source in hand states one.

Which OpenSSH version the verdicts apply to

The verdicts are version-pinned. The man page the tool is built from is the Debian trixie edition, which describes OpenSSH 10.0: its default key-exchange list starts with mlkem768x25519-sha256, and its Match Version example is OpenSSH_10.0. The box the tool was tested against runs OpenSSH 9.6p1 (Ubuntu 24.04), whose default key-exchange list has no mlkem768x25519-sha256 and still includes diffie-hellman-group14-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, and diffie-hellman-group-exchange-sha256. Pick your version in the tool: the algorithm verdicts use that version's default set. For any other version, the algorithm lists are reported verbatim with no verdict, because the tool holds no default table for that version.

Older editions state different defaults — for example, OpenBSD 5.1/5.3 editions list PermitRootLogin yes where current editions list prohibit-password (reported in search snippets during the 2026-11-04 banking run, not re-verified here). Never grade one version's output against another version's page.

The lockout-safe change order

Every step below was verified on the build box (OpenSSH 9.6p1, Ubuntu 24.04) or against the man pages named in Sources. Do not reorder the steps.

  1. Prove key login works in a new session first, before changing anything. Log in with the key alone, in a second terminal, and confirm you get a shell.
  2. Keep the existing session open. Do not close it until step 6 passes. It is your way back in.
  3. Put the changes in the earliest-sorting drop-in, /etc/ssh/sshd_config.d/00-hardening.conf. On Debian and Ubuntu the main file includes /etc/ssh/sshd_config.d/*.conf at the top, and drop-in files are included at the start of the configuration, so options set there override those in /etc/ssh/sshd_config — the first obtained value wins, and a later 50-cloud-init.conf that sets PasswordAuthentication yes loses to your 00- file. The tool emits only the directives you select, in this file.
  4. Check, then read back the effective values. Run sudo sshd -t (syntax plus keys), then sshd -G (or sudo sshd -T) and confirm the effective values changed. If a value did not change, a drop-in sorts earlier than yours, or a Match block overrides it for your user — fix that before going on.
  5. Reload, do not restart. sudo systemctl reload ssh runs sshd -t and then sends SIGHUP to the daemon, and sshd rereads its configuration file when it receives SIGHUP. A reload applies to new connections; your open session stays up.
  6. Test a new login and the negative cases from a second session. Log in with the key, then confirm a password login is refused and a root login is refused. Only then close the original session.
  7. Rollback is one move. Move the drop-in aside, run sudo sshd -t, reload — from the still-open session or the console.

One wrinkle, verified against the box's unit files: on Ubuntu 24.04 the ssh.socket unit owns the listen socket (ListenStream=0.0.0.0:22 and [::]:22, WantedBy=sockets.target). A Port change therefore needs sudo systemctl daemon-reload plus sudo systemctl restart ssh.socket, not just a reload — the daemon never binds the port itself under socket activation. Auth and forwarding changes need only the reload in step 5.

What the tool cannot see

  • Match blocks, from a bare paste. Bare sshd -G output is global-only. A Match block that reopens password auth for one user is invisible in it. Every verdict from a bare paste is labeled "global section only — Match blocks not evaluated". Paste the -T -C output for the user you care about to grade that user.
  • Where a value was set. Effective output carries no file or line source. The tool never claims "set in /etc/ssh/sshd_config line N". Fixes go in the earliest-sorting drop-in, and step 4 confirms they took effect.
  • Your keys or your users' passwords. The tool reads configuration values, not credentials. It never asks for a key, and no paste leaves the browser.

Frequently asked questions

What does the sshd_config verifier check? It parses the effective configuration printed by sshd -G or sshd -T and grades the values your server actually runs: whether password and keyboard-interactive auth are both off, what root login is allowed to do, whether public-key auth is on, empty passwords, AllowUsers and AllowGroups, forwarding settings, and whether the cipher, MAC, and key-exchange lists match your OpenSSH version's default set.

Why paste sshd -G output instead of the config file? The raw file lies by omission. The first obtained value wins, Include files at the top override the main file, unset directives print with their defaults filled in, and Match blocks change values per user. sshd -G prints the effective values after all of that is resolved, so the verdicts grade what the server runs.

Why does sshd -T fail with "no hostkeys available"? sshd -T includes the -t key check, and the host keys in /etc/ssh are normally readable only by root. Run it with sudo, or use sshd -G, which prints the same effective configuration without checking the keys.

What does "global section only" mean? Bare sshd -G output never evaluates Match blocks. A Match block that reopens password auth for one user is invisible in it. Every verdict from a bare paste is labeled "global section only". Paste a second output from sudo sshd -T -C user=...,host=...,addr=... to grade one user or address.

How do I apply the fixes without locking myself out? Prove key login works in a new session first and keep the old session open. Put the changes in the earliest-sorting drop-in, run sshd -t, then sshd -G to confirm the effective values changed, reload, and test a new login plus the negative cases before closing the original session.

Sources

  • Debian Manpages, sshd_config(5) — openssh-server, trixie — first-obtained-value rule, Include lexical order, Match block rules and the subset of keywords allowed after Match, defaults for PermitRootLogin, PasswordAuthentication, KbdInteractiveAuthentication, PubkeyAuthentication, MaxAuthTries, LoginGraceTime, and Port, the Debian package-standards overrides, the UsePAM keyboard-interactive warning, the forwarding caveats, and the default cipher, MAC, and key-exchange lists.
  • ManKier, sshd(8) — OpenSSH daemon — -T extended test mode versus -G parse-and-print versus -t validity-only, -C connection parameters for per-user Match evaluation, and SIGHUP configuration reread.

Facts verified 2026-11-05 against OpenSSH 9.6p1 (Ubuntu 24.04, sshd -V: OpenSSH_9.6p1 Ubuntu-3ubuntu13.20, OpenSSL 3.0.13) on the build box, with the Debian trixie man page (OpenSSH 10.0) reopened the same day. No Search Console evidence exists for programming or sysadmin content on this site; no demand is claimed for this page.

Keep Exploring

Keep exploring the docs, samples, and free tools to continue your evaluation.