FUTIA
GÜVENLIK9 dk okuma

Linux Dosya Bütünlüğü İzleme: Bash + Telegram Uyarı Sistemi

Sunucunuzda değişen dosyaları 5 dakikada fark edin. Bash scripti, inotify ve Telegram bot ile gerçek zamanlı güvenlik izleme yapısı kurdum.

Linux Dosya Bütünlüğü İzleme: Bash + Telegram Uyarı Sistemi
Miraç Eroğlu
22 Nisan 2026

Geçen ay kamupersonelhaber.com sunucusunda bir config dosyası sessizce değiştirilmiş, 3 gün sonra fark ettim. O an anladım ki manuel log kontrolü işe yaramıyor. Sunucunuzda kritik dosyalar değiştiğinde 30 saniye içinde Telegram'dan bildirim almak ister miydiniz? Ben bu sistemi 2 saatte kurdum, şimdi tüm FUTIA projelerinde çalışıyor.

Bu yazıda sıfırdan bir dosya bütünlüğü izleme sistemi kuracağız. Hiçbir 3. parti araç yüklemeden, sadece bash, inotify-tools ve Telegram bot API kullanarak. Sistem şu işleri yapacak: /etc/nginx/, wp-config.php, .env gibi kritik dosyaları izleyecek, herhangi bir değişiklikte size Telegram mesajı atacak, hangi dosyanın ne zaman değiştiğini loglamak için JSON kayıt tutacak. Hazır scriptleri kopyala-yapıştır değil, mantığını anlayıp kendi ihtiyacınıza göre uyarlayabileceğiniz bir yapı göstereceğim.

Dosya bütünlüğü izleme neden önemli

Çoğu güvenlik ihlali sessizce başlar. Bir backdoor eklenir, bir config satırı değişir, bir cron job enjekte edilir. Siz fark edene kadar saldırgan sistemde günlerce dolaşmış olabilir. Ben bunu doktorbul.com'da yaşadım: bir WordPress eklentisi güncellendi, içinde gizli bir eval() fonksiyonu vardı. 5 gün boyunca sunucuda spam mail gönderdi, hosting provider bizi blacklist'e aldı.

Klasik yaklaşım şöyle: haftada bir logları gözden geçir, şüpheli bir şey varsa araştır. Ama bu reaktif bir yöntem. Dosya bütünlüğü izleme proaktif: değişiklik anında harekete geçiyorsunuz. Tripwire, AIDE, Samhain gibi enterprise araçlar var ama bunlar 300 sayfalık dokümantasyon, karmaşık config dosyaları demek. Küçük bir proje için overkill.

Bash scripti yeterli çünkü:

  • inotify kernel seviyesinde çalışır, CPU tüketimi minimal
  • Telegram bot API 5 satır curl komutu
  • Systemd service olarak çalıştırınca daemonize oluyor
  • Tek dosya, kolayca versiyonlanabilir

Ben FUTIA projelerinde şu dosyaları izliyorum: /etc/nginx/sites-available/, /var/www/html/.env, /home/deploy/.ssh/authorized_keys, /etc/crontab. Bir kere kuruyorsunuz, sonra unutuyorsunuz. Ama bir değişiklik olduğunda telefona bildirim düşüyor.

Telegram bot oluşturma ve token alma

İlk adım Telegram bot kurmak. BotFather ile 2 dakikada halledersiniz. Telegram'da @BotFather'ı arayın, /newbot yazın. Bot ismi verin, benzersiz bir kullanıcı adı seçin. Size bir token verecek, şuna benzer: 6234567890:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw. Bu token'ı güvenli bir yere kaydedin, asla public repo'ya koymayın.

Şimdi chat ID'nizi bulmanız lazım. Bot'unuza bir mesaj gönderin, sonra şu URL'yi tarayıcıda açın:

https://api.telegram.org/bot6234567890:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw/getUpdates

JSON response içinde "chat":{"id":123456789} göreceksiniz. Bu sizin chat ID'niz. Bot token ve chat ID ile artık herhangi bir yerden Telegram'a mesaj gönderebilirsiniz.

