Keamanan

Hardening SSH Server Ubuntu: Panduan Lengkap dari Default ke Production-Ready

Hardening SSH Server Ubuntu: Panduan Lengkap dari Default ke Production-Ready

Tahun 2023, server VPS saya pernah di-brute-force lewat SSH. Saya tidak tahu sampai melihat log /var/log/auth.log dan menemukan lebih dari 14.000 percobaan login dalam 6 jam. Untungnya saya sudah pakai key-based auth, jadi semua percobaan gagal. Tapi pengalaman itu mengubah cara saya memandang SSH security selamanya.

SSH adalah gerbang utama ke server kamu. Jika gerbang ini lemah, semua pertahanan lainnya tidak ada artinya. Artikel ini akan memandu kamu dari pengaturan SSH default (yang berbahaya) ke konfigurasi production-ready yang sudah saya pakai di lebih dari 20 server selama 5 tahun terakhir.

1. Mengapa SSH Default Itu Berbahaya

Out of the box, SSH di Ubuntu sudah cukup aman secara relatif — port 22, password auth aktif, root login diizinkan. Tapi "cukup aman" tidak sama dengan "aman untuk produksi". Berikut risiko dari SSH default:

  • Port 22: Semua bot scanning tahu port ini. Target paling umum untuk brute-force.
  • Password auth: Memungkinkan brute-force attacks. Bot seperti Mirai dan varian baru mencoba ribuan kombinasi password per menit.
  • Root login: Jika attacker berhasil login sebagai root, mereka punya kontrol penuh atas server.
  • No rate limiting: Tidak ada batasan percobaan login dari satu IP.

Statistik dari Shodan menunjukkan ada lebih dari 18 juta SSH server yang exposed ke internet. Dari jumlah itu, sekitar 800.000 masih menggunakan password auth dengan root login aktif. Jangan jadi salah satu dari mereka.

2. Langkah 1: Generate SSH Key (Jika Belum Punya)

Sebelum mengubah apapun di server, pastikan kamu sudah punya SSH key pair. Jika belum, generate di mesin lokal kamu:

ssh-keygen -t ed25519 -C "[email protected]"

Saya rekomendasikan Ed25519 dibanding RSA karena lebih cepat dan lebih aman dengan key size yang lebih kecil. Untuk kompatibilitas lama, kamu bisa pakai RSA 4096:

ssh-keygen -t rsa -b 4096 -C "[email protected]"

Copy public key ke server:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server-kamu

Verifikasi koneksi tanpa password:

ssh -i ~/.ssh/id_ed25519 user@server-kamu "echo 'SSH key works!'"

Penting: Jangan pernah skip verifikasi ini sebelum disable password auth. Jika key tidak berfungsi, kamu akan terkunci dari server.

3. Langkah 2: Edit sshd_config

Buka file konfigurasi SSH server:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo nano /etc/ssh/sshd_config

Selalu backup sebelum edit. Percayalah, saya pernah edit sshd_config tanpa backup dan harus hard reboot VPS dari panel provider untuk recover.

Perubahan yang perlu dilakukan:

# Ganti port dari 22 ke custom (contoh: 2222)
Port 2222

# Disable root login
PermitRootLogin no

# Disable password auth (HANYA setelah key auth verified!)
PasswordAuthentication no
ChallengeResponseAuthentication no

# Disable empty passwords
PermitEmptyPasswords no

# Limit authentication attempts
MaxAuthTries 3

# Idle timeout (disconnect setelah 5 menit idle)
ClientAliveInterval 300
ClientAliveCountMax 2

# Disable X11 forwarding (tidak perlu di server)
X11Forwarding no

# Disable TCP forwarding kecuali diperlukan
AllowTcpForwarding no

# Restrict to specific users
AllowUsers agentadmin deployer

Catatan penting tentang port change: Mengganti port dari 22 ke 2222 bukan security measure yang sebenarnya — ini hanya mengurangi noise dari bot scanning. Tapi pengurangan noise itu sangat berarti. Dari pengalaman saya, mengganti port mengurangi brute-force attempts sekitar 95%.

4. Langkah 3: Install dan Konfigurasi fail2ban

fail2ban adalah sistem intrusion prevention yang memonitor log dan memblokir IP setelah beberapa percobaan login gagal.

