$type=ticker$cols=4

$type=slider$meta=0$snip=0$rm=0

Log Mining Keamanan SSH dengan Polars dan Isolation Forest: Deteksi Anomali Brute Force di Server Linux dan Pemblokiran Otomatis via nftables

Setiap server Linux yang membuka port SSH ke internet menerima ribuan percobaan login gagal per hari. Alat berbasis ambang batas seperti f...

Analis data dan sysadmin menganalisis anomali log SSH server Linux menggunakan Python Polars dan scatter plot Isolation Forest

Setiap server Linux yang membuka port SSH ke internet menerima ribuan percobaan login gagal per hari. Alat berbasis ambang batas seperti fail2ban efektif untuk serangan kasar, misalnya 5 gagal dalam 10 menit. Namun penyerang modern sudah beradaptasi. Mereka melakukan low-and-slow brute force dari botnet terdistribusi, merotasi username, atau menjajal kredensial bocor dengan ritme yang sengaja dibuat di bawah ambang.

Di sinilah data mining berperan. Alih-alih aturan statis, kita membangun profil perilaku per IP dari log autentikasi, lalu membiarkan algoritma unsupervised Isolation Forest menemukan titik yang "tidak biasa" dibandingkan populasi. Untuk pemrosesan data, kita memakai Polars, library DataFrame berbasis Rust dengan eksekusi multi-thread dan lazy query optimizer. Polars mampu memproses jutaan baris log di laptop dalam hitungan detik, jauh lebih cepat dan hemat memori dibanding pandas.

1. Mengapa Isolation Forest?

  • Tanpa label: kita jarang punya dataset "serangan vs. normal" yang bersih. Isolation Forest bekerja tanpa label.
  • Intuisi sederhana: titik anomali lebih mudah diisolasi dengan potongan acak, sehingga kedalaman pohonnya pendek. Skor anomali diturunkan dari rata-rata kedalaman isolasi.
  • Efisien: kompleksitas mendekati linear dan cocok untuk fitur numerik agregat per jendela waktu.

2. Ekstraksi Log Autentikasi dari journald

Pada distribusi berbasis systemd, log SSH tersedia di journal. Gunakan format short-unix agar timestamp berupa epoch yang tidak ambigu (unit bernama ssh di Debian/Ubuntu, sshd di RHEL/Rocky):

# Ekspor 7 hari terakhir log SSH
journalctl -u ssh --since "7 days ago" -o short-unix --no-pager > ssh_7d.log
wc -l ssh_7d.log
head -3 ssh_7d.log
# 1762639141.123456 web01 sshd[2211]: Failed password for invalid user admin from 203.0.113.7 port 50122 ssh2

# Siapkan virtualenv analisis
python3 -m venv ~/logmining && source ~/logmining/bin/activate
pip install polars scikit-learn

3. Parsing dan Feature Engineering dengan Polars

3.1 Parsing Regex Menjadi Kolom Terstruktur

import polars as pl

PAT = (r"^(?P<ts>\d+\.\d+) \S+ sshd\[\d+\]: "
       r"(?P<event>Failed password|Accepted (?:password|publickey)|Invalid user)"
       r"(?: for)?(?: invalid user)? (?P<user>\S+) from (?P<ip>[0-9a-fA-F\.:]+)")

with open("ssh_7d.log", encoding="utf-8", errors="replace") as f:
    lines = f.read().splitlines()

events = (
    pl.DataFrame({"line": lines})
    .with_columns(pl.col("line").str.extract_groups(PAT).alias("m"))
    .unnest("m")
    .drop_nulls("ip")
    .with_columns(
        pl.from_epoch((pl.col("ts").cast(pl.Float64) * 1_000_000).cast(pl.Int64),
                      time_unit="us").alias("ts")
    )
    .drop("line")
    .sort(["ip", "ts"])
)
print(events.group_by("event").len())

3.2 Profil Perilaku per IP per Jendela 10 Menit

group_by_dynamic membuat jendela waktu bergulir per IP. Kita menghitung fitur yang mencerminkan pola brute force: jumlah gagal, rasio username tidak valid, keragaman username, dan keberhasilan login.