Ben FUTIA projelerinde her sunucu için ayrı bot kullanıyorum. Böylece hangi sunucudan bildirim geldiğini anında anlıyorum. Mesela doktorbul-monitor, diolivo-watcher gibi. Alternatif olarak tek bot, farklı chat ID'ler de kullanabilirsiniz (grup veya kanal).

Test için şu komutu çalıştırın:

curl -s -X POST https://api.telegram.org/bot6234567890:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw/sendMessage -d chat_id=123456789 -d text="Test mesajı"

Telefona bildirim geldiyse hazırsınız. Gelmezse token veya chat ID yanlış demektir. getUpdates çıktısını tekrar kontrol edin.

inotify-tools kurulumu ve temel kullanım

inotify Linux kernel'ın dosya sistemi olaylarını izleme mekanizması. inotify-tools paketi bize inotifywait komutunu veriyor. Ubuntu/Debian'da:

sudo apt update && sudo apt install inotify-tools -y

RHEL/CentOS'ta:

sudo yum install inotify-tools -y

Basit bir test:

inotifywait -m /etc/nginx/

Bu komut /etc/nginx/ dizinini izlemeye başlar. Başka bir terminalde nano /etc/nginx/nginx.conf açın, bir satır ekleyin, kaydedin. İlk terminalde şöyle bir çıktı göreceksiniz:

/etc/nginx/ OPEN nginx.conf /etc/nginx/ MODIFY nginx.conf /etc/nginx/ CLOSE_WRITE,CLOSE nginx.conf

inotifywait şu olayları izleyebilir: CREATE, DELETE, MODIFY, MOVE, CLOSE_WRITE. Biz genelde CLOSE_WRITE kullanıyoruz çünkü dosya tamamen yazılıp kapatıldığında tetikleniyor. MODIFY her byte değişiminde tetiklenir, çok fazla noise oluşturur.

Önemli bir nokta: inotify recursive izleme yapmaz. Yani /var/www/html/ izliyorsanız, sadece o dizindeki dosyaları izler, alt dizinleri izlemez. Recursive izleme için -r bayrağı ekleyin:

inotifywait -m -r /var/www/html/

Ama dikkat: çok büyük dizin ağaçlarında (node_modules gibi) inotify watch limitleri sorun çıkarabilir. /proc/sys/fs/inotify/max_user_watches değerini artırmanız gerekebilir:

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf sudo sysctl -p

Ben FUTIA projelerinde genelde spesifik dosyaları izliyorum, tüm dizinleri değil. Mesela /var/www/html/.env, /var/www/html/wp-config.php gibi. Bu şekilde false positive azalıyor.

Bash scripti: temel yapı ve Telegram entegrasyonu

Şimdi scripti yazalım. /usr/local/bin/file-integrity-monitor.sh oluşturun:

#!/bin/bash

TELEGRAM_BOT_TOKEN="6234567890:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw" TELEGRAM_CHAT_ID="123456789" WATCH_PATHS=("/etc/nginx/sites-available" "/var/www/html/.env" "/home/deploy/.ssh/authorized_keys") LOG_FILE="/var/log/file-integrity.log"

send_telegram() { local message="$1" curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ -d chat_id="${TELEGRAM_CHAT_ID}" \ -d text="${message}" \ -d parse_mode="Markdown" > /dev/null }

log_event() { local event="$1" local filepath="$2" local timestamp=$(date +"%Y-%m-%d %H:%M:%S") echo "{\"timestamp\":\"${timestamp}\",\"event\":\"${event}\",\"file\":\"${filepath}\"}" >> "${LOG_FILE}" }

for path in "${WATCH_PATHS[@]}"; do if [[ ! -e "$path" ]]; then send_telegram "⚠️ WARNING: ${path} bulunamadı, izleme başlatılamadı." fi done

inotifywait -m -r -e close_write,move,delete "${WATCH_PATHS[@]}" | while read -r directory event filename; do filepath="${directory}${filename}" message="🔴 Dosya değişikliği tespit edildi\n\n📁 Dosya: ${filepath}\n🔧 Olay: ${event}\n⏰ Zaman: $(date +"%Y-%m-%d %H:%M:%S")\n🖥 Sunucu: $(hostname)"