sudo apt install fail2ban -y

Buat config custom:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Tambahkan SSH jail:

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600

Penjelasan:

  • maxretry = 3: Setelah 3 percobaan gagal, IP dibanned.
  • bantime = 3600: Ban selama 1 jam (3600 detik).
  • findtime = 600: 3 percobaan gagal dalam 10 menit terakhir.

Restart fail2ban:

sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client status sshd

Dari pengalaman saya, fail2ban di server production biasanya memblokir 50-200 IP per hari. Angka ini cukup konsisten di 4 server yang saya kelola.

5. Langkah 4: Audit Logging

SSH logging default di Ubuntu sudah cukup, tapi saya suka menambahkan detail lebih untuk analisis keamanan. Edit /etc/ssh/sshd_config:

LogLevel VERBOSE

Ini akan log lebih banyak detail termasuk fingerprint key yang digunakan. Untuk log analysis, saya pakai script sederhana:

#!/bin/bash
# /usr/local/bin/ssh-audit.sh
echo "=== Failed SSH Logins (last 24h) ==="
journalctl -u ssh --since "24 hours ago" | grep "Failed password" |   awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20

echo ""
echo "=== Unique IPs with failed logins ==="
journalctl -u ssh --since "24 hours ago" | grep "Failed password" |   grep -oP 'd+.d+.d+.d+' | sort -u | wc -l

echo ""
echo "=== Successful logins ==="
journalctl -u ssh --since "24 hours ago" | grep "Accepted" |   awk '{print $1,$2,$3,$9,$11}'

Jalankan script ini via cron setiap pagi untuk mendapat ringkasan aktivitas SSH.

6. Langkah 5: U2F/FIDO2 Authentication (Opsional tapi Recommended)

Untuk keamanan ekstra, kamu bisa menggunakan hardware security key (YubiKey atau sejenisnya) sebagai second factor. OpenSSH 8.2+ sudah mendukung FIDO2:

ssh-keygen -t ed25519-sk -C "[email protected]"

Ini membutuhkan hardware key yang di-plugin saat login. Lebih aman dari key file biasa karena private key tidak pernah leaving hardware. Tapi ini opsional — untuk kebanyakan use case, key-based auth saja sudah cukup aman.

7. Checklist Hardening Lengkap

LangkahPrioritasDampak
Key-based authWAJIBHilangkan brute-force risk
Disable root loginWAJIBMencegah direct root access
Disable password authWAJIBHilangkan password risk
Custom portREKOMENDASIKurangi noise 95%
fail2banREKOMENDASIAuto-block attacker IPs
AllowUsersREKOMENDASIBatasi akses ke user tertentu
U2F/FIDO2OPSIONALHardware-level security

Penutup

Hardening SSH bukan opsional untuk server production — ini wajib. Dengan mengikuti langkah-langkah di atas, server kamu akan jauh lebih aman dari serangan brute-force dan unauthorized access. Waktu yang kamu investasikan sekitar 30 menit ini bisa mencegah malapetaka di kemudian hari.

Ingat, security itu lapisan (defense in depth). SSH hardening adalah lapisan pertama dan paling penting. Untuk hardening lebih lanjut, baca juga panduan kami tentang container security hardening untuk Docker production environments.

8. Monitoring SSH Attempts Real-time

Selain fail2ban, saya juga menjalankan monitoring real-time untuk SSH attempts. Ini penting untuk deteksi dini jika ada serangan yang lebih sophisticated:

# Monitor SSH attempts real-time
sudo tail -f /var/log/auth.log | grep -i "ssh"

# Cek IP yang paling banyak gagal login
sudo journalctl -u ssh --since "1 hour ago" | grep "Failed password" | awk '{print $11}' | sort | uniq -c | sort -rn

Saya juga buat script Python sederhana untuk analisis log SSH mingguan:

#!/usr/bin/env python3
import subprocess
import json
from collections import Counter

result = subprocess.run(
    ['journalctl', '-u', 'ssh', '--since', '7 days ago', '--no-pager'],
    capture_output=True, text=True
)

