OpenSSH on Ubuntu: Precise Installation and Hardening
Reliable remote access is fundamental for any Ubuntu production server. For most environments—regardless if it's a private cloud node or a VM provisioned via Terraform—OpenSSH remains the de facto entry point. A misconfigured instance attracts automated scanning, brute force attempts, and sometimes lockout scenarios. Below: practical installation, scrutiny, and baseline hardening for OpenSSH (tested with Ubuntu 22.04 LTS, OpenSSH_8.9p1).
1. Update Your System
First, eliminate package version drift. New package versions include security fixes (for instance, CVE-2023-38408 impacted some earlier OpenSSH releases).
sudo apt update && sudo apt upgrade -y
Check kernel and OpenSSH version if you care about kernel-hardening features:
uname -r
ssh -V
# Expected output: OpenSSH_8.9p1 Ubuntu-3ubuntu0.5, OpenSSL 3.0.2
Note: If a service cannot be restarted post-upgrade, apt
might pause awaiting manual intervention.
2. Install OpenSSH Server
sudo apt install openssh-server=1:8.9p1-3ubuntu0.5 -y
Pin specific versions in controlled environments. This installs /usr/sbin/sshd
, creates /etc/ssh/sshd_config
, and starts the daemon immediately if successful.
3. SSH Service and Health
sudo systemctl status ssh
You want:
Active: active (running) ...
If it’s inactive, try:
sudo systemctl start ssh
sudo journalctl -u ssh | tail -20
Practical example: On cloud VMs, some custom images disable SSH socket activation by default (/lib/systemd/system/ssh.socket
missing or masked).
4. Firewall Considerations (UFW/iptables)
UFW is preinstalled on Ubuntu Server editions, but not always enabled.
sudo ufw allow 22/tcp # Default for SSH
sudo ufw status verbose
Output snippet:
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
If a security group or cloud firewall is upstream (e.g., AWS EC2), check both layers. Don't enable UFW on a remote box without confirming SSH is whitelisted.
5. Local SSH Connection Testing
Basic smoke test, no assumptions:
ssh -v localhost
-v
gives verbose output for troubleshooting. If the connection hangs or you see Connection refused
, inspect /etc/ssh/sshd_config
for typos, check /var/log/auth.log
, or look for port conflicts.
6. Security Hardening: Not Optional
A. Change Default Port
Editing /etc/ssh/sshd_config
:
Port 2222
Restart and update firewall:
sudo systemctl restart ssh
sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcp
Does changing the port stop targeted attacks? Not entirely—port scanners like masscan identify SSH rapidly. Still, lowering log noise is useful.
B. Disable Root Login
PermitRootLogin no
This setting in sshd_config
closes one of the most exploited vectors. Note: On some cloud images, root login via pubkey is enabled by default for first-boot scripts—inspect your image sources.
C. Enforce Key-Based Authentication
- Generate key locally (preferably Ed25519):
ssh-keygen -t ed25519 -C "engineering-team@example.org"
# Ed25519 is faster, uses smaller keys, and is more secure than RSA (for most use cases)
- Deploy public key:
ssh-copy-id user@remote-server
- Lock down authentication options:
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM no
Restart:
sudo systemctl restart ssh
Practical tip: Always keep one session open when testing new sshd_config
changes. Misconfiguration means loss of connectivity—on headless or remote instances, that means out-of-band access or console intervention.
7. Troubleshooting: Real-World Issues
Symptom | Investigation/Remediation |
---|---|
Cannot connect after port change | Ensure new firewall rule exists; test with nmap or telnet . |
sshd won’t start after config edit | sudo sshd -t validates config before restarting. |
Authentication failures | Tail /var/log/auth.log for diagnostics. |
Automated scans fill logs | Use tools like fail2ban to block repeat offenders. |
SSH brute force via cloud provider networks | Review reverse DNS and log patterns, possibly block IP ranges. |
Sample error from misconfigured sshd_config
:
/etc/ssh/sshd_config line 15: Bad configuration option: PermitRootLoggin
8. Beyond Basics: Non-Obvious Hardening
Consider:
- Enabling
AllowUsers
orAllowGroups
to restrict access further. - Setting
LoginGraceTime 20
to reduce window for brute-forcing. - Enforcing minimum key lengths or algorithms via
HostKeyAlgorithms
. - Deploying hardware-backed keys (Yubikey/FIDO2) for admin workflows.
Known issue: Disabling password authentication and PAM can break some automated tooling (e.g., Ansible with default SSH settings); test pipelines accordingly.
Summary
OpenSSH configuration isn’t a set-and-forget task. Each deployment environment carries its own threats and operational quirks. By focusing on explicit versioning, config validation, and layered network controls, the SSH surface can be dramatically reduced.
Most problems arise not from software bugs, but from “it worked last time” habits. Small missteps—like deploying an image with preconfigured, poorly secured keys—often create the largest attack surfaces.
For in-depth audit logging or advanced access controls, integrate with systemd-journald, central SIEM, or two-factor modules (libpam-google-authenticator
). This guide doesn’t cover every advanced method, but these basics form the backbone of resilient Ubuntu server operations.
Note: Always retain console or recovery access before making authentication changes on critical systems.
For further refinement, monitor OpenSSH CVEs regularly, and consider scheduled key rotation and multi-factor authentication for admin endpoints.