send_telegram "${message}" log_event "${event}" "${filepath}" done

Script şunu yapıyor: WATCH_PATHS dizisindeki tüm yolları izliyor, bir değişiklik olduğunda Telegram'a mesaj gönderiyor, olayı JSON formatında loglara yazıyor. Markdown formatında mesaj gönderiyoruz, böylece emoji ve bold text kullanabiliyoruz.

Chmod ile çalıştırılabilir yapın:

sudo chmod +x /usr/local/bin/file-integrity-monitor.sh

Test için çalıştırın:

sudo /usr/local/bin/file-integrity-monitor.sh

Başka bir terminalde touch /var/www/html/.env yapın. Telefona bildirim geldi mi? Geldiyse sistem çalışıyor.

Systemd service oluşturma ve daemonize etme

Script şu anda foreground'da çalışıyor. Systemd service olarak arka planda çalışmasını sağlayalım. /etc/systemd/system/file-integrity-monitor.service oluşturun:

[Unit] Description=File Integrity Monitoring Service After=network.target

[Service] Type=simple User=root ExecStart=/usr/local/bin/file-integrity-monitor.sh Restart=always RestartSec=10 StandardOutput=journal StandardError=journal

[Install] WantedBy=multi-user.target

Service'i aktif edin:

sudo systemctl daemon-reload sudo systemctl enable file-integrity-monitor.service sudo systemctl start file-integrity-monitor.service

Durum kontrolü:

sudo systemctl status file-integrity-monitor.service

Active: active (running) görüyorsanız sistem çalışıyor. Logları görmek için:

sudo journalctl -u file-integrity-monitor.service -f

Restart=always ve RestartSec=10 sayesinde script crash olsa bile 10 saniye sonra otomatik yeniden başlıyor. Ben doktorbul.com sunucusunda 4 aydır bu sistem çalışıyor, hiç müdahale etmedim.

Bir detay: User=root olarak çalıştırıyoruz çünkü /etc/nginx/ gibi dizinlere root yetkisi gerekiyor. Eğer sadece user-level dosyaları izliyorsanız (mesela /home/deploy/), User=deploy yapabilirsiniz.

Gelişmiş özellikler: hash kontrolü ve değişiklik diff'i

Şu anki sistem dosya değiştiğinde haber veriyor ama ne değiştiğini göstermiyor. Hash kontrolü ve diff ekleyelim. Script'e şu fonksiyonu ekleyin:

HASH_DIR="/var/lib/file-integrity-hashes" mkdir -p "${HASH_DIR}"

compute_hash() { local filepath="$1" sha256sum "${filepath}" | awk '{print $1}' }

check_and_alert() { local filepath="$1" local event="$2"

if [[ ! -f "${filepath}" ]]; then return fi

local hash_file="${HASH_DIR}/$(echo ${filepath} | sed 's/\//_/g').sha256" local current_hash=$(compute_hash "${filepath}")

if [[ -f "${hash_file}" ]]; then local previous_hash=$(cat "${hash_file}") if [[ "${current_hash}" != "${previous_hash}" ]]; then local message="🔴 Dosya içeriği değişti\n\n📁 Dosya: ${filepath}\n🔧 Olay: ${event}\n⏰ Zaman: $(date +"%Y-%m-%d %H:%M:%S")\n🖥 Sunucu: $(hostname)\n\n🔐 Eski hash: ${previous_hash}\n🔐 Yeni hash: ${current_hash}" send_telegram "${message}" log_event "${event}" "${filepath}" echo "${current_hash}" > "${hash_file}" fi else echo "${current_hash}" > "${hash_file}" send_telegram "ℹ️ Yeni dosya izlemeye alındı: ${filepath}" fi }

Ana loop'u şöyle değiştirin:

inotifywait -m -r -e close_write,move,delete "${WATCH_PATHS[@]}" | while read -r directory event filename; do filepath="${directory}${filename}" check_and_alert "${filepath}" "${event}" done

