Skip to content

Read the SSH configuration sshd and ssh really use [10m] - #29

Closed
jpawlowski wants to merge 2 commits into
wintermeyer:mainfrom
jpawlowski:feat/ssh-config
Closed

jpawlowski wants to merge 2 commits into
wintermeyer:mainfrom
jpawlowski:feat/ssh-config

Conversation

@jpawlowski

@jpawlowski jpawlowski commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Symptom: Since OpenSSH 10.4, sshd -T prints PermitRootLogin instead of permitrootlogin, so the audits' grep '^permitrootlogin ' finds nothing and judges sshd settings they never saw. An Include outside sshd_config.d, FreeBSD's /usr/local/etc/ssh and a daemon started with -f are missed too; details in #28.

Change: New rules/ssh-config.md: one sshd probe that carries a -f from the running daemon over, tries sshd -G and falls back to sshd -T, and lists every file read; the ssh -v -G client probe per account that connects out; grep -i on all such output. The security and fleet audits filter case-insensitively, and the security audit reports a server's SSH client. rules/<family>.md name sshd's unit, paths, log and checksum tool. CLAUDE.md points to the rule.

Size: Split out of #14, which now builds on it; independent of #13.

Verified: guard test matrix 551 passed, 0 failed. Probes run against a local OpenSSH 10.3 sshd with an Include outside sshd_config.d and a -f daemon.

An AI agent wrote this text in my name. I know that is problematic.

Part of #27.
Closes #28.

The probes read sshd_config and sshd_config.d/*.conf under /etc/ssh.
Include can pull in any file (macOS reads /etc/ssh/crypto.conf), the
FreeBSD package and appliances use /usr/local/etc/ssh, and a daemon
started with -f reads another file entirely. And since OpenSSH 10.4,
sshd -T and sshd -G print directive names in mixed case
(PermitRootLogin), so a filter like grep '^permitrootlogin ' finds
nothing and the security and fleet audits read an empty config.

New rules/ssh-config.md:
- one sshd probe that takes a -f from the running daemon, tries
  sshd -G (OpenSSH 9.3+, no host keys needed) and falls back to
  sshd -T, and lists every file read (sshd -dd);
- the ssh -v -G client probe, per account that connects out;
- grep -i on every filter over that output.

The security audit's fallback and weak-algorithm check and the fleet
audit's sshd probe use grep -i. The security audit reports a server's
SSH client (StrictHostKeyChecking no, a /dev/null known-hosts file).
rules/<family>.md name sshd's unit, config directory, auth log,
checksum tool and job scheduler per OS. CLAUDE.md points to the rule.

Tested against a local sshd (OpenSSH 10.3) with an Include outside
sshd_config.d and a daemon started with -f. The mixed case of 10.4
is taken from the upstream commit (f6acdce690), not tested.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts:
#	.claude/skills/heinzel-fleet-audit/references/probes.md
#	.claude/skills/heinzel-security/references/ssh.md
@wintermeyer

Copy link
Copy Markdown
Owner

Thanks! The grep -i fix landed in #48 for 2.22.0. Most of the rest was groundwork for the SSH CA work in #14, which I closed, so I'm closing this one too.

An AI agent wrote this text in my name. I know that is problematic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Read the SSH configuration sshd and ssh really use

2 participants