features = (
    events.group_by_dynamic("ts", every="10m", group_by="ip")
    .agg(
        attempts=pl.len(),
        fails=(pl.col("event") == "Failed password").sum(),
        invalid=(pl.col("event") == "Invalid user").sum(),
        accepted=pl.col("event").str.starts_with("Accepted").sum(),
        distinct_users=pl.col("user").n_unique(),
    )
    .with_columns(
        invalid_ratio=(pl.col("invalid") / pl.col("attempts")),
        hour=pl.col("ts").dt.hour(),
    )
)
print(features.describe())
CATATAN - Skala Big Data: Untuk log berukuran puluhan GB dari banyak server, ganti pembacaan menjadi pl.scan_csv(...) atau simpan hasil parsing sebagai Parquet lalu gunakan pl.scan_parquet("logs/*.parquet"). Eksekusi lazy membuat Polars hanya membaca kolom yang diperlukan dan memproses data secara streaming.

4. Melatih Isolation Forest dan Menandai Anomali

from sklearn.ensemble import IsolationForest

COLS = ["attempts", "fails", "invalid", "accepted", "distinct_users", "invalid_ratio", "hour"]
X = features.select(COLS).fill_null(0).to_numpy()

model = IsolationForest(n_estimators=300, contamination=0.01, random_state=42)
model.fit(X)

scored = features.with_columns(
    score=pl.Series(model.decision_function(X)),     # makin negatif = makin anomali
    anomaly=pl.Series(model.predict(X) == -1),
)

suspects = (
    scored.filter(pl.col("anomaly") & (pl.col("accepted") == 0) & (pl.col("fails") + pl.col("invalid") >= 10))
    .group_by("ip")
    .agg(windows=pl.len(), total_fail=(pl.col("fails") + pl.col("invalid")).sum(),
         min_score=pl.col("score").min(), users=pl.col("distinct_users").max())
    .sort("min_score")
)
print(suspects.head(20))
suspects.write_csv("ssh_suspects.csv")

Perhatikan filter tambahan accepted == 0. Model hanya mengatakan "tidak biasa", dan perilaku tidak biasa belum tentu jahat. Admin yang login dari lokasi baru pada jam 2 pagi juga anomali. Kombinasi skor anomali dengan aturan domain (tanpa login sukses, minimal 10 kegagalan) menekan false positive secara signifikan.

5. Pemblokiran Otomatis dengan nftables Set

5.1 Siapkan Tabel dan Set dengan Timeout

# /etc/nftables.d/ssh-guard.nft
table inet ssh_guard {
    set blocklist4 {
        type ipv4_addr
        flags timeout
    }
    chain input {
        type filter hook input priority -5; policy accept;
        tcp dport 22 ip saddr @blocklist4 counter drop
    }
}
sudo nft -f /etc/nftables.d/ssh-guard.nft
sudo nft list set inet ssh_guard blocklist4

5.2 Script Pengumpan Blocklist

import ipaddress, subprocess, polars as pl

ALLOWLIST = [ipaddress.ip_network(n) for n in ("10.10.10.0/24", "192.168.12.0/24", "100.64.0.0/10")]

def allowed(ip):
    return any(ip in net for net in ALLOWLIST)

for row in pl.read_csv("ssh_suspects.csv").iter_rows(named=True):
    ip = ipaddress.ip_address(row["ip"])
    if ip.version != 4 or allowed(ip):
        continue
    subprocess.run(["nft", "add", "element", "inet", "ssh_guard", "blocklist4",
                    "{", f"{ip} timeout 24h", "}"], check=True)
    print(f"blocked {ip} score={row['min_score']:.3f} fails={row['total_fail']}")
PERINGATAN - Jangan Mengunci Diri Sendiri: Selalu masukkan subnet manajemen, VPN (Tailscale 100.64.0.0/10/WireGuard), dan IP bastion ke allowlist sebelum mengaktifkan pemblokiran otomatis. Gunakan timeout agar blokir kedaluwarsa sendiri, uji dulu dalam mode dry-run (cukup cetak IP), dan pastikan akses konsol out-of-band (Proxmox noVNC/IPMI) tersedia jika terjadi salah blokir.