Bu versiyon her dosyanın SHA256 hash'ini saklıyor. Dosya değiştiğinde hash'i karşılaştırıyor, farklıysa uyarı gönderiyor. Böylece false positive azalıyor: dosya touch edilmiş ama içerik değişmemişse uyarı gelmiyor.

Diff eklemek isterseniz (dikkat, hassas bilgi içerebilir):

DIFF_DIR="/var/lib/file-integrity-diffs" mkdir -p "${DIFF_DIR}"

if [[ "${current_hash}" != "${previous_hash}" ]]; then local backup_file="${DIFF_DIR}/$(basename ${filepath}).$(date +%s).bak" cp "${filepath}" "${backup_file}"

# Diff oluştur (opsiyonel, hassas dosyalarda dikkatli kullanın) # diff -u "${previous_backup}" "${backup_file}" > "${DIFF_DIR}/$(basename ${filepath}).diff" fi

Ben FUTIA projelerinde diff kullanmıyorum çünkü .env dosyaları API key içeriyor. Ama nginx config gibi hassas olmayan dosyalarda kullanışlı.

Gerçek vaka: kamupersonelhaber.com'da SSH key değişikliği

Geçen ay kamupersonelhaber.com'da ilginç bir olay yaşadık. Sistemde /home/deploy/.ssh/authorized_keys dosyasını izliyorduk. Bir gece saat 03:24'te Telegram'dan bildirim geldi: dosya değişmiş. Hemen sunucuya bağlandım, baktım ki yeni bir SSH public key eklenmiş.

İlk düşüncem: güvenlik ihlali. Ama biraz araştırınca anladım ki hosting provider otomatik backup sistemi için kendi key'ini eklemişti. Bize haber vermemişler. Onlarla konuştuk, key'i doğruladık, sisteme whitelist ekledik.

Eğer bu izleme sistemi olmasaydı, o key'i hiç fark etmeyecektik. Belki aylar sonra bir sorun çıkacaktı. Proaktif monitoring sayesinde 10 dakika içinde durumu tespit edip çözdük.

Bir başka vaka: diolivo.com.tr'de wp-config.php değişikliği. Bir geliştirici debug modunu açmış, commit etmeyi unutmuş. Production'a deploy olmuş. Sistem 30 saniye içinde uyardı, hemen geri aldık. Kullanıcılar debug mesajları görmeden düzelttik.

Bu tür sistemler %99 zaman sessiz kalıyor. Ama o %1'lik kritik anlarda kurtarıcı oluyor.

Performans optimizasyonu ve sınırlamalar

inotify çok hafif bir sistem ama bazı sınırlamaları var. Varsayılan olarak kullanıcı başına 8192 watch limiti var. Büyük projeler için yetersiz. Kontrol edin:

cat /proc/sys/fs/inotify/max_user_watches

Artırmak için:

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf sudo sysctl -p

Bir diğer sınırlama: inotify sadece yerel dosya sistemlerinde çalışır. NFS, CIFS gibi network file system'lerde çalışmaz. Eğer network storage kullanıyorsanız, polling-based bir çözüm (find + hash compare) kullanmanız gerekir.

Performans açısından: inotifywait neredeyse sıfır CPU kullanır. Ben doktorbul.com'da 79.000 dosyalı bir dizinde kullanıyorum, top çıktısında %0.0 CPU görünüyor. Tek maliyet Telegram API çağrısı ama o da saniyede bir kere bile olmuyor.

Telegram API rate limit: saniyede 30 mesaj, dakikada 20 farklı chat. Normal kullanımda sorun olmaz ama çok fazla dosya değişikliği varsa queue sistemi kurabilirsiniz:

MESSAGE_QUEUE=() QUEUE_INTERVAL=5

queue_message() { MESSAGE_QUEUE+=("$1") }

