LFCS 112 ๐ง SSH Server โ Hardening
The previous chapter established the configuration syntax and the lockout risk. This chapter covers the directives that reduce the attack surface after the basic setup is working. Hardening is not a single change but a layered strategy: eliminate the most attractive attack vectors (root login, password authentication), reduce the window for brute force (MaxAuthTries, LoginGraceTime), and close auxiliary services that are enabled by default but rarely needed (X11 forwarding, TCP forwarding, agent forwarding). The LFCS exam tests the recommended values and the reasoning behind each directive. The critical prerequisite remains: key-based authentication must be verified before password authentication is disabled.
Key point: Hardening reduces the attack surface, not the attack likelihood. A hardened server still receives scan traffic. The directives below make the scan traffic less useful to an attacker: no root account to guess, no password to brute force, no forwarding feature to abuse as a tunnel.
Why SSH hardening requires a layered approach
The root login problem. The root account exists on every Linux system and has unlimited privileges. An attacker who compromises root has full control of the machine. PermitRootLogin no forces every administrator to log in as a normal user and escalate with sudo. The attacker must now guess a valid username and a valid key, not just the universal root account . The alternative prohibit-password allows root login with a key but blocks password login. The stricter no is the correct choice for most servers.
The password brute force problem. A password can be guessed. A 4096-bit RSA key cannot. PasswordAuthentication no eliminates the entire class of credential-stuffing and brute-force attacks against SSH. The trade-off is that the key must be installed and working before the directive is applied. The lockout risk is real: a misconfigured key means no access at all .
The authentication attempt problem. Even with keys, an attacker can open connections and try keys. MaxAuthTries 3 limits the number of authentication attempts per connection. After three failures, the connection is terminated. LoginGraceTime 30 limits how long an unauthenticated connection can remain open before the server disconnects it. Both directives reduce the resources an attacker can consume .
The forwarding problem. SSH is not just a shell. It can forward X11 sessions, TCP ports, and SSH agents. X11 forwarding exposes the client’s display server. TCP forwarding can be used to tunnel arbitrary traffic through the server, bypassing firewalls. Agent forwarding exposes the client’s SSH agent to the server, which means a compromised server can use the client’s keys to connect to other hosts. All three are disabled by default in a hardened configuration unless explicitly needed .
The trade-off. Every hardening directive closes a feature. X11 forwarding is useful for remote GUI applications. TCP forwarding is useful for database tunnels. Agent forwarding is useful for bastion hosts. The correct approach is to disable everything and enable only what the specific server requires. A web server does not need X11. A database server does not need TCP forwarding. A bastion host needs agent forwarding, but a production application server does not.
a. The baseline hardening directives
The recommended baseline is a set of directives that can be placed in a drop-in file under /etc/ssh/sshd_config.d/. This preserves the vendor’s base configuration and makes the hardening changes easy to identify and revert .
# /etc/ssh/sshd_config.d/99-hardening.conf
PermitRootLogin no
PermitEmptyPasswords no
IgnoreRhosts yes
HostbasedAuthentication no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
PermitRootLogin no prevents direct root login. PermitEmptyPasswords no blocks accounts with empty passwords. IgnoreRhosts yes and HostbasedAuthentication no disable the legacy host-based trust mechanisms. PubkeyAuthentication yes enables key authentication. PasswordAuthentication no and KbdInteractiveAuthentication no disable password and keyboard-interactive authentication. X11Forwarding no, AllowAgentForwarding no, and AllowTcpForwarding no disable the forwarding features. MaxAuthTries 3 limits authentication attempts. LoginGraceTime 30 limits the unauthenticated connection window. ClientAliveInterval 300 and ClientAliveCountMax 2 disconnect idle sessions after 10 minutes (300 seconds ร 2) .
b. Restricting access by user and source
The AllowUsers directive limits which accounts can authenticate. The AllowGroups directive limits by group membership. Both are more restrictive than the default, which allows any valid account to attempt authentication.
# Only allow specific users
AllowUsers alice bob
# Or restrict to a group
AllowGroups ssh-users
The Match block allows conditional configuration. A common pattern is to allow password authentication for a specific emergency account while disabling it globally.
PasswordAuthentication no
Match User emergency
PasswordAuthentication yes
The Match block must appear at the end of the configuration. Directives before the first Match are global; directives inside a Match apply only when the condition is true .
The PerSourcePenalties option, introduced in OpenSSH 9.8, automatically penalizes client addresses that repeatedly fail authentication. A client that fails three times is blocked for a duration that increases with repeated offenses. The PerSourcePenaltyExemptList option exempts trusted management addresses from the penalties .
c. Validating the hardened configuration
The validation workflow is identical to the previous chapter. sshd -t checks the syntax. sshd -T displays the effective configuration. The service is reloaded with systemctl reload, not restart, to preserve the current session.
# Validate syntax
sudo sshd -t
# Display effective values
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|maxauthtries|x11forwarding'
# Reload (preserves connections)
sudo systemctl reload sshd
The sshd -T output is the authoritative check. A directive in the drop-in file that is overridden by the base configuration or by an earlier drop-in file will not appear as expected. The grep filter shows the actual effective values .
Complete Example Session
# ============================================
# PART 1: BACK UP AND PREPARE
# ============================================
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo mkdir -p /etc/ssh/sshd_config.d
# ============================================
# PART 2: CREATE THE HARDENING OVERRIDE
# ============================================
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf <<'EOF'
PermitRootLogin no
PermitEmptyPasswords no
IgnoreRhosts yes
HostbasedAuthentication no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
EOF
# ============================================
# PART 3: VALIDATE SYNTAX
# ============================================
sudo sshd -t
# No output: syntax is valid.
# ============================================
# PART 4: CHECK EFFECTIVE VALUES
# ============================================
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|maxauthtries|x11forwarding'
# permitrootlogin no
# passwordauthentication no
# maxauthtries 3
# x11forwarding no
# ============================================
# PART 5: RELOAD THE SERVICE
# ============================================
sudo systemctl reload sshd
# ============================================
# PART 6: TEST IN A NEW SESSION
# ============================================
ssh user@server
# Key-based login succeeds.
ssh -o PubkeyAuthentication=no user@server
# Permission denied (publickey).
# ============================================
# PART 7: VERIFY ROOT LOGIN IS BLOCKED
# ============================================
ssh root@server
# Permission denied (publickey).
# ============================================
# PART 8: CHECK FORWARDING IS DISABLED
# ============================================
ssh -X user@server
# X11 forwarding request failed on channel 0.
The eight parts trace the hardening workflow: backup, drop-in creation, syntax validation, effective value check, reload, authentication test, root login test, and forwarding test.
Quick Reference
Baseline Hardening Directives
| Directive | Recommended Value | Purpose |
|---|---|---|
PermitRootLogin | no | Block direct root login |
PermitEmptyPasswords | no | Block empty password accounts |
PasswordAuthentication | no | Disable password login |
KbdInteractiveAuthentication | no | Disable keyboard-interactive |
PubkeyAuthentication | yes | Enable key authentication |
MaxAuthTries | 3 | Limit attempts per connection |
LoginGraceTime | 30 | Limit unauthenticated window |
X11Forwarding | no | Disable X11 forwarding |
AllowAgentForwarding | no | Disable agent forwarding |
AllowTcpForwarding | no | Disable TCP forwarding |
Access Restriction Directives
| Directive | Purpose |
|---|---|
AllowUsers | Limit to specific users |
AllowGroups | Limit to specific groups |
Match User | Conditional configuration |
Validation Commands
| Command | Purpose |
|---|---|
sshd -t | Validate syntax |
sshd -T | Display effective configuration |
systemctl reload sshd | Apply without dropping connections |
Best Practices
โ Do This:
sudo sshd -t
<!-- Validate syntax before reload --> # โ
ssh user@server
<!-- Test key login in a separate session first --> # โ
PermitRootLogin no
<!-- Force sudo escalation --> # โ
โ Don’t Do This:
# Disable password auth before testing key auth
<!-- Locks out the administrator --> # โ
# Enable X11 or TCP forwarding on a web server
<!-- Expands the attack surface unnecessarily --> # โ
# Use PermitRootLogin prohibit-password on a hardened host
<!-- no is stricter and preferred --> # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Locked out after hardening | Password disabled before key tested | Console recovery; re-enable password |
| Directive ignored | Overridden by drop-in file | Check sshd -T |
| X11 forwarding still works | X11Forwarding not set to no | Add to drop-in file |
| MaxAuthTries not enforced | Directive placed after Match block | Place before any Match |
| Root login still possible | PermitRootLogin not applied | Verify with sshd -T |
Real-World Examples
1. Disable Root Login
PermitRootLogin no
2. Disable Password Auth
PasswordAuthentication no
3. Limit Auth Attempts
MaxAuthTries 3
4. Reduce Grace Time
LoginGraceTime 30
5. Disable X11
X11Forwarding no
6. Disable TCP Forwarding
AllowTcpForwarding no
7. Restrict Users
AllowUsers alice bob
8. Emergency Match Block
Match User emergency
PasswordAuthentication yes
9. Validate
sudo sshd -t
10. Check Effective Values
sudo sshd -T | grep passwordauthentication
Visual
Attack Surface Reduction
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Default SSH โ
โ โโโ Root login allowed โ
โ โโโ Password auth allowed โ
โ โโโ X11 forwarding enabled โ
โ โโโ TCP forwarding enabled โ
โ โโโ Unlimited auth attempts โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Hardening
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Hardened SSH โ
โ โโโ Root login: no โ
โ โโโ Password auth: no โ
โ โโโ X11 forwarding: no โ
โ โโโ TCP forwarding: no โ
โ โโโ Max auth tries: 3 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Validation Workflow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Edit sshd_config.d/99-hardening.conf โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ sshd -t (syntax check) โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ sshd -T | grep (effective values) โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ systemctl reload sshd โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Test key login in new session โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Drop-in location | /etc/ssh/sshd_config.d/ |
| Root login | PermitRootLogin no |
| Password auth | PasswordAuthentication no |
| Key auth | PubkeyAuthentication yes |
| Max attempts | MaxAuthTries 3 |
| Grace time | LoginGraceTime 30 |
| X11 forwarding | X11Forwarding no |
| TCP forwarding | AllowTcpForwarding no |
| Agent forwarding | AllowAgentForwarding no |
| Validation | sshd -t then sshd -T |
Key takeaways:
- Hardening is layered. Disable root login, disable password authentication, limit authentication attempts, and close forwarding features. Each layer removes an attack vector .
- The drop-in file is the correct location.
/etc/ssh/sshd_config.d/99-hardening.confpreserves the vendor’s base configuration and makes the hardening changes identifiable and revertible . - Key authentication must be verified before password authentication is disabled. The lockout risk is the primary failure mode. Test in a separate session before applying the change .
sshd -Tis the authoritative check. Drop-in files can override each other. The effective configuration is visible only throughsshd -T.- Forwarding features should be disabled unless required. X11 forwarding, TCP forwarding, and agent forwarding expand the attack surface. A web server does not need them .
Remember: Hardening reduces the attack surface, not the attack volume. The scan traffic continues. The difference is that the scan finds no root account to guess, no password to brute force, and no forwarding feature to abuse. The PermitRootLogin no directive removes the highest-value target. The PasswordAuthentication no directive removes the entire class of credential attacks. The MaxAuthTries 3 directive limits the attempts. The drop-in file contains the changes. The sshd -t validates the syntax. The sshd -T confirms the effective values.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!