6. Otomatisasi Berkala dengan systemd Timer

# /etc/systemd/system/ssh-anomaly.service
[Unit]
Description=SSH log mining & anomaly blocklist

[Service]
Type=oneshot
WorkingDirectory=/opt/ssh-anomaly
ExecStart=/bin/sh -c 'journalctl -u ssh --since "7 days ago" -o short-unix --no-pager > ssh_7d.log && /root/logmining/bin/python detect.py && /root/logmining/bin/python block.py'

# /etc/systemd/system/ssh-anomaly.timer
[Timer]
OnCalendar=*:0/15
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now ssh-anomaly.timer
systemctl list-timers ssh-anomaly.timer

7. Pengembangan Lanjutan

  • Skala fleet: kirim log dari seluruh server ke Redpanda/ClickHouse, lalu jalankan feature engineering langsung di SQL dan latih model dari hasil query.
  • Fitur tambahan: ASN/negara (GeoIP), entropi username, interval antar-percobaan (bot cenderung periodik), dan korelasi dengan log web.
  • Evaluasi model: bandingkan hasil dengan blocklist publik (AbuseIPDB, CrowdSec CTI) untuk mengestimasi presisi, dan latih ulang secara berkala karena pola serangan berubah (concept drift).
  • Hardening dasar tetap nomor satu: nonaktifkan PasswordAuthentication, gunakan kunci/sertifikat SSH atau akses Zero Trust. Deteksi anomali adalah lapisan pertahanan tambahan, bukan pengganti.

Kesimpulan

Dengan Polars untuk parsing dan agregasi berkecepatan tinggi serta Isolation Forest untuk deteksi tanpa label, log autentikasi yang biasanya hanya ditumpuk berubah menjadi sinyal keamanan yang bisa ditindaklanjuti. Pendekatan ini menangkap pola brute force yang lolos dari aturan ambang statis. Selama dipadukan dengan allowlist, timeout, dan hardening dasar, pemblokiran otomatis tetap aman dioperasikan di server produksi.

COMMENTS

Name