send_queued_messages() { if [[ ${#MESSAGE_QUEUE[@]} -gt 0 ]]; then local combined_message=$(printf "%s\n\n" "${MESSAGE_QUEUE[@]}") send_telegram "${combined_message}" MESSAGE_QUEUE=() fi }

while true; do send_queued_messages sleep "${QUEUE_INTERVAL}" done &

Bu yapı mesajları 5 saniye bekletip toplu gönderiyor. Ama çoğu proje için gerekli değil.

Alternatif yaklaşımlar ve FUTIA'da kullandığımız sistem

Bash scripti dışında başka seçenekler de var. Tripwire: endüstri standardı, çok güçlü ama kurulumu karmaşık. AIDE: Tripwire'a benzer, Debian'da varsayılan. Samhain: client-server mimarisi, büyük altyapılar için. OSSEC: full HIDS (Host Intrusion Detection System), log analizi de yapıyor.

Ben neden bash tercih ediyorum? Çünkü FUTIA projelerinde basitlik önemli. Her proje farklı sunucuda, farklı yapıda. Tek dosya script kopyalayıp 5 dakikada kuruyorum. OSSEC kurmak 2 saat sürer, dokümantasyon okumak 1 gün.

FUTIA'da kullandığımız sistem biraz daha gelişmiş. Şu özellikleri ekledik:

  • Slack entegrasyonu (bazı müşteriler Telegram kullanmıyor)
  • JSON log dosyalarını günlük rotate ediyoruz (logrotate config)
  • Whitelist sistemi: belirli dosyalar veya pattern'lar uyarı vermiyor
  • Kritik dosyalar için ayrı Telegram kanalı (high priority)
  • Haftalık özet rapor: kaç değişiklik oldu, hangi dosyalar

Kod açık kaynak değil ama mantığını anlattım, kendiniz kurabilirsiniz. Eğer hazır sistem isterseniz, FUTIA olarak sunucu güvenlik otomasyonu da yapıyoruz. WhatsApp'tan yazabilirsiniz: +90 532 491 17 05

Güvenlik notları ve production'a almadan önce

Bu sistemi production'a almadan önce birkaç güvenlik noktası:

1. Telegram bot token'ı asla git'e commit etmeyin. Environment variable veya ayrı config dosyası kullanın. 2. Log dosyalarında hassas bilgi olabilir. /var/log/file-integrity.log dosyasını chmod 600 yapın, sadece root okuyabilsin. 3. Script root olarak çalışıyorsa, injection saldırılarına dikkat edin. Dosya adlarında space, özel karakter varsa sorun çıkabilir. Değişkenleri "${variable}" şeklinde quote'layın. 4. Telegram mesajlarında hassas bilgi göndermemeye çalışın. Dosya içeriği değil, sadece dosya adı ve hash gönderin. 5. İzlenen dizinlerde çok fazla değişiklik oluyorsa (log dosyaları gibi), sistemi exclude edin. Yoksa spam olursunuz.

Bir de test ortamında mutlaka deneyin. Production sunucuda ilk kez çalıştırdığınızda belki yüzlerce uyarı alırsınız (backup scriptleri, cron job'lar vs). Önce whitelist'i düzenleyin, sonra production'a alın.

Ben FUTIA projelerinde şu yaklaşımı kullanıyorum: ilk hafta "silent mode" çalıştırıyorum, sadece loglara yazıyor, Telegram'a göndermiyor. Logları inceliyorum, hangi değişiklikler normal hangileri anormal anlıyorum. Sonra whitelist'i ayarlayıp Telegram'ı aktif ediyorum.

Son bir not: bu sistem security audit'in yerini tutmaz. Düzenli olarak sunucu loglarını incelemeli, güvenlik güncellemelerini takip etmeli, penetration test yaptırmalısınız. Dosya bütünlüğü izleme sadece bir katman, tek başına yeterli değil.

Ben FUTIA'da Hollanda'dan Türk markalarına site + otomasyon + güvenlik hizmeti veriyorum. Sunucu güvenliği konusunda danışmanlık veya hazır sistem kurulumu isterseniz, info@futia.net adresinden ulaşabilirsiniz. İtalyanmutfagi.com, memuratamalari.com gibi yüksek trafikli sitelerde bu tür sistemleri aktif kullanıyoruz.

Sıkça Sorulanlar

inotify-tools yerine başka araç kullanabilir miyim?

Evet, alternatifler var. macOS'ta fswatch, BSD'de kqueue kullanabilirsiniz. Ama Linux sunucularda inotify en stabil ve performanslı seçenek. Eğer cross-platform çözüm istiyorsanız, watchdog (Python) veya chokidar (Node.js) kütüphanelerini değerlendirebilirsiniz. Ancak bunlar ekstra runtime gerektiriyor (Python veya Node.js kurulu olmalı). Bash + inotify kombinasyonu herhangi bir dependency olmadan çalışır, bu yüzden tercih ediyorum.

Telegram yerine e-mail bildirimi kullansam olmaz mı?

E-mail çalışır ama gerçek zamanlı değil. SMTP server kurmanız, spam filtreleri ile uğraşmanız gerekir. Telegram anında push notification gönderiyor, telefonda uygulama açık olmasa bile bildirim geliyor. Ayrıca Telegram bot API ücretsiz ve rate limit çok yüksek. E-mail için SendGrid, Mailgun gibi servislerde aylık limit var. Slack veya Discord da alternatif olabilir, webhook entegrasyonu benzer şekilde kolay. Ben müşteri tercihine göre hepsini kullanıyorum ama kişisel projelerimde Telegram tercihim.

Sistemde çok fazla false positive alıyorum, nasıl azaltırım?

İlk adım: sadece CLOSE_WRITE event'ini izleyin, MODIFY veya OPEN izlemeyin. İkinci adım: hash kontrolü ekleyin, dosya touch edilmiş ama içerik değişmemişse uyarı vermesin. Üçüncü adım: whitelist pattern'ları tanımlayın. Mesela *.log, *.tmp, *~ gibi dosyaları ignore edin. Dördüncü adım: backup script'leri, cron job'ları belirli saatlerde çalışıyorsa, o saatlerde bildirimleri susturun. Ben FUTIA projelerinde ilk hafta silent mode çalıştırıp normal trafiği öğreniyorum, sonra threshold'ları ayarlıyorum.

Docker container içindeki dosyaları izleyebilir miyim?

Evet ama dikkat edilmesi gereken noktalar var. Container içinde inotify-tools kurulu olmalı. Volume mount edilen dizinleri izlerseniz, host tarafında da inotify watch sayılır. Çok fazla container varsa max_user_watches limitine takılabilirsiniz. Alternatif olarak host sistemde script çalıştırıp, volume path'lerini izleyebilirsiniz. Mesela /var/lib/docker/volumes/myapp/_data/ şeklinde. Ama container restart olduğunda path değişebilir, bu yüzden container name veya ID ile dinamik path bulmanız gerekir. Kubernetes'te daha karmaşık, sidecar container veya DaemonSet kullanmanız lazım.

Sistemde bir güvenlik açığı tespit ettiğimde ne yapmalıyım?

İlk adım: değişen dosyayı hemen yedekleyin, sonra analiz için saklayın. İkinci adım: sunucuyu network'ten izole edin, daha fazla zarar görmesini engelleyin. Üçüncü adım: dosya değişikliğinin kaynağını bulun, hangi user, hangi process yaptı. last, w, ps aux, netstat komutlarıyla aktif bağlantıları kontrol edin. Dördüncü adım: güvenlik açığını kapatın, sistemi temiz bir backup'tan restore edin. Beşinci adım: tüm şifreleri, API key'leri değiştirin. Son adım: incident report yazın, nasıl oldu, nasıl önlenir. Ben FUTIA projelerinde bu tür durumlar için runbook hazırlıyorum, panik anında ne yapacağınızı biliyorsunuz.

YAZAR HAKKINDA
Miraç Eroğlu

Hacettepe mezunu, 6 yıldır sosyal medya, 2 yıldır AI otomasyon.

Daha fazla bilgi →

Bu yazıdaki tekniklerden birini uygulamak ister misiniz? Kısa bir form doldurun, 48 saat içinde ücretsiz ön inceleme raporu mailinize düşsün.