Synopsis #
OpenBSD includes OpenSSH in the base system. Its defaults are maintained with the operating system and should not be replaced by copied cipher lists or generic hardening templates. A conservative remote-access setup uses a tested administrator account, public-key authentication, deliberate forwarding policy, Packet Filter exposure, configuration validation, and an independent recovery console.
This guide changes authentication only after a key-based administrator session succeeds. Keep the original session and console access available until a second connection works under the final policy.
For SSH-key-controlled access to a service behind a gateway, see Unlock an Internal Service with an SSH Key .
Establish the Administrator Account #
Complete Create an Administrator Account with doas and SSH Keys first. Verify the account from a separate client session:
ssh -o IdentitiesOnly=yes -o PreferredAuthentications=publickey \
-o PasswordAuthentication=no -o KbdInteractiveAuthentication=no \
-i ~/.ssh/id_ed25519 admin@server.example.com
# Test the intended private key
doas id
# Confirm that the account can perform administrative work
Do not continue if either command fails.
Inspect the Effective Server Configuration #
The server configuration is sshd_config(5)
at /etc/ssh/sshd_config. Many defaults do not appear as active lines in that file. Inspect the effective settings with sshd(8)
:
doas sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|allowtcpforwarding|x11forwarding) '
OpenBSD currently defaults PermitRootLogin to prohibit-password, PasswordAuthentication to yes, and KbdInteractiveAuthentication to yes. The final policy should reflect the host’s actual access requirements rather than assumptions about defaults.
Apply a Minimal Authentication Policy #
After key-based administration has been tested, set the following explicit policy to /etc/ssh/sshd_config:
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
Edit existing global values rather than appending duplicate directives: the first value obtained normally takes effect. Place these global directives before the first Match block, and review any included files and matching overrides. This policy disables all remote root login, password authentication, and keyboard-interactive authentication. It does not affect console login.
Do not add algorithm lists merely to make the configuration look stricter. OpenSSH removes weak defaults and introduces new algorithms through supported system updates. A local list can preserve obsolete choices or prevent future improvements.
Decide Whether Forwarding Is Required #
SSH can forward agents, TCP connections, Unix-domain sockets, X11 connections, and tunnel devices. These features are useful administrative tools, but they should match the host’s role.
For an account that needs only an interactive shell and file transfer, a Match block can restrict forwarding:
Match User admin
DisableForwarding yes
PermitTunnel no
Do not apply this restriction when the account requires port forwarding, agent forwarding, X11 forwarding, or tunnel creation. A Match block continues until another Match or the end of the file, so place global settings above it.
Set PermitTunnel no to disable tunnel creation. Check the settings and test a new connection.
Validate and Reload #
Check the syntax and inspect the effective result before changing the running daemon:
doas sshd -t
# Reject syntax or key-file errors
doas sshd -T -C user=admin,addr=198.51.100.25,host=client.example.com | \
grep -Ei '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|disableforwarding|permittunnel) '
# Confirm the administrator settings, including permittunnel no
doas sshd -T -C user=root,addr=198.51.100.25,host=client.example.com | \
grep -Ei '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication) '
# Confirm that the global root-login policy was not placed inside a Match block
doas rcctl reload sshd
# Apply the validated configuration without ending established sessions
Keep the existing session open. Start another connection with verbose client logging:
ssh -v -o IdentitiesOnly=yes -o PreferredAuthentications=publickey \
-o PasswordAuthentication=no -o KbdInteractiveAuthentication=no \
-i ~/.ssh/id_ed25519 admin@server.example.com
Confirm login and doas again. Only then close the recovery session.
Limit Network Exposure with PF #
If the host uses a default-block pf.conf(5)
policy, allow SSH on the intended interface and address. This example permits TCP port 22 on the address assigned to the egress interface group:
pass in on egress proto tcp to (egress) port ssh
Validate the complete ruleset with pfctl(8) before loading it:
doas pfctl -nf /etc/pf.conf
# Parse the file without changing the active ruleset
doas pfctl -f /etc/pf.conf
# Load the validated ruleset
Restrict the source address when administration always comes from a stable management network. A changed SSH port may reduce log noise, but it is not an authentication control.
Verify Host Identity #
On first connection, verify the server host-key fingerprint through an independent channel. Display fingerprints on the server with ssh-keygen(1) :
doas ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
If a known-hosts warning appears after a legitimate server rebuild, verify the new fingerprint before removing the old entry.
Monitor Authentication #
Follow authentication events in /var/log/authlog:
doas tail -f /var/log/authlog
Use last(1) to review successful sessions:
last
Repeated failed attempts from the Internet are expected on a public SSH service. Strong authentication, supported software, limited accounts, and accurate logs matter more than reactive address lists built from short-lived scans.
Recovery #
If the new session fails, use the still-open session or console to:
- inspect
/var/log/authlog; - run
sshd -t; - inspect the account’s home,
.ssh, andauthorized_keysownership and modes; - compare
sshd -Twith the intended policy; - revert the last configuration change and reload
sshd.
If every administrative credential is lost, use Recover Access and Reset the Root Password . Maintain at least one independent recovery credential. A FIDO-backed key can improve key protection but does not replace that recovery path.