1clickInstall,1,404,1,Access Management,1,android,1,Ansible,1,Apache Iceberg,1,Apache2,1,API Telegram,1,Apple,3,Automation,1,AWS,1,Backup,2,bapak internet indonesia,1,Big Data,2,blkid,1,booting,1,BorgBackup,1,brainware,1,calc,1,can't mount,3,can't read superblock,1,cara mengatasi disk failure,1,cara mengatasi disk penuh,1,cara mengatasi error disk,1,cara mengatasi error proxmox,1,cara mengatasi log full,1,centOS,1,Ceph,1,certificate,1,Chrome,1,Cilium,1,cinta sang penguasa,1,CLI,1,ClickHouse,1,Cloud,4,Cloud Computing,10,Cloud Native,1,Cloud Storage,6,Clustering,1,Codec,1,CodeIgniter,2,computare,4,computer,4,Container,1,Cybersecurity,12,dakwah,16,Data Engineering,2,Data Mining,2,dd,1,Debian,2,Deepin Linux,1,DevOps,8,DevSecOps,1,digital,1,Docker,12,dosa,1,dosa besar,1,eBPF,1,Enkripsi,1,era digital,1,error certificate,1,error path,1,error subscription,1,excel,1,failed subscription,1,Fedora,1,fedora26,1,Feeder,1,Firewall,1,fstab,1,ftp server,1,fujitsu,1,gambar,1,ghibah,1,Git,2,GitHub,2,gitignore,1,gitignore not work,1,Google,2,Google Chrome,1,Google Cloud,1,Google Drive,2,google-drive-ocamlfuse,1,Harbor,1,Harddisk,1,Hardware,1,Hashing,1,HCI,1,HDD,2,history,1,Homelab,1,host,1,Hostname,1,how to,2,IaC,1,IAM,1,igmp proxy,1,Ilmu Komputer,1,impress,1,indihome,1,INDUKSI MATEMATIKA,1,instalasi,3,install,10,install GIT,1,install linux,6,internet,2,islam,17,javascript,1,K-Means,1,K3s,1,Kafka,1,KDE Plasma,1,keamanan,1,Keamanan Cloud,2,keamanan data,1,Keamanan Jaringan,1,keynote,1,kodi,1,komputer,5,Kubernetes,3,kuliah,1,Lakehouse,1,Latte-dock,1,leap,7,leap 42.3,1,LibreOffice,1,Linux,63,linux ringan,3,Machine Learning,2,machintos,4,macOS,5,mageia,1,mandriva,1,mate,1,microsoft office,2,microsoft windows,4,microsoft word,1,Mikrotik,3,mint,1,Monitoring,1,mount,4,mounting,1,Multimedia Codec,1,Netwatch,1,network,1,network security,1,Networking,11,Nextcloud,1,Nginx,1,node js,1,NTFS,3,ntfsfix,2,numbers,1,office,5,Online Account,1,onno,1,onnowpurbo,1,Open Source,3,OpenMandriva,1,OpenOffice,2,openoffice calc,1,openoffice writer,1,openSUSE,11,operating system,1,OPNsense,1,ownCloud,1,ownCloud Client,1,PAGES,1,PDDikti,1,pemikir islam,1,pengguna,1,perangkat keras,1,Perangkat Lunak,2,PHP,1,PHP 5,1,PKI,1,Polars,1,port 80,1,port 8082,1,postel sevice award,1,Powerpoint,1,presentasi,1,presentation,1,Privacy,1,Proxmox,16,PVE,1,Python,1,q4os,1,Redpanda,1,remaja islam,2,review,7,rezeki,1,s1300i,1,scanner,1,scansnap,1,Security,12,sejarah,1,Server,22,setting,1,Sistem Operasi,2,Software,2,spreadsheet,1,SSH,2,SSO,1,stb,1,Storage,8,sukses dunia akhirat,1,Sysadmin,18,Tailscale,1,Telegram,1,Teleport,1,telkom,1,tesseract,1,text,1,Trino,1,Tutorial,31,tv box,1,Ubuntu,3,Unsupervised Learning,1,usb drive,1,useetv,1,user,1,VBA,1,version control,1,virtual machine,2,Virtualization,4,Visual basic,1,Visual Basic for Applications,1,VLC,2,VLC Media Player,1,VPN,1,vsftpd,1,Wazuh,1,whatsapp api,1,winbox,1,Windows,7,Windows 7,1,word,1,WORD PROCESSOR,2,workstation,1,WPS Office,1,Zero Trust,1,zypper,1,
ltr
item
zhato TECH: Log Mining Keamanan SSH dengan Polars dan Isolation Forest: Deteksi Anomali Brute Force di Server Linux dan Pemblokiran Otomatis via nftables
Log Mining Keamanan SSH dengan Polars dan Isolation Forest: Deteksi Anomali Brute Force di Server Linux dan Pemblokiran Otomatis via nftables
zhato TECH
http://www.zhato-tech.id/2026/11/log-mining-keamanan-ssh-dengan-polars.html
http://www.zhato-tech.id/
http://www.zhato-tech.id/
http://www.zhato-tech.id/2026/11/log-mining-keamanan-ssh-dengan-polars.html
true
740282316614930842
UTF-8
Loaded All Posts Not found any posts VIEW ALL Readmore Reply Cancel reply Delete By Home PAGES POSTS View All RECOMMENDED FOR YOU LABEL ARCHIVE SEARCH ALL POSTS Not found any post match with your request Back Home Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sun Mon Tue Wed Thu Fri Sat January February March April May June July August September October November December Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec just now 1 minute ago $$1$$ minutes ago 1 hour ago $$1$$ hours ago Yesterday $$1$$ days ago $$1$$ weeks ago more than 5 weeks ago Followers Follow THIS PREMIUM CONTENT IS LOCKED STEP 1: Share to a social network STEP 2: Click the link on your social network Copy All Code Select All Code All codes were copied to your clipboard Can not copy the codes / texts, please press [CTRL]+[C] (or CMD+C with Mac) to copy Table of Content