failed_ips = []
for line in result.stdout.split('
'):
    if 'Failed password' in line:
        parts = line.split()
        for part in parts:
            if part.count('.') == 3:
                failed_ips.append(part)

ip_counts = Counter(failed_ips).most_common(20)
print("Top 20 attacking IPs (last 7 days):")
for ip, count in ip_counts:
    print(f"  {ip}: {count} attempts")

print(f"
Total unique attacking IPs: {len(set(failed_ips))}")
print(f"Total failed attempts: {len(failed_ips)}")

Script ini saya jalankan via cron setiap minggu. Dari data 7 hari terakhir, biasanya ada 200-500 IP unik yang mencoba login. Dengan fail2ban aktif, semua IP ini sudah di-banned otomatis.

9. Advanced: SSH Certificate Authority

Untuk tim yang lebih dari 3 orang, mengelola authorized_keys satu per satu jadi tidak praktis. SSH Certificate Authority (CA) memungkinkan kamu menandatangani public key dengan CA key, sehingga kamu cukup trust satu CA key di semua server.

Konsep:

  • Buat CA key pair di mesin yang aman (bukan server production)
  • Setiap developer generate keypair sendiri
  • CA menandatangani public key developer → menghasilkan certificate
  • Server hanya perlu trust CA public key → semua certificate yang ditandatangani CA otomatis trusted

Setup ini mengurangi overhead management secara signifikan. Saat developer leave tim, kamu cukup revoke certificate-nya tanpa perlu update authorized_keys di 10 server. Saya pernah pakai setup ini di tim 5 orang yang mengelola 15 server — penghematan waktu yang signifikan.

Tapi untuk developer solo atau tim kecil (< 3 orang), SSH CA overkill. Cukup pakai key-based auth biasa dan manage authorized_keys secara manual.

10. Common Mistakes yang Harus Dihindari

Dari pengalaman saya dan cerita dari komunitas, berikut kesalahan SSH hardening yang paling sering terjadi:

  • Disable password auth tanpa test key auth dulu: Ini yang paling fatal. Saya pernah membantu teman yang terkunci dari VPS karena langsung disable password auth sebelum memastikan key auth berfungsi. Solusi: selalu test key auth di terminal yang BERBEDA sebelum disable password auth.
  • Lupa backup sshd_config: Jika ada typo di sshd_config, SSH bisa tidak bisa start. Tanpa backup, kamu harus hard reboot dari panel provider. Always backup: cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
  • AllowUsers terlalu restrictive: Jika kamu lupa tambahkan user deploy ke AllowUsers, deployment pipeline bisa gagal. Pastikan semua user yang dibutuhkan sudah di-list.
  • Tidak restart sshd setelah perubahan: Perubahan sshd_config tidak langsung aktif. Jalankan sudo systemctl restart sshd (atau ssh -t server "sudo systemctl restart sshd" — tapi hati-hati, jika ada error di config, kamu bisa terkunci).
  • Menggunakan password yang sama untuk SSH dan panel provider: Jika panel provider (DigitalOcean, Vultr) compromised, attacker bisa reset password VPS kamu. Gunakan password berbeda atau bahkan better yet, disable password auth di panel.

Tip final: Jalankan audit SSH secara berkala dengan perintah ini:

# Cek semua pengaturan aktif
sshd -T | grep -E "(permitrootlogin|passwordauthentication|port|maxauthtries)"

# Cek authorized keys semua user
for user in $(cut -d: -f1 /etc/passwd); do
  if [ -f "/home/$user/.ssh/authorized_keys" ]; then
    echo "=== $user ==="
    wc -l < "/home/$user/.ssh/authorized_keys"
  fi
done

Ini memastikan tidak ada user tersembunyi yang punya akses SSH, dan semua pengaturan sudah sesuai hardening checklist.

8. Monitoring SSH Attempts Real-time

Selain fail2ban, saya juga menjalankan monitoring real-time untuk SSH attempts. Ini penting untuk deteksi dini jika ada serangan yang lebih sophisticated:

# Monitor SSH attempts real-time
sudo tail -f /var/log/auth.log | grep -i "ssh"

# Cek IP yang paling banyak gagal login
sudo journalctl -u ssh --since "1 hour ago" | grep "Failed password" | awk '{print $11}' | sort | uniq -c | sort -rn

Saya juga buat script Python sederhana untuk analisis log SSH mingguan:

#!/usr/bin/env python3
import subprocess
import json
from collections import Counter

result = subprocess.run(
    ['journalctl', '-u', 'ssh', '--since', '7 days ago', '--no-pager'],
    capture_output=True, text=True
)

failed_ips = []
for line in result.stdout.split('
'):
    if 'Failed password' in line:
        parts = line.split()
        for part in parts:
            if part.count('.') == 3:
                failed_ips.append(part)

ip_counts = Counter(failed_ips).most_common(20)
print("Top 20 attacking IPs (last 7 days):")
for ip, count in ip_counts:
    print(f"  {ip}: {count} attempts")

print(f"
Total unique attacking IPs: {len(set(failed_ips))}")
print(f"Total failed attempts: {len(failed_ips)}")

Script ini saya jalankan via cron setiap minggu. Dari data 7 hari terakhir, biasanya ada 200-500 IP unik yang mencoba login. Dengan fail2ban aktif, semua IP ini sudah di-banned otomatis.

9. Advanced: SSH Certificate Authority

Untuk tim yang lebih dari 3 orang, mengelola authorized_keys satu per satu jadi tidak praktis. SSH Certificate Authority (CA) memungkinkan kamu menandatangani public key dengan CA key, sehingga kamu cukup trust satu CA key di semua server.

Konsep:

  • Buat CA key pair di mesin yang aman (bukan server production)
  • Setiap developer generate keypair sendiri
  • CA menandatangani public key developer → menghasilkan certificate
  • Server hanya perlu trust CA public key → semua certificate yang ditandatangani CA otomatis trusted

Setup ini mengurangi overhead management secara signifikan. Saat developer leave tim, kamu cukup revoke certificate-nya tanpa perlu update authorized_keys di 10 server. Saya pernah pakai setup ini di tim 5 orang yang mengelola 15 server — penghematan waktu yang signifikan.

Tapi untuk developer solo atau tim kecil (< 3 orang), SSH CA overkill. Cukup pakai key-based auth biasa dan manage authorized_keys secara manual.

10. Common Mistakes yang Harus Dihindari

Dari pengalaman saya dan cerita dari komunitas, berikut kesalahan SSH hardening yang paling sering terjadi:

  • Disable password auth tanpa test key auth dulu: Ini yang paling fatal. Saya pernah membantu teman yang terkunci dari VPS karena langsung disable password auth sebelum memastikan key auth berfungsi. Solusi: selalu test key auth di terminal yang BERBEDA sebelum disable password auth.
  • Lupa backup sshd_config: Jika ada typo di sshd_config, SSH bisa tidak bisa start. Tanpa backup, kamu harus hard reboot dari panel provider. Always backup: cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
  • AllowUsers terlalu restrictive: Jika kamu lupa tambahkan user deploy ke AllowUsers, deployment pipeline bisa gagal. Pastikan semua user yang dibutuhkan sudah di-list.
  • Tidak restart sshd setelah perubahan: Perubahan sshd_config tidak langsung aktif. Jalankan sudo systemctl restart sshd (atau ssh -t server "sudo systemctl restart sshd" — tapi hati-hati, jika ada error di config, kamu bisa terkunci).
  • Menggunakan password yang sama untuk SSH dan panel provider: Jika panel provider (DigitalOcean, Vultr) compromised, attacker bisa reset password VPS kamu. Gunakan password berbeda atau bahkan better yet, disable password auth di panel.

Tip final: Jalankan audit SSH secara berkala dengan perintah ini:

# Cek semua pengaturan aktif
sshd -T | grep -E "(permitrootlogin|passwordauthentication|port|maxauthtries)"

# Cek authorized keys semua user
for user in $(cut -d: -f1 /etc/passwd); do
  if [ -f "/home/$user/.ssh/authorized_keys" ]; then
    echo "=== $user ==="
    wc -l < "/home/$user/.ssh/authorized_keys"
  fi
done

Ini memastikan tidak ada user tersembunyi yang punya akses SSH, dan semua pengaturan sudah sesuai hardening checklist.

💬 Komentar (0)

Belum ada komentar. Jadilah yang pertama! 💬

Komentar akan muncul setelah moderasi.