ELK Stack ile Windows Event Log Analizi
Windows ortamlarında log yönetimi, çoğu sysadmin’in “sonra hallederim” listesinin başında gelir. Ta ki bir güvenlik olayı yaşanana veya bir müşteri “geçen hafta ne olmuştu?” diye sorana kadar. Ben de yıllarca Windows Event Log’larını sadece Event Viewer üzerinden takip ettim, sonra bir gün 50 sunucunun loglarını tek tek açmak zorunda kaldım ve o gece ELK Stack kurulumuna başladım. Bu yazıda sıfırdan çalışan bir Windows Event Log analiz altyapısını nasıl kuracağınızı, hangi hataları yapmamanız gerektiğini ve gerçek dünyada bu sistemin nasıl işe yaradığını anlatacağım.
Mimariyi Anlamak
ELK Stack üç bileşenden oluşur: Elasticsearch (veri depolama ve arama), Logstash (veri işleme ve dönüştürme), Kibana (görselleştirme). Windows Event Log’ları için bu üçlüye bir de Winlogbeat ekleniyor. Windows sunucularına Winlogbeat agent’ı kuruyorsunuz, bu agent logları Logstash veya direkt Elasticsearch’e gönderiyor.
Genel mimari şöyle işliyor:
- Windows Sunucuları (Winlogbeat) -> Logstash -> Elasticsearch -> Kibana
Neden direkt Elasticsearch’e değil de Logstash üzerinden gönderiyoruz? Çünkü Logstash’te veri zenginleştirme, filtreleme ve dönüştürme yapabiliyorsunuz. Örneğin Event ID 4625 (başarısız login) geldiğinde bunu otomatik olarak “Failed Login Attempt” etiketiyle işaretleyebiliyorsunuz.
Elasticsearch Kurulumu
Üretim ortamı için single-node kurulum önerilmez ama başlangıç için işe yarar. Ben genellikle minimum 3 node’lu cluster kuruyorum. Şimdilik tek node ile başlayalım:
# Elasticsearch GPG key ve repo ekle
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
sudo apt-get update && sudo apt-get install elasticsearch -y
# Servis başlat
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch
Kurulum sonrası /etc/elasticsearch/elasticsearch.yml dosyasını düzenlemeniz gerekiyor:
# /etc/elasticsearch/elasticsearch.yml temel ayarlar
cluster.name: windows-log-cluster
node.name: elk-node-01
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
discovery.type: single-node
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.enabled: true ile güvenliği açık tutun. Production ortamında TLS olmadan çalıştırmak ciddi bir güvenlik açığıdır.
Logstash Kurulumu ve Pipeline Konfigürasyonu
Logstash kurulumu Elasticsearch’ten sonra gelir çünkü Java bağımlılıklarını paylaşıyorlar:
sudo apt-get install logstash -y
Şimdi kritik kısma geliyoruz: Logstash pipeline konfigürasyonu. Bu dosyayı yanlış yazarsanız loglar ya hiç gelmez ya da anlamsız bir şekilde gelir. /etc/logstash/conf.d/winlogbeat.conf dosyasını oluşturun:
input {
beats {
port => 5044
ssl => true
ssl_certificate => "/etc/logstash/certs/logstash.crt"
ssl_key => "/etc/logstash/certs/logstash.key"
}
}
filter {
if [agent][type] == "winlogbeat" {
# Security logları için özel işleme
if [winlog][channel] == "Security" {
# Başarısız login denemelerini işaretle
if [winlog][event_id] == 4625 {
mutate {
add_tag => ["failed_login"]
add_field => { "event_category" => "authentication_failure" }
}
}
# Başarılı loginleri işaretle
if [winlog][event_id] == 4624 {
mutate {
add_tag => ["successful_login"]
add_field => { "event_category" => "authentication_success" }
}
}
# Hesap kilitleme
if [winlog][event_id] == 4740 {
mutate {
add_tag => ["account_lockout"]
add_field => { "alert_level" => "high" }
}
}
# Yeni servis kurulumu
if [winlog][event_id] == 7045 {
mutate {
add_tag => ["new_service"]
add_field => { "alert_level" => "medium" }
}
}
}
# GeoIP zenginleştirme - kaynak IP varsa
if [winlog][event_data][IpAddress] and [winlog][event_data][IpAddress] != "-" {
geoip {
source => "[winlog][event_data][IpAddress]"
target => "source_geo"
}
}
}
}
output {
elasticsearch {
hosts => ["https://localhost:9200"]
index => "winlogbeat-%{+YYYY.MM.dd}"
user => "elastic"
password => "${ELASTIC_PASSWORD}"
ssl => true
cacert => "/etc/elasticsearch/certs/http_ca.crt"
}
# Yüksek öncelikli alertler için ayrı index
if "account_lockout" in [tags] {
elasticsearch {
hosts => ["https://localhost:9200"]
index => "security-alerts-%{+YYYY.MM.dd}"
user => "elastic"
password => "${ELASTIC_PASSWORD}"
ssl => true
cacert => "/etc/elasticsearch/certs/http_ca.crt"
}
}
}
Logstash’in Elasticsearch şifresine güvenli erişimi için keystore kullanın:
# Logstash keystore oluştur ve şifre ekle
sudo -u logstash /usr/share/logstash/bin/logstash-keystore create
sudo -u logstash /usr/share/logstash/bin/logstash-keystore add ELASTIC_PASSWORD
Winlogbeat Kurulumu (Windows Tarafı)
Windows sunucularında PowerShell ile kurulum yapıyoruz:
# PowerShell ile Winlogbeat indir ve kur
$version = "8.11.0"
$url = "https://artifacts.elastic.co/downloads/beats/winlogbeat/winlogbeat-$version-windows-x86_64.zip"
Invoke-WebRequest -Uri $url -OutFile "C:winlogbeat.zip"
Expand-Archive -Path "C:winlogbeat.zip" -DestinationPath "C:Program Files"
Rename-Item "C:Program Fileswinlogbeat-$version-windows-x86_64" "C:Program FilesWinlogbeat"
# Servis olarak kur
cd "C:Program FilesWinlogbeat"
.install-service-winlogbeat.ps1
C:Program FilesWinlogbeatwinlogbeat.yml konfigürasyon dosyası:
winlogbeat.event_logs:
- name: Application
ignore_older: 72h
- name: System
ignore_older: 72h
- name: Security
ignore_older: 72h
# Kritik event ID'leri filtrele - hepsini göndermek bant genişliği öldürür
event_id: 4624, 4625, 4634, 4647, 4648, 4656, 4672, 4698, 4702, 4720, 4722, 4724, 4725, 4726, 4728, 4732, 4740, 4756, 4768, 4769, 4771, 4776
- name: Microsoft-Windows-PowerShell/Operational
ignore_older: 24h
- name: Microsoft-Windows-Sysmon/Operational
ignore_older: 24h
tags: ["sysmon"]
output.logstash:
hosts: ["elk-server.domain.com:5044"]
ssl.certificate_authorities: ["C:/Program Files/Winlogbeat/certs/ca.crt"]
logging.level: warning
logging.to_files: true
logging.files:
path: C:/ProgramData/winlogbeat/Logs
name: winlogbeat
keepfiles: 7
fields:
environment: production
datacenter: ist-dc01
fields_under_root: true
Dikkat edin, Security kanalı için belirli Event ID’leri filtreledim. Bunu yapmazsanız her oturum açma işleminin onlarca ilgili eventi gelir ve Elasticsearch’iniz gereksiz verilerle dolmaya başlar. 500 kullanıcılı bir AD ortamında günlük Security log trafiği filtresiz 2-3 GB’a ulaşabilir.
Kibana Kurulumu ve Temel Dashboard
sudo apt-get install kibana -y
# /etc/kibana/kibana.yml
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["https://localhost:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.password: "kibana_system_sifreniz"
elasticsearch.ssl.certificateAuthorities: ["/etc/elasticsearch/certs/http_ca.crt"]
elasticsearch.ssl.verificationMode: certificate
Kibana başladıktan sonra Winlogbeat’in hazır dashboard’larını yükleyin. Bu dashboard’lar gerçekten kullanışlı, sıfırdan başlamak zorunda değilsiniz:
# Windows makinede Winlogbeat dashboard'larını yükle
cd "C:Program FilesWinlogbeat"
.winlogbeat.exe setup --dashboards `
-E output.logstash.enabled=false `
-E output.elasticsearch.enabled=true `
-E output.elasticsearch.hosts=["https://elk-server:9200"] `
-E output.elasticsearch.username=elastic `
-E output.elasticsearch.password=SifrenizBurada `
-E output.elasticsearch.ssl.certificate_authorities="C:Program FilesWinlogbeatcertsca.crt"
Gerçek Dünya Senaryosu: Brute Force Tespiti
Bir finans şirketinde çalışırken, RDP üzerinden gelen brute force saldırısını tespit etmemiz gerekiyordu. Logları ELK’e taşıdıktan sonra Kibana’da şu Lucene sorgusuyla anlık görüntü aldık:
# Kibana Discover'da kullanılacak KQL sorgusu
winlog.event_id: 4625 AND winlog.event_data.LogonType: "3" AND @timestamp >= "now-1h"
# Aynı IP'den gelen başarısız deneme sayısını bulmak için Lens aggregation:
# Bucket: winlog.event_data.IpAddress
# Metric: Count
# Filter: event_id = 4625, son 24 saat
# Sıralama: Count DESC
Bu sorgu bize son 1 saatte ağ üzerinden kaç başarısız login denemesi olduğunu gösterdi. 10 dakika içinde tek bir IP’den 847 başarısız deneme geldiğini gördük. Elasticsearch’te bu tip anomalileri yakalamak için şu index pattern’ı da kullanabilirsiniz:
# Elasticsearch API ile direkt sorgulama
curl -X GET "https://localhost:9200/winlogbeat-*/_search"
-H "Content-Type: application/json"
-u elastic:sifreniz
--cacert /etc/elasticsearch/certs/http_ca.crt
-d '{
"size": 0,
"query": {
"bool": {
"must": [
{"term": {"winlog.event_id": 4625}},
{"range": {"@timestamp": {"gte": "now-1h"}}}
]
}
},
"aggs": {
"failed_logins_by_ip": {
"terms": {
"field": "winlog.event_data.IpAddress",
"size": 10,
"order": {"_count": "desc"}
}
}
}
}'
Index Lifecycle Management ile Disk Yönetimi
Burası çok önemli ve genellikle atlanan kısım. ELK kuruyorsunuz, loglar geliyor, birkaç ay sonra diskler dolmuş ve Elasticsearch yavaşlamış oluyor. Index Lifecycle Management (ILM) bu sorunu çözüyor:
# ILM Policy oluştur - Elasticsearch API
curl -X PUT "https://localhost:9200/_ilm/policy/winlogbeat-policy"
-H "Content-Type: application/json"
-u elastic:sifreniz
--cacert /etc/elasticsearch/certs/http_ca.crt
-d '{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_primary_shard_size": "50gb",
"max_age": "7d"
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": {
"number_of_shards": 1
},
"forcemerge": {
"max_num_segments": 1
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"freeze": {}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}'
Bu policy ile: loglar 7 gün hot storage’da kalır, 7-30 gün arası warm’da sıkıştırılmış halde tutulur, 30-90 gün arası cold’da freeze edilir, 90 günden sonra silinir. Kendi ihtiyaçlarınıza göre bu süreleri ayarlayın. Yasal gerekliliklere göre bazı logları 1 yıl veya daha uzun saklamanız gerekebilir.
Güvenlik ve İzin Yönetimi
ELK Stack’te rol bazlı erişim kontrolü (RBAC) kritik öneme sahiptir. SOC analistlerinin Security loglarına erişimi olmalı ama System log’larını düzenleyememeli. Bunu Kibana üzerinden veya API ile yapabilirsiniz:
# SOC analistleri için readonly rol oluştur
curl -X POST "https://localhost:9200/_security/role/soc_analyst"
-H "Content-Type: application/json"
-u elastic:sifreniz
--cacert /etc/elasticsearch/certs/http_ca.crt
-d '{
"indices": [
{
"names": ["winlogbeat-*", "security-alerts-*"],
"privileges": ["read", "view_index_metadata"],
"field_security": {
"grant": ["*"]
}
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": ["read"],
"resources": ["*"]
}
]
}'
# SOC analist kullanıcısı oluştur
curl -X POST "https://localhost:9200/_security/user/soc_user1"
-H "Content-Type: application/json"
-u elastic:sifreniz
--cacert /etc/elasticsearch/certs/http_ca.crt
-d '{
"password": "GucluBirSifre123!",
"roles": ["soc_analyst"],
"full_name": "SOC Analisti 1",
"email": "[email protected]"
}'
Performans Optimizasyonu
Winlogbeat tarafında queue.mem ayarları önemli:
# winlogbeat.yml içine ekleyin
queue.mem:
events: 4096
flush.min_events: 512
flush.timeout: 5s
# Logstash pipeline worker sayısını CPU core'a göre ayarlayın
# /etc/logstash/logstash.yml
pipeline.workers: 4
pipeline.batch.size: 500
pipeline.batch.delay: 50
# Elasticsearch heap size - RAM'in yarısını ver, 32GB'ı geçme
# /etc/elasticsearch/jvm.options.d/heap.options
-Xms8g
-Xmx8g
Elasticsearch heap’ini 32GB’ın üzerine çıkarmayın. JVM’in pointer compression özelliği 32GB üzerinde devre dışı kalır ve performans düşer. 64GB RAM’iniz varsa iki node çalıştırın, her birine 16-20GB verin.
Uyarı Sistemi Kurulumu
Kibana Alerting ile kritik eventler için bildirim kuralları oluşturabilirsiniz. Örneğin 5 dakika içinde 10’dan fazla başarısız login olursa e-posta gönder:
Kibana arayüzünde Stack Management > Rules and Connectors yolunu izleyin. Elasticsearch Query rule tipini seçin:
- Index: winlogbeat-*
- KQL Filter: winlog.event_id: 4625
- Time window: 5 dakika
- Threshold: Count > 10
- Action: E-posta veya Slack notification
Kibana’nın built-in alerting’i temel ihtiyaçlar için yeterli. Daha gelişmiş correlation rules için Elastic SIEM (Elastic Security) modülüne bakabilirsiniz.
Karşılaşılan Yaygın Sorunlar
Winlogbeat logları gelmiyor: İlk kontrol edeceğiniz yer Winlogbeat log dosyası. C:ProgramDatawinlogbeatLogswinlogbeat dosyasına bakın. SSL sertifika sorunları, firewall kuralları (5044 portu) ve Logstash servisinin çalışıp çalışmadığı sıklıkla sorun çıkarır.
Elasticsearch disk doldu: ILM policy yoksa veya yanlış yapılandırılmışsa bu olur. Acil durum için /_cat/indices?v&s=store.size:desc endpoint’iyle en büyük index’leri bulun ve eski olanları silin.
Logstash yavaş işliyor: Pipeline worker sayısını artırın ve batch size’ı optimize edin. Geoip filter CPU yoğun bir işlemdir, zorunlu değilse kapatın.
Kibana’da tarih/saat sorunu: Kibana’nın zaman dilimiyle Winlogbeat’in zaman diliminin uyuşmadığı durumlar olabiliyor. Tüm sistemlerde UTC kullanın, görüntüleme için Kibana’dan timezone ayarı yapın.
Sonuç
ELK Stack ile Windows Event Log analizi ilk kurulumda zahmetli görünüyor ama çalışır hale getirdiğinizde gerçekten vazgeçilmez bir araç oluyor. 50 sunucunun loglarını tek bir ekrandan görmek, brute force saldırılarını dakikalar içinde tespit etmek, hesap kilitlenmelerinin nedenini anında bulmak, bunların hepsi operasyonel verimliliği ciddi ölçüde artırıyor.
Başlarken şunlara dikkat edin: ILM policy’yi en baştan kurun, Event ID filtrelemesini doğru yapın yoksa gereksiz veri trafiğiyle boğulursunuz, güvenliği kapatmayın ve mutlaka TLS kullanın, heap size’ı doğru ayarlayın.
Bu altyapıyı bir kez kurduğunuzda “nasıl bu kadar süre Event Viewer ile idare ettim?” diye soracaksınız. Eski günlere dönmek mümkün olmuyor.
