Linux : Praktikum Hardening SSH dan Audit Konfigurasi: Difference between revisions
Praktikum pendamping: hardening SSH, audit konfigurasi efektif (sshd -T/-C), dan lima lapis bukti akses ย |
Revisi: sudut audit server warisan + tautan artikel konsep pasangan (Page 761) ย |
||
| (One intermediate revision by the same user not shown) | |||
| Line 1: | Line 1: | ||
Lima lapis hardening SSH sudah dipasang. Port diganti, password dimatikan, Fail2ban berjalan, dan log tampak tenang. Lalu datang pertanyaan yang jarang ditanyakan: '''kapan terakhir kali kamu membuktikan lapis mana yang benar-benar aktif?''' | |||
Artikel ini adalah lab | Artikel ini adalah lab '''audit''', bukan lab pemasangan. Artikel konsep [[Linux : SSH Hardening Lanjutan (Lima Lapis Kunci Akses)]] membangun lima lapis dari nol. Di sini arahnya dibalik: kamu menerima server warisan yang katanya "sudah aman", lalu membuat '''lembar temuan''' yang setiap barisnya punya bukti perintah. | ||
== ๐ฏ Tujuan == | == ๐ฏ Tujuan == | ||
Setelah mengikuti lab ini, kamu bisa: | Setelah mengikuti lab ini, kamu bisa: | ||
* | * Mengaudit konfigurasi SSH yang sudah berjalan tanpa mengubah apa pun lebih dulu. | ||
* Membaca konfigurasi efektif | * Menunjuk '''lapis mana yang menolak''' sebuah login, bukan menebak. | ||
* | * Membaca konfigurasi efektif per user dengan <code>sshd -T -C</code>. | ||
* Menemukan dua jebakan paling sering: '''urutan Include''' dan '''Match yang bertentangan'''. | |||
* | * Menyusun lembar temuan berisi temuan, bukti, risiko, dan tindakan. | ||
* | * Memperbaiki temuan tanpa mengunci diri sendiri di luar server. | ||
== ๐ Konteks nyata == | == ๐ Konteks nyata == | ||
Bayangkan | Bayangkan kamu menerima kunci gedung lab dari admin sebelumnya. Ia bilang: "pintunya sudah diganti nomornya, satpam sudah dipasang, aman." | ||
Tugasmu bukan mempercayai kalimat itu, tetapi berkeliling: mencoba pintu, membaca daftar tamu, mengecek ruang mana yang terbuka, dan menanyakan di mana bukunya. Audit bekerja persis begitu โ '''kecurigaan bukan bukti, dan ingatan bukan catatan'''. | |||
* | * ๐ฅ '''Kasus nyata:''' sebuah SMK memindahkan SSH ke port 2222 dan memasang Fail2ban. Di berkas <code>/etc/ssh/sshd_config</code> tertulis <code>PasswordAuthentication no</code>, dan admin sudah memverifikasinya berkali-kali. Yang tidak dibaca: <code>/etc/ssh/sshd_config.d/50-cloud-init.conf</code> dari image server berisi <code>PasswordAuthentication yes</code>. Karena <code>Include</code> duduk di baris pertama, nilai itu dibaca lebih dulu dan menang. Tujuh bulan kemudian akun <code>operator</code> dengan sandi <code>operator123</code> dipakai bergantian empat orang, dan nilai dua kelas berubah pada suatu malam. | ||
ย | |||
== ๐ง Konsep singkat == | == ๐ง Konsep singkat == | ||
Audit SSH berarti memeriksa lima lapis yang sama seperti artikel konsep, tetapi dengan urutan terbalik: mulai dari bukti, bukan dari niat. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Lapis !! Pertanyaan !! Alat bukti | ! Lapis !! Pertanyaan audit !! Alat bukti | ||
|- | |- | ||
| 1. | | 1. Identitas || Sandi masih diterima? || <code>passwordauthentication</code> efektif | ||
|- | |- | ||
| 2. | | 2. Keanggotaan || Siapa yang dibatasi? || <code>allowusers</code>, <code>allowgroups</code> | ||
|- | |- | ||
| 3. | | 3. Kewenangan || Boleh apa setelah masuk? || <code>permitrootlogin</code>, <code>disableforwarding</code> | ||
|- | |- | ||
| 4. | | 4. Batas || Berapa lama dan berapa kali? || <code>maxauthtries</code>, <code>logingracetime</code> | ||
|- | |- | ||
| 5. | | 5. Bukti || Apa yang tercatat? || <code>loglevel</code>, <code>auth.log</code> | ||
|} | |} | ||
Aturan kerjanya | Aturan kerjanya: '''berhenti di lapis pertama yang gagal'''. Kalau login ditolak karena <code>AllowUsers</code>, jangan menyimpulkan "kuncinya salah" lalu membuat kunci baru. | ||
ย | |||
=== ๐น Tiga perintah yang mirip, artinya beda === | |||
* <code>sshd -t</code> โ hanya memeriksa '''keabsahan''' berkas. Tidak mencetak apa pun kalau sehat. Ini rem darurat sebelum reload. | |||
* <code>sshd -T</code> โ mencetak '''konfigurasi efektif''' setelah semua <code>Include</code> diterapkan. Inilah kebenaran yang dipakai daemon. | |||
* <code>sshd -T -C user=...,addr=...,host=...</code> โ konfigurasi efektif '''untuk satu koneksi tertentu''', termasuk blok <code>Match</code>. | |||
ย | |||
* ๐ก '''Tips:''' jadikan <code>sshd -T</code> sebagai saksi utama. Selama audit, setiap temuan harus bisa dijawab dengan satu baris keluarannya. | |||
=== ๐น Nilai pertama yang menang === | === ๐น Nilai pertama yang menang === | ||
<code>sshd_config(5)</code> | <code>sshd_config(5)</code> menyatakan: untuk setiap kata kunci, '''nilai pertama yang ditemukan itulah yang dipakai'''. Paket Debian dan Ubuntu menaruh <code>Include /etc/ssh/sshd_config.d/*.conf</code> di '''baris paling atas''', sehingga drop-in dibaca lebih dulu dan menimpa berkas utama. | ||
* โ ๏ธ '''Hati-hati:''' "sudah saya matikan di berkas utama" bukan bukti. Bukti adalah baris <code>passwordauthentication no</code> pada keluaran <code>sshd -T</code>. | |||
ย | |||
* โ ๏ธ '''Hati-hati:''' | |||
=== ๐น Satu berkas, dua kebenaran === | === ๐น Satu berkas, dua kebenaran === | ||
<code>Match</code> membuat blok bersyarat | <code>Match</code> membuat blok bersyarat yang '''menimpa''' bagian global untuk user, group, atau alamat tertentu. Satu berkas konfigurasi bisa berarti dua hal berbeda untuk dua orang โ dan hanya <code>-C</code> yang bisa memisahkannya. | ||
ย | |||
ย | |||
== ๐งฉ Istilah penting == | == ๐งฉ Istilah penting == | ||
* '''Konfigurasi efektif''' โ hasil akhir setelah | * '''Konfigurasi efektif''' โ hasil akhir setelah <code>Include</code> dan <code>Match</code> diterapkan; yang benar-benar dibaca <code>sshd</code>. | ||
* ''' | * '''Drop-in''' โ berkas di <code>sshd_config.d/</code>; nomor kecil dibaca lebih dulu, jadi lebih kuat. | ||
* ''' | * '''Socket activation''' โ mode di mana <code>systemd</code> yang memegang port lewat <code>ssh.socket</code>, bukan <code>sshd</code>. | ||
* '''Match block''' โ blok bersyarat berdasarkan <code>User</code>, <code>Group</code>, <code>Address</code>, <code>Host</code>, atau <code>LocalPort</code>. | * '''Match block''' โ blok bersyarat berdasarkan <code>User</code>, <code>Group</code>, <code>Address</code>, <code>Host</code>, atau <code>LocalPort</code>. | ||
* '''prohibit-password''' โ | * '''prohibit-password''' โ root tidak boleh memakai password, tetapi '''masih boleh memakai kunci'''. | ||
* '''StrictModes''' โ | * '''StrictModes''' โ <code>sshd</code> memeriksa pemilik dan izin berkas kunci sebelum login diterima. | ||
* '''MaxAuthTries''' โ batas percobaan autentikasi per koneksi; kegagalan mulai dicatat setelah | * '''MaxAuthTries''' โ batas percobaan autentikasi per koneksi; kegagalan mulai dicatat setelah separuh nilai. | ||
* '''MaxStartups''' โ batas koneksi yang belum terautentikasi, ditulis <code>start:rate:full</code>. | * '''MaxStartups''' โ batas koneksi yang belum terautentikasi, ditulis <code>start:rate:full</code>. | ||
* ''' | * '''DisableForwarding''' โ mematikan semua penerusan port, tunnel, dan agent dalam satu saklar. | ||
* ''' | * '''auth.log''' โ berkas jejak autentikasi di Debian/Ubuntu, biasanya milik <code>syslog:adm</code>. | ||
ย | |||
== ๐ง Praktik: audit server warisan tanpa mengunci diri == | |||
Semua pengujian dilakukan pada '''salinan''' konfigurasi di <code>/tmp/ssh-audit</code> dan instance kedua di port 2222. Layanan asli tidak disentuh sampai kamu yakin. | |||
ย | |||
* โ ๏ธ '''Hati-hati:''' buka '''dua sesi''' sebelum mulai โ satu untuk bekerja, satu dibiarkan terbuka sebagai jalan pulang. Audit yang mengunci diri sendiri bukan audit, itu insiden. | |||
== | === ๐น Langkah 1 โ potret dan simpan sebagai pembanding === | ||
<syntaxhighlight lang="text"> | |||
sudo sshd -T | sort > /tmp/audit-awal.txt | |||
sudo sshd -T | grep -Ei '^(port|permitrootlogin|passwordauthentication|pubkeyauthentication|kbdinteractive|allowusers|allowgroups|maxauthtries|logingracetime|loglevel|disableforwarding)' | |||
ss -tlnp | grep -i ssh | |||
systemctl is-enabled ssh ssh.socket 2>&1 | |||
</syntaxhighlight> | |||
# Catat juga unit yang aktif. Di Ubuntu 24.04, <code>ssh.socket</code> bisa ikut aktif dan memegang port sendiri. | |||
* | * ๐ '''Angka penting:''' saat <code>ssh.socket</code> aktif, <code>systemd</code> yang membuka port. Mengubah <code>Port</code> di <code>sshd_config</code> tidak memindahkan pintu, karena yang mendengarkan bukan <code>sshd</code>. | ||
=== ๐น Langkah | === ๐น Langkah 2 โ petakan berkas yang benar-benar dibaca === | ||
# | # Lihat urutan <code>Include</code> dan isi folder drop-in. Ini peta sumber konflik. | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo grep -n '^Include' /etc/ssh/sshd_config | ||
sudo ls -1 /etc/ssh/sshd_config.d/ 2>/dev/null | |||
sudo - | sudo grep -Hn -Ei 'password|permitrootlogin|allowusers|maxauthtries' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null | ||
sudo - | |||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Bandingkan jumlah baris konfigurasi efektif dengan jumlah baris yang kamu baca. Selisihnya berasal dari bawaan dan drop-in. | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo sshd -T | | sudo sshd -T | wc -l | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* ๐งช '''Uji cepat:''' <code>sudo sshd -T | | * ๐งช '''Uji cepat:''' <code>sudo sshd -T | grep -c .</code> memberi jumlah baris efektif. Kalau kamu baru mengubah satu baris tetapi angka ini tidak berubah, perubahanmu tidak terbaca. | ||
=== ๐น Langkah | === ๐น Langkah 3 โ lapis 1: apakah sandi masih diterima === | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo sshd -T | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|permitemptypasswords)' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Cari akun yang masih punya sandi aktif. Ini daftar calon pintu masuk kalau lapis 1 jebol. | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo passwd -S -a | awk '$2=="P" {print $1, $2}' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Inventaris kunci yang tertanam: siapa pun yang punya baris di sini bisa masuk tanpa sandi. | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo find /home /root -maxdepth 3 -name authorized_keys -printf '%p %TY-%Tm-%Td\n' 2>/dev/null | ||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Hasil yang diharapkan: tiga daftar yang bisa kamu tunjuk โ status sandi, nilai efektif, dan kunci yang ada. | ||
ย | |||
=== ๐น Langkah 4 โ lapis 2: siapa yang dibatasi === | |||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo sshd -T | grep -Ei '^(allowusers|allowgroups|denyusers|denygroups)' || echo "KOSONG: semua akun boleh masuk" | |||
</syntaxhighlight> | </syntaxhighlight> | ||
# Keluaran kosong adalah temuan, bukan hasil netral. Artinya tidak ada daftar tamu sama sekali. | |||
<syntaxhighlight lang="text"> | |||
sudo sshd -T -C user=nobody,addr=192.168.100.10,host=admin-pc | grep -Ei '^(allowusers|allowgroups|passwordauthentication)' | |||
</syntaxhighlight> | |||
# Hasil yang diharapkan: nilai yang sama persis untuk user yang tidak berhak โ bukti bahwa lapis 2 belum bekerja. | |||
=== ๐น Langkah | === ๐น Langkah 5 โ lapis 3: kewenangan setelah masuk === | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo sshd -T | grep -Ei '^(permitrootlogin|disableforwarding|x11forwarding|allowtcpforwarding|permittunnel|allowagentforwarding)' | |||
sudo sshd -T | |||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Periksa pengecualian per user. Inilah tempat <code>Match</code> biasanya menyimpan kejutan. | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
ssh -p 2222 - | sudo sshd -T -C user=guru1,addr=192.168.100.20,host=laptop-guru | grep -Ei '^(forcecommand|chrootdirectory|permittty|allowtcpforwarding|disableforwarding)' | ||
</syntaxhighlight> | |||
# Uji nyata: coba buka tunnel ke port lokal. Kalau <code>DisableForwarding yes</code> bekerja, permintaan ditolak. | |||
<syntaxhighlight lang="text"> | |||
ssh -p 2222 -N -L 8080:127.0.0.1:80 lab@127.0.0.1 | |||
# channel 2: open failed: administratively prohibited: open failed | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=== ๐น Langkah | * ๐ก '''Tips:''' pesan <code>administratively prohibited</code> adalah bukti lapis 3 yang bekerja. Kalau tunnel justru terbuka, temuanmu berbunyi "kewenangan terlalu luas" โ bukan "jaringan bermasalah". | ||
ย | |||
=== ๐น Langkah 6 โ lapis 4: batas percobaan dan waktu === | |||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo sshd -T | grep -Ei '^(maxauthtries|logingracetime|maxstartups|clientaliveinterval)' | ||
sudo command -v fail2ban-client && sudo fail2ban-client status sshd | |||
</syntaxhighlight> | |||
# Baca angkanya, bukan status layanannya. Fail2ban yang aktif tetap tidak menolong kalau <code>MaxAuthTries</code> dibiarkan besar dan sandi masih diterima. | |||
sudo sshd - | ย | ||
sudo | * ๐ '''Angka penting:''' bawaan <code>MaxAuthTries 6</code>, <code>LoginGraceTime 120</code> detik, <code>MaxStartups 10:30:100</code>, <code>ClientAliveInterval 0</code>. Kegagalan autentikasi mulai dicatat setelah mencapai separuh <code>MaxAuthTries</code>. | ||
sudo | ย | ||
=== ๐น Langkah 7 โ lapis 5: bukti yang tersedia === | |||
<syntaxhighlight lang="text"> | |||
sudo sshd -T | grep -i '^loglevel' | |||
ls -l /var/log/auth.log 2>/dev/null | |||
sudo journalctl --disk-usage | |||
sudo lastb -n 5 | |||
</syntaxhighlight> | |||
# Hitung bukti yang benar-benar ada, bukan yang seharusnya ada. | |||
<syntaxhighlight lang="text"> | |||
sudo grep -c 'Accepted publickey' /var/log/auth.log | |||
sudo grep -c 'Failed password' /var/log/auth.log | |||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Hasil yang diharapkan: dua angka. Kalau keduanya nol padahal server menghadap internet, curigai <code>LogLevel</code> atau lokasi log, bukan "tidak ada serangan". | ||
ย | |||
=== ๐น Langkah 8 โ susun lembar temuan === | |||
Inilah keluaran utama audit. Setiap baris harus bisa dipertahankan dengan perintah, bukan pendapat. | |||
ย | |||
{| class="wikitable" | {| class="wikitable" | ||
! | ! Temuan !! Bukti !! Risiko !! Tindakan | ||
|- | |||
| Sandi masih diterima || <code>passwordauthentication yes</code> || tebakan sandi berhasil || matikan, sisakan kunci | |||
|- | |||
| Tanpa daftar tamu || <code>allowusers</code> kosong || akun lama ikut masuk || <code>AllowGroups</code> | |||
|- | |||
| Root boleh dengan kunci || <code>permitrootlogin without-password</code> || kunci lama tak tercabut || <code>no</code> + akun sudo | |||
|- | |- | ||
| yes || | | Forwarding terbuka || <code>allowtcpforwarding yes</code> || server jadi jalan pintas || <code>DisableForwarding yes</code> | ||
|- | |- | ||
| | | <code>Port</code> tidak berlaku || <code>ssh.socket</code> aktif || perubahan port sia-sia || ubah di unit socket | ||
|- | |- | ||
| | | Log minim || <code>loglevel INFO</code> || sidik jari kunci tak tercatat || <code>LogLevel VERBOSE</code> | ||
|} | |} | ||
# | # Beri urutan prioritas: lapis 1 dan 2 dulu, karena keduanya menentukan siapa yang boleh masuk. | ||
=== ๐น Langkah 9 โ dua jebakan yang membatalkan temuanmu === | |||
ย | # '''Jebakan urutan Include.''' Buat salinan konfigurasi di <code>/tmp</code> agar produksi aman, lalu buat dua berkas yang bertentangan. | ||
=== ๐น Langkah | |||
ย | |||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo tee /tmp/ssh- | sudo mkdir -p /tmp/ssh-audit/sshd_config.d | ||
sudo tee /tmp/ssh-audit/sshd_config > /dev/null <<'EOF' | |||
Include /tmp/ssh-audit/sshd_config.d/*.conf | |||
Port 2222 | |||
PidFile /tmp/ssh-audit/sshd.pid | |||
HostKey /etc/ssh/ssh_host_ed25519_key | |||
PasswordAuthentication no | |||
EOF | |||
sudo tee /tmp/ssh-audit/sshd_config.d/99-warisan.conf > /dev/null <<'EOF' | |||
PasswordAuthentication yes | PasswordAuthentication yes | ||
EOF | EOF | ||
sudo sshd -T -f /tmp/ssh- | sudo sshd -T -f /tmp/ssh-audit/sshd_config | grep -i passwordauth | ||
ย | |||
ย | |||
</syntaxhighlight> | </syntaxhighlight> | ||
ย | # Hasil yang diharapkan: <code>passwordauthentication yes</code>. Berkas utama menulis <code>no</code>, tetapi drop-in dibaca lebih dulu. Inilah bentuk persis kegagalan yang tidak terlihat saat membaca berkas utama. | ||
# '''Jebakan Match.''' Tambahkan pengecualian untuk satu user, lalu tanyakan dua kali dengan user berbeda. | |||
# | |||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo tee /tmp/ssh- | sudo tee /tmp/ssh-audit/sshd_config.d/20-pengecualian.conf > /dev/null <<'EOF' | ||
Match User lab | Match User lab | ||
ย ย ย PasswordAuthentication yes | ย ย ย PasswordAuthentication yes | ||
ย ย AllowTcpForwarding yes | |||
EOF | EOF | ||
sudo sshd - | sudo sshd -T -f /tmp/ssh-audit/sshd_config -C user=lab,addr=192.168.100.30,host=pc-lab | grep -Ei 'passwordauth|allowtcpforwarding' | ||
sudo sshd -T -f /tmp/ssh-audit/sshd_config -C user=tamu,addr=192.168.100.30,host=pc-lab | grep -Ei 'passwordauth|allowtcpforwarding' | |||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Hasil yang diharapkan: dua jawaban berbeda untuk berkas yang sama. Audit tanpa <code>-C</code> akan melaporkan satu kebenaran saja. | ||
# '''Konfigurasi rusak.''' Buktikan bahwa rem darurat bekerja sebelum menyentuh layanan asli. | |||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo sh -c 'echo PasswordAuthenticaion no >> /tmp/ssh-audit/sshd_config' | ||
sudo sshd - | sudo sshd -t -f /tmp/ssh-audit/sshd_config; echo "kode keluar: $?" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
# Hasil yang diharapkan: <code> | # Hasil yang diharapkan: <code>Bad configuration option: passwordauthenticaion</code> dan kode keluar bukan nol. | ||
=== ๐น Langkah 10 โ perbaiki, lalu audit ulang === | |||
ย | # Perbaikan ditaruh di drop-in bernomor kecil supaya menang atas berkas bawaan. Nama berkas adalah bagian dari strategi, bukan hiasan. | ||
=== ๐น Langkah | |||
# | |||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo tee /etc/ssh/sshd_config.d/10-hardening.conf > /dev/null <<'EOF' | ||
ssh | PubkeyAuthentication yes | ||
PasswordAuthentication no | |||
KbdInteractiveAuthentication no | |||
ย | PermitEmptyPasswords no | ||
PermitRootLogin no | |||
ย | AllowGroups ssh-users | ||
MaxAuthTries 3 | |||
LoginGraceTime 30 | |||
LogLevel VERBOSE | |||
ssh - | |||
ย | |||
EOF | EOF | ||
sudo sshd -t | sudo sshd -t && echo "konfigurasi sah" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Reload, lalu bandingkan potret lama dengan yang baru. Perbedaan itulah bukti pekerjaanmu. | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo systemctl reload ssh | ||
sudo sshd -T | sort > /tmp/audit-akhir.txt | |||
diff /tmp/audit-awal.txt /tmp/audit-akhir.txt | |||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Verifikasi hasil akhir dengan pertanyaan yang sama seperti awal audit: sandi, daftar tamu, kewenangan, batas, bukti. | ||
ย | |||
ย | |||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo sshd -T | grep -Ei '^(passwordauthentication|permitrootlogin|allowgroups|maxauthtries|loglevel)' | ||
sudo sshd - | sudo sshd -T -C user=tamu,addr=192.168.100.10,host=admin-pc | grep -Ei '^(allowgroups|passwordauthentication)' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
# | # Bersih-bersih bahan audit. | ||
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
sudo | sudo rm -rf /tmp/ssh-audit | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* โ ๏ธ '''Hati-hati:''' <code>systemctl reload ssh</code> pada konfigurasi rusak bisa membuat layanan berhenti dan port tertutup. Selalu <code>sshd -t</code> lebih dulu, dan pastikan sesi kedua masih terbuka. | |||
== ๐ญ Dipakai di dunia kerja == | == ๐ญ Dipakai di dunia kerja == | ||
* '''Sekolah:''' server CBT dan e-rapor | * '''Sekolah:''' server CBT dan e-rapor sering diwarisi dari tahun sebelumnya. Audit lima lapis menghasilkan daftar akun dan kunci yang bisa dicabut sebelum tahun ajaran baru, tanpa menebak siapa masih aktif. | ||
* '''Kantor distributor:''' vendor | * '''Kantor distributor:''' audit dilakukan sebelum akses vendor diperpanjang. Temuan "sandi masih diterima" dan "root boleh dengan kunci" biasanya cukup untuk menolak perpanjangan sampai diperbaiki. | ||
* '''Klinik dan layanan data pribadi:''' | * '''Klinik dan layanan data pribadi:''' auditor eksternal tidak menerima jawaban "sudah kami amankan". Mereka meminta keluaran konfigurasi efektif dan daftar akun yang boleh masuk. | ||
* '''Hosting dan VPS:''' | * '''Hosting dan VPS:''' pemilik layanan perlu tahu apakah image yang dipakai meninggalkan drop-in bawaan yang menimpa hardening mereka. Audit berkas drop-in adalah langkah pertama. | ||
* '''ISP dan warnet:''' perangkat | * '''ISP dan warnet:''' perangkat dikelola dari jarak jauh; audit memastikan tidak ada akun bersama yang masih memakai sandi default setelah pergantian teknisi. | ||
* '''Industri:''' jaringan operasi | * '''Industri:''' perubahan konfigurasi di jaringan operasi harus bisa dipertanggungjawabkan. Lembar temuan bercap waktu lebih berguna daripada ingatan teknisi. | ||
== โ
Verifikasi == | == โ
Verifikasi == | ||
{| class="wikitable" | {| class="wikitable" | ||
! | ! Pemeriksaan !! Perintah !! Bukti lulus | ||
|- | |- | ||
| | | Konfigurasi sah || <code>sshd -t</code> || kode keluar 0, tanpa pesan | ||
|- | |- | ||
| | | Sandi mati || <code>sshd -T</code> || <code>passwordauthentication no</code> | ||
|- | |- | ||
| | | Daftar tamu ada || <code>sshd -T</code> || <code>allowgroups</code> terisi | ||
|- | |- | ||
| | | Root tertutup || <code>sshd -T -C user=root,...</code> || <code>permitrootlogin no</code> | ||
|- | |- | ||
| | | Pengecualian terbatas || <code>-C user=lab</code> vs <code>user=tamu</code> || dua nilai berbeda, sesuai rencana | ||
|- | |- | ||
| | | Tunnel ditolak || <code>ssh -L</code> || <code>administratively prohibited</code> | ||
|- | |- | ||
| | | Batas aktif || <code>sshd -T</code> || <code>maxauthtries 3</code> | ||
|- | |- | ||
| | | Bukti tersedia || <code>grep -c 'Accepted publickey'</code> || angka bukan nol | ||
|- | |- | ||
| | | Port sesuai || <code>ss -tlnp</code> || port yang direncanakan, bukan bawaan | ||
|} | |} | ||
Kalau satu baris gagal, jangan | Kalau satu baris gagal, jangan menutup audit. Tulis sebagai temuan terbuka dengan bukti perintahnya. | ||
== โ ๏ธ Kesalahan umum & troubleshooting == | == โ ๏ธ Kesalahan umum & troubleshooting == | ||
| Line 313: | Line 284: | ||
! Pesan atau gejala !! Artinya !! Tindakan | ! Pesan atau gejala !! Artinya !! Tindakan | ||
|- | |- | ||
| Connection refused || tidak ada daemon di port itu || <code>ss -tlnp</code>, cek <code>Port</code> | | Connection refused || tidak ada daemon di port itu || <code>ss -tlnp</code>, cek unit dan firewall | ||
|- | |||
| Port tidak berubah walau <code>Port</code> diedit || <code>ssh.socket</code> memegang port || ubah <code>ListenStream</code> di unit socket | |||
|- | |- | ||
| Permission denied (publickey) || | | Permission denied (publickey) || kunci tidak cocok atau ditolak lapis 2 || <code>ssh -vvv</code>, cek <code>AllowGroups</code> | ||
|- | |- | ||
| Permission denied (publickey,password) || | | Permission denied (publickey,password) || sandi masih ditawarkan tetapi gagal || cek <code>sshd -T -C</code> | ||
|- | |- | ||
| bad ownership or modes for directory || <code>StrictModes</code> menolak izin home || <code>chmod 750</code>, <code>chown user:user</code> | | bad ownership or modes for directory || <code>StrictModes</code> menolak izin home || <code>chmod 750</code>, <code>chown user:user</code> | ||
|- | |||
| administratively prohibited || forwarding dimatikan || ini hasil yang diharapkan saat audit | |||
|- | |- | ||
| Too many authentication failures || <code>MaxAuthTries</code> habis || pakai <code>-o IdentitiesOnly=yes</code> | | Too many authentication failures || <code>MaxAuthTries</code> habis || pakai <code>-o IdentitiesOnly=yes</code> | ||
|- | |- | ||
| Bad configuration option: ... || salah ketik kata kunci || <code>sshd -t</code> lalu perbaiki | |||
| Bad configuration option: ... || salah ketik kata kunci || <code>sshd -t</code> lalu perbaiki | |||
|- | |- | ||
| | | Log kosong padahal ada percobaan || salah lokasi log atau level rendah || cek <code>LogLevel</code>, <code>rsyslog</code>, journal | ||
|- | |- | ||
| | | Perubahan hilang setelah reboot || drop-in tidak terbaca atau unit menimpa || cek urutan nama berkas dan unit aktif | ||
|} | |} | ||
* ๐ก '''Tips:''' saat men-debug klien, pakai <code>ssh -v</code> (cukup) atau <code>-vvv</code> (detail). Di sisi server, <code>LogLevel VERBOSE</code> mencatat sidik jari kunci tanpa membocorkan isi sesi; kembalikan ke <code>INFO</code> setelah audit selesai. | |||
ย | |||
* ๐ก '''Tips:''' saat men-debug klien, | |||
== ๐ Catatan keamanan & etika == | == ๐ Catatan keamanan & etika == | ||
* ''' | * '''Audit dulu, ubah kemudian.''' Perintah baca tidak mengubah apa pun; setiap perubahan konfigurasi butuh sesi cadangan dan snapshot. | ||
* ''' | * '''Jangan mencetak isi berkas rahasia.''' <code>/etc/shadow</code> dan kunci privat tidak perlu dibaca untuk audit; cukup status dan nama berkasnya. | ||
* ''' | * '''Hasil audit adalah data pribadi.''' Daftar akun, kunci, dan alamat IP adalah informasi sensitif. Simpan di tempat terbatas, jangan di grup chat. | ||
* '''Cabut akses dengan mencabut kunci.''' | * '''<code>LogLevel DEBUG</code> bukan alat permanen.''' Manpage <code>sshd_config(5)</code> menyebut level DEBUG melanggar privasi pengguna. | ||
* '''Cabut akses dengan mencabut kunci.''' Mengganti sandi tidak menyentuh <code>authorized_keys</code> yang sudah tertanam. | |||
* '''Etika:''' audit hanya pada server milik sendiri atau yang kamu diberi izin tertulis. Memindai server orang lain adalah pelanggaran hukum. | |||
* '''Etika:''' | |||
== ๐ Kesimpulan == | == ๐ Kesimpulan == | ||
Audit hardening SSH bukan membaca berkas dengan teliti, tetapi '''menunjuk bukti''': nilai efektif, user yang terkena, dan pesan penolakan yang muncul. | |||
Dua perintah menjadi tulang punggungnya: <code>sshd -T</code> untuk kebenaran umum, dan <code>sshd -T -C</code> untuk kebenaran per user. Selama keduanya belum dijalankan, "sudah diamankan" masih sekadar kalimat. | |||
Langkah berikutnya: ambil satu server | Langkah berikutnya: ambil satu server warisan di labmu, jalankan Langkah 1 sampai 8 tanpa mengubah apa pun, lalu presentasikan lembarnya ke teman satu kelompok untuk diuji balik. | ||
== ๐ Materi terkait == | == ๐ Materi terkait == | ||
* [[Linux : Mengamankan SSH Server dengan Port Custom]] โ | * [[Linux : SSH Hardening Lanjutan (Lima Lapis Kunci Akses)]] โ artikel konsep pasangan lab ini: memasang lima lapis dari nol. | ||
* [[Linux : Mengamankan SSH Server dengan Port Custom]] โ kenapa ganti port bukan hardening. | |||
* [[Linux : Membatasi Percobaan Login SSH dengan Fail2ban]] โ lapis tambahan setelah <code>MaxAuthTries</code>. | * [[Linux : Membatasi Percobaan Login SSH dengan Fail2ban]] โ lapis tambahan setelah <code>MaxAuthTries</code>. | ||
* [[Linux : Praktikum Audit Akun, Group, dan Hak sudo]] โ audit identitas dan kewenangan di sisi sistem. | |||
* [[Mengijinkan User Tertentu Remote SSH]] โ versi ringkas pembatasan user. | * [[Mengijinkan User Tertentu Remote SSH]] โ versi ringkas pembatasan user. | ||
* [[Linux : Log dan journalctl untuk Troubleshooting]] โ membaca jejak ketika log tidak ada di tempat yang diduga. | |||
* [[Linux : | |||
== ๐ Referensi == | == ๐ Referensi == | ||
* Debian Manpages โ [https://manpages.debian.org/bookworm/openssh-server/sshd_config.5.en.html sshd_config(5)], bookworm. | * Debian Manpages โ [https://manpages.debian.org/bookworm/openssh-server/sshd_config.5.en.html sshd_config(5)], bookworm. | ||
* Debian Manpages โ [https://manpages.debian.org/bookworm/openssh-server/sshd.8.en.html sshd(8)], | * Debian Manpages โ [https://manpages.debian.org/bookworm/openssh-server/sshd.8.en.html sshd(8)], opsi <code>-t</code>, <code>-T</code>, dan <code>-C</code>. | ||
* Debian Manpages โ [https://manpages.debian.org/bookworm/openssh-client/ssh.1.en.html ssh(1)] dan [https://manpages.debian.org/bookworm/openssh-client/ssh-keygen.1.en.html ssh-keygen(1)]. | * Debian Manpages โ [https://manpages.debian.org/bookworm/openssh-client/ssh.1.en.html ssh(1)] dan [https://manpages.debian.org/bookworm/openssh-client/ssh-keygen.1.en.html ssh-keygen(1)]. | ||
* Debian Wiki โ [https://wiki.debian.org/SSH SSH]. | * Debian Wiki โ [https://wiki.debian.org/SSH SSH]. | ||
Latest revision as of 18:20, 11 November 2026
Lima lapis hardening SSH sudah dipasang. Port diganti, password dimatikan, Fail2ban berjalan, dan log tampak tenang. Lalu datang pertanyaan yang jarang ditanyakan: kapan terakhir kali kamu membuktikan lapis mana yang benar-benar aktif?
Artikel ini adalah lab audit, bukan lab pemasangan. Artikel konsep Linux : SSH Hardening Lanjutan (Lima Lapis Kunci Akses) membangun lima lapis dari nol. Di sini arahnya dibalik: kamu menerima server warisan yang katanya "sudah aman", lalu membuat lembar temuan yang setiap barisnya punya bukti perintah.
๐ฏ Tujuan
Setelah mengikuti lab ini, kamu bisa:
- Mengaudit konfigurasi SSH yang sudah berjalan tanpa mengubah apa pun lebih dulu.
- Menunjuk lapis mana yang menolak sebuah login, bukan menebak.
- Membaca konfigurasi efektif per user dengan
sshd -T -C. - Menemukan dua jebakan paling sering: urutan Include dan Match yang bertentangan.
- Menyusun lembar temuan berisi temuan, bukti, risiko, dan tindakan.
- Memperbaiki temuan tanpa mengunci diri sendiri di luar server.
๐ Konteks nyata
Bayangkan kamu menerima kunci gedung lab dari admin sebelumnya. Ia bilang: "pintunya sudah diganti nomornya, satpam sudah dipasang, aman."
Tugasmu bukan mempercayai kalimat itu, tetapi berkeliling: mencoba pintu, membaca daftar tamu, mengecek ruang mana yang terbuka, dan menanyakan di mana bukunya. Audit bekerja persis begitu โ kecurigaan bukan bukti, dan ingatan bukan catatan.
- ๐ฅ Kasus nyata: sebuah SMK memindahkan SSH ke port 2222 dan memasang Fail2ban. Di berkas
/etc/ssh/sshd_configtertulisPasswordAuthentication no, dan admin sudah memverifikasinya berkali-kali. Yang tidak dibaca:/etc/ssh/sshd_config.d/50-cloud-init.confdari image server berisiPasswordAuthentication yes. KarenaIncludeduduk di baris pertama, nilai itu dibaca lebih dulu dan menang. Tujuh bulan kemudian akunoperatordengan sandioperator123dipakai bergantian empat orang, dan nilai dua kelas berubah pada suatu malam.
๐ง Konsep singkat
Audit SSH berarti memeriksa lima lapis yang sama seperti artikel konsep, tetapi dengan urutan terbalik: mulai dari bukti, bukan dari niat.
| Lapis | Pertanyaan audit | Alat bukti |
|---|---|---|
| 1. Identitas | Sandi masih diterima? | passwordauthentication efektif
|
| 2. Keanggotaan | Siapa yang dibatasi? | allowusers, allowgroups
|
| 3. Kewenangan | Boleh apa setelah masuk? | permitrootlogin, disableforwarding
|
| 4. Batas | Berapa lama dan berapa kali? | maxauthtries, logingracetime
|
| 5. Bukti | Apa yang tercatat? | loglevel, auth.log
|
Aturan kerjanya: berhenti di lapis pertama yang gagal. Kalau login ditolak karena AllowUsers, jangan menyimpulkan "kuncinya salah" lalu membuat kunci baru.
๐น Tiga perintah yang mirip, artinya beda
sshd -tโ hanya memeriksa keabsahan berkas. Tidak mencetak apa pun kalau sehat. Ini rem darurat sebelum reload.sshd -Tโ mencetak konfigurasi efektif setelah semuaIncludediterapkan. Inilah kebenaran yang dipakai daemon.sshd -T -C user=...,addr=...,host=...โ konfigurasi efektif untuk satu koneksi tertentu, termasuk blokMatch.
- ๐ก Tips: jadikan
sshd -Tsebagai saksi utama. Selama audit, setiap temuan harus bisa dijawab dengan satu baris keluarannya.
๐น Nilai pertama yang menang
sshd_config(5) menyatakan: untuk setiap kata kunci, nilai pertama yang ditemukan itulah yang dipakai. Paket Debian dan Ubuntu menaruh Include /etc/ssh/sshd_config.d/*.conf di baris paling atas, sehingga drop-in dibaca lebih dulu dan menimpa berkas utama.
- โ ๏ธ Hati-hati: "sudah saya matikan di berkas utama" bukan bukti. Bukti adalah baris
passwordauthentication nopada keluaransshd -T.
๐น Satu berkas, dua kebenaran
Match membuat blok bersyarat yang menimpa bagian global untuk user, group, atau alamat tertentu. Satu berkas konfigurasi bisa berarti dua hal berbeda untuk dua orang โ dan hanya -C yang bisa memisahkannya.
๐งฉ Istilah penting
- Konfigurasi efektif โ hasil akhir setelah
IncludedanMatchditerapkan; yang benar-benar dibacasshd. - Drop-in โ berkas di
sshd_config.d/; nomor kecil dibaca lebih dulu, jadi lebih kuat. - Socket activation โ mode di mana
systemdyang memegang port lewatssh.socket, bukansshd. - Match block โ blok bersyarat berdasarkan
User,Group,Address,Host, atauLocalPort. - prohibit-password โ root tidak boleh memakai password, tetapi masih boleh memakai kunci.
- StrictModes โ
sshdmemeriksa pemilik dan izin berkas kunci sebelum login diterima. - MaxAuthTries โ batas percobaan autentikasi per koneksi; kegagalan mulai dicatat setelah separuh nilai.
- MaxStartups โ batas koneksi yang belum terautentikasi, ditulis
start:rate:full. - DisableForwarding โ mematikan semua penerusan port, tunnel, dan agent dalam satu saklar.
- auth.log โ berkas jejak autentikasi di Debian/Ubuntu, biasanya milik
syslog:adm.
๐ง Praktik: audit server warisan tanpa mengunci diri
Semua pengujian dilakukan pada salinan konfigurasi di /tmp/ssh-audit dan instance kedua di port 2222. Layanan asli tidak disentuh sampai kamu yakin.
- โ ๏ธ Hati-hati: buka dua sesi sebelum mulai โ satu untuk bekerja, satu dibiarkan terbuka sebagai jalan pulang. Audit yang mengunci diri sendiri bukan audit, itu insiden.
๐น Langkah 1 โ potret dan simpan sebagai pembanding
sudo sshd -T | sort > /tmp/audit-awal.txt
sudo sshd -T | grep -Ei '^(port|permitrootlogin|passwordauthentication|pubkeyauthentication|kbdinteractive|allowusers|allowgroups|maxauthtries|logingracetime|loglevel|disableforwarding)'
ss -tlnp | grep -i ssh
systemctl is-enabled ssh ssh.socket 2>&1
- Catat juga unit yang aktif. Di Ubuntu 24.04,
ssh.socketbisa ikut aktif dan memegang port sendiri.
- ๐ Angka penting: saat
ssh.socketaktif,systemdyang membuka port. MengubahPortdisshd_configtidak memindahkan pintu, karena yang mendengarkan bukansshd.
๐น Langkah 2 โ petakan berkas yang benar-benar dibaca
- Lihat urutan
Includedan isi folder drop-in. Ini peta sumber konflik.
sudo grep -n '^Include' /etc/ssh/sshd_config
sudo ls -1 /etc/ssh/sshd_config.d/ 2>/dev/null
sudo grep -Hn -Ei 'password|permitrootlogin|allowusers|maxauthtries' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null
- Bandingkan jumlah baris konfigurasi efektif dengan jumlah baris yang kamu baca. Selisihnya berasal dari bawaan dan drop-in.
sudo sshd -T | wc -l
- ๐งช Uji cepat:
sudo sshd -T | grep -c .memberi jumlah baris efektif. Kalau kamu baru mengubah satu baris tetapi angka ini tidak berubah, perubahanmu tidak terbaca.
๐น Langkah 3 โ lapis 1: apakah sandi masih diterima
sudo sshd -T | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|permitemptypasswords)'
- Cari akun yang masih punya sandi aktif. Ini daftar calon pintu masuk kalau lapis 1 jebol.
sudo passwd -S -a | awk '$2=="P" {print $1, $2}'
- Inventaris kunci yang tertanam: siapa pun yang punya baris di sini bisa masuk tanpa sandi.
sudo find /home /root -maxdepth 3 -name authorized_keys -printf '%p %TY-%Tm-%Td\n' 2>/dev/null
- Hasil yang diharapkan: tiga daftar yang bisa kamu tunjuk โ status sandi, nilai efektif, dan kunci yang ada.
๐น Langkah 4 โ lapis 2: siapa yang dibatasi
sudo sshd -T | grep -Ei '^(allowusers|allowgroups|denyusers|denygroups)' || echo "KOSONG: semua akun boleh masuk"
- Keluaran kosong adalah temuan, bukan hasil netral. Artinya tidak ada daftar tamu sama sekali.
sudo sshd -T -C user=nobody,addr=192.168.100.10,host=admin-pc | grep -Ei '^(allowusers|allowgroups|passwordauthentication)'
- Hasil yang diharapkan: nilai yang sama persis untuk user yang tidak berhak โ bukti bahwa lapis 2 belum bekerja.
๐น Langkah 5 โ lapis 3: kewenangan setelah masuk
sudo sshd -T | grep -Ei '^(permitrootlogin|disableforwarding|x11forwarding|allowtcpforwarding|permittunnel|allowagentforwarding)'
- Periksa pengecualian per user. Inilah tempat
Matchbiasanya menyimpan kejutan.
sudo sshd -T -C user=guru1,addr=192.168.100.20,host=laptop-guru | grep -Ei '^(forcecommand|chrootdirectory|permittty|allowtcpforwarding|disableforwarding)'
- Uji nyata: coba buka tunnel ke port lokal. Kalau
DisableForwarding yesbekerja, permintaan ditolak.
ssh -p 2222 -N -L 8080:127.0.0.1:80 lab@127.0.0.1
# channel 2: open failed: administratively prohibited: open failed
- ๐ก Tips: pesan
administratively prohibitedadalah bukti lapis 3 yang bekerja. Kalau tunnel justru terbuka, temuanmu berbunyi "kewenangan terlalu luas" โ bukan "jaringan bermasalah".
๐น Langkah 6 โ lapis 4: batas percobaan dan waktu
sudo sshd -T | grep -Ei '^(maxauthtries|logingracetime|maxstartups|clientaliveinterval)'
sudo command -v fail2ban-client && sudo fail2ban-client status sshd
- Baca angkanya, bukan status layanannya. Fail2ban yang aktif tetap tidak menolong kalau
MaxAuthTriesdibiarkan besar dan sandi masih diterima.
- ๐ Angka penting: bawaan
MaxAuthTries 6,LoginGraceTime 120detik,MaxStartups 10:30:100,ClientAliveInterval 0. Kegagalan autentikasi mulai dicatat setelah mencapai separuhMaxAuthTries.
๐น Langkah 7 โ lapis 5: bukti yang tersedia
sudo sshd -T | grep -i '^loglevel'
ls -l /var/log/auth.log 2>/dev/null
sudo journalctl --disk-usage
sudo lastb -n 5
- Hitung bukti yang benar-benar ada, bukan yang seharusnya ada.
sudo grep -c 'Accepted publickey' /var/log/auth.log
sudo grep -c 'Failed password' /var/log/auth.log
- Hasil yang diharapkan: dua angka. Kalau keduanya nol padahal server menghadap internet, curigai
LogLevelatau lokasi log, bukan "tidak ada serangan".
๐น Langkah 8 โ susun lembar temuan
Inilah keluaran utama audit. Setiap baris harus bisa dipertahankan dengan perintah, bukan pendapat.
| Temuan | Bukti | Risiko | Tindakan |
|---|---|---|---|
| Sandi masih diterima | passwordauthentication yes |
tebakan sandi berhasil | matikan, sisakan kunci |
| Tanpa daftar tamu | allowusers kosong |
akun lama ikut masuk | AllowGroups
|
| Root boleh dengan kunci | permitrootlogin without-password |
kunci lama tak tercabut | no + akun sudo
|
| Forwarding terbuka | allowtcpforwarding yes |
server jadi jalan pintas | DisableForwarding yes
|
Port tidak berlaku |
ssh.socket aktif |
perubahan port sia-sia | ubah di unit socket |
| Log minim | loglevel INFO |
sidik jari kunci tak tercatat | LogLevel VERBOSE
|
- Beri urutan prioritas: lapis 1 dan 2 dulu, karena keduanya menentukan siapa yang boleh masuk.
๐น Langkah 9 โ dua jebakan yang membatalkan temuanmu
- Jebakan urutan Include. Buat salinan konfigurasi di
/tmpagar produksi aman, lalu buat dua berkas yang bertentangan.
sudo mkdir -p /tmp/ssh-audit/sshd_config.d
sudo tee /tmp/ssh-audit/sshd_config > /dev/null <<'EOF'
Include /tmp/ssh-audit/sshd_config.d/*.conf
Port 2222
PidFile /tmp/ssh-audit/sshd.pid
HostKey /etc/ssh/ssh_host_ed25519_key
PasswordAuthentication no
EOF
sudo tee /tmp/ssh-audit/sshd_config.d/99-warisan.conf > /dev/null <<'EOF'
PasswordAuthentication yes
EOF
sudo sshd -T -f /tmp/ssh-audit/sshd_config | grep -i passwordauth
- Hasil yang diharapkan:
passwordauthentication yes. Berkas utama menulisno, tetapi drop-in dibaca lebih dulu. Inilah bentuk persis kegagalan yang tidak terlihat saat membaca berkas utama. - Jebakan Match. Tambahkan pengecualian untuk satu user, lalu tanyakan dua kali dengan user berbeda.
sudo tee /tmp/ssh-audit/sshd_config.d/20-pengecualian.conf > /dev/null <<'EOF'
Match User lab
PasswordAuthentication yes
AllowTcpForwarding yes
EOF
sudo sshd -T -f /tmp/ssh-audit/sshd_config -C user=lab,addr=192.168.100.30,host=pc-lab | grep -Ei 'passwordauth|allowtcpforwarding'
sudo sshd -T -f /tmp/ssh-audit/sshd_config -C user=tamu,addr=192.168.100.30,host=pc-lab | grep -Ei 'passwordauth|allowtcpforwarding'
- Hasil yang diharapkan: dua jawaban berbeda untuk berkas yang sama. Audit tanpa
-Cakan melaporkan satu kebenaran saja. - Konfigurasi rusak. Buktikan bahwa rem darurat bekerja sebelum menyentuh layanan asli.
sudo sh -c 'echo PasswordAuthenticaion no >> /tmp/ssh-audit/sshd_config'
sudo sshd -t -f /tmp/ssh-audit/sshd_config; echo "kode keluar: $?"
- Hasil yang diharapkan:
Bad configuration option: passwordauthenticaiondan kode keluar bukan nol.
๐น Langkah 10 โ perbaiki, lalu audit ulang
- Perbaikan ditaruh di drop-in bernomor kecil supaya menang atas berkas bawaan. Nama berkas adalah bagian dari strategi, bukan hiasan.
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf > /dev/null <<'EOF'
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
PermitRootLogin no
AllowGroups ssh-users
MaxAuthTries 3
LoginGraceTime 30
LogLevel VERBOSE
EOF
sudo sshd -t && echo "konfigurasi sah"
- Reload, lalu bandingkan potret lama dengan yang baru. Perbedaan itulah bukti pekerjaanmu.
sudo systemctl reload ssh
sudo sshd -T | sort > /tmp/audit-akhir.txt
diff /tmp/audit-awal.txt /tmp/audit-akhir.txt
- Verifikasi hasil akhir dengan pertanyaan yang sama seperti awal audit: sandi, daftar tamu, kewenangan, batas, bukti.
sudo sshd -T | grep -Ei '^(passwordauthentication|permitrootlogin|allowgroups|maxauthtries|loglevel)'
sudo sshd -T -C user=tamu,addr=192.168.100.10,host=admin-pc | grep -Ei '^(allowgroups|passwordauthentication)'
- Bersih-bersih bahan audit.
sudo rm -rf /tmp/ssh-audit
- โ ๏ธ Hati-hati:
systemctl reload sshpada konfigurasi rusak bisa membuat layanan berhenti dan port tertutup. Selalusshd -tlebih dulu, dan pastikan sesi kedua masih terbuka.
๐ญ Dipakai di dunia kerja
- Sekolah: server CBT dan e-rapor sering diwarisi dari tahun sebelumnya. Audit lima lapis menghasilkan daftar akun dan kunci yang bisa dicabut sebelum tahun ajaran baru, tanpa menebak siapa masih aktif.
- Kantor distributor: audit dilakukan sebelum akses vendor diperpanjang. Temuan "sandi masih diterima" dan "root boleh dengan kunci" biasanya cukup untuk menolak perpanjangan sampai diperbaiki.
- Klinik dan layanan data pribadi: auditor eksternal tidak menerima jawaban "sudah kami amankan". Mereka meminta keluaran konfigurasi efektif dan daftar akun yang boleh masuk.
- Hosting dan VPS: pemilik layanan perlu tahu apakah image yang dipakai meninggalkan drop-in bawaan yang menimpa hardening mereka. Audit berkas drop-in adalah langkah pertama.
- ISP dan warnet: perangkat dikelola dari jarak jauh; audit memastikan tidak ada akun bersama yang masih memakai sandi default setelah pergantian teknisi.
- Industri: perubahan konfigurasi di jaringan operasi harus bisa dipertanggungjawabkan. Lembar temuan bercap waktu lebih berguna daripada ingatan teknisi.
โ Verifikasi
| Pemeriksaan | Perintah | Bukti lulus |
|---|---|---|
| Konfigurasi sah | sshd -t |
kode keluar 0, tanpa pesan |
| Sandi mati | sshd -T |
passwordauthentication no
|
| Daftar tamu ada | sshd -T |
allowgroups terisi
|
| Root tertutup | sshd -T -C user=root,... |
permitrootlogin no
|
| Pengecualian terbatas | -C user=lab vs user=tamu |
dua nilai berbeda, sesuai rencana |
| Tunnel ditolak | ssh -L |
administratively prohibited
|
| Batas aktif | sshd -T |
maxauthtries 3
|
| Bukti tersedia | grep -c 'Accepted publickey' |
angka bukan nol |
| Port sesuai | ss -tlnp |
port yang direncanakan, bukan bawaan |
Kalau satu baris gagal, jangan menutup audit. Tulis sebagai temuan terbuka dengan bukti perintahnya.
โ ๏ธ Kesalahan umum & troubleshooting
| Pesan atau gejala | Artinya | Tindakan |
|---|---|---|
| Connection refused | tidak ada daemon di port itu | ss -tlnp, cek unit dan firewall
|
Port tidak berubah walau Port diedit |
ssh.socket memegang port |
ubah ListenStream di unit socket
|
| Permission denied (publickey) | kunci tidak cocok atau ditolak lapis 2 | ssh -vvv, cek AllowGroups
|
| Permission denied (publickey,password) | sandi masih ditawarkan tetapi gagal | cek sshd -T -C
|
| bad ownership or modes for directory | StrictModes menolak izin home |
chmod 750, chown user:user
|
| administratively prohibited | forwarding dimatikan | ini hasil yang diharapkan saat audit |
| Too many authentication failures | MaxAuthTries habis |
pakai -o IdentitiesOnly=yes
|
| Bad configuration option: ... | salah ketik kata kunci | sshd -t lalu perbaiki
|
| Log kosong padahal ada percobaan | salah lokasi log atau level rendah | cek LogLevel, rsyslog, journal
|
| Perubahan hilang setelah reboot | drop-in tidak terbaca atau unit menimpa | cek urutan nama berkas dan unit aktif |
- ๐ก Tips: saat men-debug klien, pakai
ssh -v(cukup) atau-vvv(detail). Di sisi server,LogLevel VERBOSEmencatat sidik jari kunci tanpa membocorkan isi sesi; kembalikan keINFOsetelah audit selesai.
๐ Catatan keamanan & etika
- Audit dulu, ubah kemudian. Perintah baca tidak mengubah apa pun; setiap perubahan konfigurasi butuh sesi cadangan dan snapshot.
- Jangan mencetak isi berkas rahasia.
/etc/shadowdan kunci privat tidak perlu dibaca untuk audit; cukup status dan nama berkasnya. - Hasil audit adalah data pribadi. Daftar akun, kunci, dan alamat IP adalah informasi sensitif. Simpan di tempat terbatas, jangan di grup chat.
LogLevel DEBUGbukan alat permanen. Manpagesshd_config(5)menyebut level DEBUG melanggar privasi pengguna.- Cabut akses dengan mencabut kunci. Mengganti sandi tidak menyentuh
authorized_keysyang sudah tertanam. - Etika: audit hanya pada server milik sendiri atau yang kamu diberi izin tertulis. Memindai server orang lain adalah pelanggaran hukum.
๐ Kesimpulan
Audit hardening SSH bukan membaca berkas dengan teliti, tetapi menunjuk bukti: nilai efektif, user yang terkena, dan pesan penolakan yang muncul.
Dua perintah menjadi tulang punggungnya: sshd -T untuk kebenaran umum, dan sshd -T -C untuk kebenaran per user. Selama keduanya belum dijalankan, "sudah diamankan" masih sekadar kalimat.
Langkah berikutnya: ambil satu server warisan di labmu, jalankan Langkah 1 sampai 8 tanpa mengubah apa pun, lalu presentasikan lembarnya ke teman satu kelompok untuk diuji balik.
๐ Materi terkait
- Linux : SSH Hardening Lanjutan (Lima Lapis Kunci Akses) โ artikel konsep pasangan lab ini: memasang lima lapis dari nol.
- Linux : Mengamankan SSH Server dengan Port Custom โ kenapa ganti port bukan hardening.
- Linux : Membatasi Percobaan Login SSH dengan Fail2ban โ lapis tambahan setelah
MaxAuthTries. - Linux : Praktikum Audit Akun, Group, dan Hak sudo โ audit identitas dan kewenangan di sisi sistem.
- Mengijinkan User Tertentu Remote SSH โ versi ringkas pembatasan user.
- Linux : Log dan journalctl untuk Troubleshooting โ membaca jejak ketika log tidak ada di tempat yang diduga.
๐ Referensi
- Debian Manpages โ sshd_config(5), bookworm.
- Debian Manpages โ sshd(8), opsi
-t,-T, dan-C. - Debian Manpages โ ssh(1) dan ssh-keygen(1).
- Debian Wiki โ SSH.
- OpenSSH Project โ manual resmi.