136 lines
3.4 KiB
Markdown
136 lines
3.4 KiB
Markdown
---
|
|
title: SSH Hardening
|
|
description: Practical SSH server hardening guidance for Linux systems in homelab and self-hosted environments
|
|
tags:
|
|
- security
|
|
- ssh
|
|
- linux
|
|
category: security
|
|
created: 2026-03-14
|
|
updated: 2026-03-14
|
|
---
|
|
|
|
# SSH Hardening
|
|
|
|
## Introduction
|
|
|
|
SSH is the primary administrative entry point for many Linux systems. Hardening it reduces the likelihood of credential attacks, accidental privilege exposure, and overly broad remote access.
|
|
|
|
## Purpose
|
|
|
|
This guide focuses on making SSH safer by:
|
|
|
|
- Disabling weak authentication paths
|
|
- Reducing exposure to brute-force attacks
|
|
- Limiting which users can log in
|
|
- Preserving maintainability by relying on modern OpenSSH defaults where possible
|
|
|
|
## Architecture Overview
|
|
|
|
SSH hardening has three layers:
|
|
|
|
- Transport and daemon configuration
|
|
- Network exposure and firewall policy
|
|
- Operational practices such as key handling and logging
|
|
|
|
For most self-hosted systems, the best model is:
|
|
|
|
```text
|
|
Admin workstation -> VPN or trusted network -> SSH server
|
|
```
|
|
|
|
## Step-by-Step Guide
|
|
|
|
### 1. Use key-based authentication
|
|
|
|
Generate a key on the client and copy the public key to the server:
|
|
|
|
```bash
|
|
ssh-keygen -t ed25519 -C "admin@example.com"
|
|
ssh-copy-id admin@server.example
|
|
```
|
|
|
|
### 2. Harden `sshd_config`
|
|
|
|
Baseline example:
|
|
|
|
```text
|
|
PermitRootLogin no
|
|
PasswordAuthentication no
|
|
KbdInteractiveAuthentication no
|
|
PubkeyAuthentication yes
|
|
MaxAuthTries 3
|
|
LoginGraceTime 30
|
|
X11Forwarding no
|
|
AllowTcpForwarding no
|
|
AllowAgentForwarding no
|
|
AllowUsers admin
|
|
```
|
|
|
|
If you need port forwarding for a specific workflow, enable it deliberately instead of leaving it broadly available.
|
|
|
|
### 3. Validate the configuration
|
|
|
|
```bash
|
|
sudo sshd -t
|
|
```
|
|
|
|
### 4. Reload safely
|
|
|
|
Keep an existing SSH session open while reloading:
|
|
|
|
```bash
|
|
sudo systemctl reload sshd
|
|
```
|
|
|
|
Distribution-specific service names may be `ssh` or `sshd`.
|
|
|
|
### 5. Restrict network exposure
|
|
|
|
- Prefer VPN-only or management-VLAN-only access
|
|
- Allow SSH from trusted subnets only
|
|
- Do not expose SSH publicly unless it is necessary and monitored
|
|
|
|
## Configuration Example
|
|
|
|
Example host firewall intent:
|
|
|
|
```text
|
|
Allow TCP 22 from 192.168.10.0/24
|
|
Allow TCP 22 from Tailscale tailnet range
|
|
Deny TCP 22 from all other sources
|
|
```
|
|
|
|
## Troubleshooting Tips
|
|
|
|
### Locked out after config change
|
|
|
|
- Keep the original session open until a new login succeeds
|
|
- Validate the daemon config with `sshd -t`
|
|
- Check the service name and logs with `journalctl -u sshd` or `journalctl -u ssh`
|
|
|
|
### Key authentication fails
|
|
|
|
- Check file permissions on `~/.ssh` and `authorized_keys`
|
|
- Confirm the server allows public key authentication
|
|
- Verify the client is offering the intended key with `ssh -v`
|
|
|
|
### Automation jobs break
|
|
|
|
- Review whether the workload depended on password auth, port forwarding, or agent forwarding
|
|
- Create narrowly scoped exceptions rather than reverting the whole hardening change
|
|
|
|
## Best Practices
|
|
|
|
- Rely on current OpenSSH defaults for ciphers and algorithms unless you have a specific compliance need
|
|
- Disable password-based interactive logins on internet-reachable systems
|
|
- Use individual user accounts and `sudo` instead of direct root SSH
|
|
- Combine SSH hardening with network-level restrictions
|
|
- Review SSH logs regularly on administrative systems
|
|
|
|
## References
|
|
|
|
- [OpenBSD `sshd_config` manual](https://man.openbsd.org/sshd_config)
|
|
- [OpenSSH](https://www.openssh.com/)
|
|
- [Mozilla OpenSSH guidelines](https://infosec.mozilla.org/guidelines/openssh)
|