Tüm yazılar
·11 dk okuma·ShamashAi Ekibi

ShamashAi Reachability Logs: TCP/ICMP Probe'lar Neden Ayrı Tabloda Tutuluyor?

ShamashAi, TCP ve ICMP probe sonuçlarını events tablosundan ayrı reachability_logs tablosunda saklar. Health check log'ları güvenlik olaylarını kirletmez, hot-path sorgular yavaşlamaz. Retention politikası, filtreler ve performans tasarımı detaylarıyla.

Cuma Sabahı 08:47: dc-01 Erişilemiyor Uyarısı

Cuma sabahı 08:47'de ShamashAi Dashboard'unda kırmızı bir uyarı belirir: "dc-01.prod.local - TCP:3389 erişilemiyor (timeout 3000ms)". Sistem yöneticisi Mehmet, hemen Device Health paneline bakar. Son 10 dakikada dc-01 sunucusuna 6 ardışık TCP probe gönderilmiş, tümü başarısız. Latency değerleri sıfır, status 'fail', message: "Connection refused or timeout". Aynı anda events tablosunda 14 farklı BRUTE_FORCE_DETECTED, 3 M365_RISKY_SIGNIN kaydı var — bu kritik güvenlik olayları. Mehmet, şükür eder ki reachability log'ları events tablosunu şişirtmemiş. Eğer her 2 dakikada bir 50 cihaza gönderilen ICMP ping ve TCP check'ler events tablosunda dursaydı, günde onlarca bin kayıt birikir, sorgular yavaşlar, asıl tehditleri görmek zorlaşırdı. ShamashAi bu sorunu tasarım aşamasında çözdü: reachability_logs adlı ayrı bir tabloya yazarak hot-path performansını korudu ve event_type semantiğini bozmadı. Bu yazıda ShamashAi'nin reachability probe sisteminin mimari kararlarını, tablo yapısını, retention politikasını ve kullanım senaryolarını teknik detaylarıyla açıklıyoruz.

Neden Ayrı Tablo? Event Tablosunu Kirletme Riski

Events Tablosunun Amacı: Güvenlik Olayları

ShamashAi'nin merkezi dbo.events tablosu, güvenlik olaylarını saklar. Her satır bir event_type (BRUTE_FORCE_DETECTED, AUTH_FAIL_USER, KNOWN_BAD_IP, BEHAVIORAL_ANOMALY, CERT_EXPIRING, SOAR_ACTION, BACKUP_FAILED vb.) taşır. Bu tablonun sorguları, SIEM'in çekirdeğini oluşturur:
  • Gerçek zamanlı korelasyon kuralları (örn. "10 dakikada 5'ten fazla AUTH_FAIL_USER aynı IP'den → BRUTE_FORCE_DETECTED tetikle")
  • Incident gruplandırma (dbo.incident_groups ile ilişkilendirme)
  • AI/ML model besleme (POST /ai/investigate-event endpoint'i event_type'lara bakarak pattern arar)
  • Compliance raporları (GET /compliance/evidence, KVKK Madde 12 kanıtları)
Events tablosu hot-path'tir: saniyede onlarca yeni kayıt, yüzlerce okuma. Index'ler (event_type, timestamp, source_device_id) bu hızı sağlar.

Health Check Log'ları Farklı Bir Kategori

Reachability probe'ları (TCP port check, ICMP ping) ise operational telemetry'dir — cihazların erişilebilirlik durumunu izler, güvenlik tehdidi değildir. Özellikleri:
  • Yüksek hacim: Eğer 200 cihaza 2 dakikada bir probe gönderilirse günde ~144.000 kayıt.
  • Farklı semantik: "status: ok/warn/fail/unknown", "latency_ms" gibi alanlar event_type semantiğine uymaz.
  • Farklı retention: Health check log'ları daha kısa süre saklanabilir (genelde 30 gün yeter), events ise compliance gereklilikleri nedeniyle 90+ gün tutulur.
  • Farklı okuma patern: Reachability log'ları genelde Device Detail sayfasında veya "son 1 saat erişilemeyen cihazlar" sorgusuyla okunur; correlation engine'e girmez.
Events tablosuna reachability kayıtları yazılsaydı: 1. Index şişmesi: event_type index'ine anlamsız "HEALTH_CHECK" değerleri binerce kez eklenir. 2. Query yavaşlaması: "Son 1 saatte BRUTE_FORCE_DETECTED olayları" sorgusu, 7200 health check kaydını da taramak zorunda kalır (WHERE event_type = 'BRUTE_FORCE_DETECTED' filtresinde bile index scan pahalılaşır). 3. Karışık semantik: Correlation kuralları "event_type IN ('BRUTE_FORCE_DETECTED', 'AUTH_FAIL_USER')" yazarken sürekli "AND event_type NOT LIKE '%HEALTH%'" eklemek zorunda kalır. 4. Retention karmaşası: Events 90 gün tutulurken health check'leri 30 günde silmek için ekstra script gerekir.

ShamashAi Reachability_Logs Tablosu: Yapı ve Alanlar

ShamashAi, dbo.reachability_logs tablosunu şu şemayla tasarladı: sql CREATE TABLE dbo.reachability_logs ( id BIGINT IDENTITY PRIMARY KEY, timestamp DATETIME2(3) NOT NULL, source VARCHAR(255) NOT NULL, -- device hostname veya IP check_type VARCHAR(50) NOT NULL, -- 'TCP', 'ICMP' target VARCHAR(255), -- hedef IP/hostname (TCP için port:3389 vs.) status VARCHAR(20) NOT NULL, -- 'ok', 'warn', 'fail', 'unknown' latency_ms INT, -- ping/response süresi (ms) message NVARCHAR(1000), -- "Connection refused", "Timeout 3000ms" vb. INDEX idx_timestamp (timestamp DESC), INDEX idx_source_status (source, status, timestamp DESC) );

Alan Açıklamaları

  • check_type: 'TCP' (belirli porta bağlanma denemeleri, örn. 3389/RDP, 22/SSH) veya 'ICMP' (ping).
  • status:
- ok: Probe başarılı, cihaz erişilebilir. - warn: Yavaş yanıt (örn. latency_ms > 500) ama erişilebilir. - fail: Timeout, connection refused, host unreachable. - unknown: Probe gönderildi ama sonuç belirsiz (nadiren, network hatası).
  • latency_ms: Round-trip süresi. ICMP için ping latency, TCP için SYN-ACK süresi.
  • message: Hata mesajı (örn. "EHOSTUNREACH", "Timeout 5000ms") veya başarı notu ("Response in 12ms").
Örnek kayıt: { "timestamp": "2026-08-12T08:47:23.456Z", "source": "dc-01.prod.local", "check_type": "TCP", "target": "dc-01.prod.local:3389", "status": "fail", "latency_ms": null, "message": "Connection refused or timeout (3000ms)" }

API ve UI Entegrasyonu

GET /reachability/logs Endpoint

ShamashAi API, reachability log'larını sorgulamak için GET /reachability/logs endpoint'ini sunar: Request (Node.js Fastify route örneği): javascript // routes/reachability.js module.exports = async function (fastify, opts) { fastify.get('/reachability/logs', { schema: { querystring: { type: 'object', properties: { source: { type: 'string' }, // device hostname/IP status: { type: 'string', enum: ['ok', 'warn', 'fail', 'unknown'] }, q: { type: 'string' }, // free text search (message içinde) start: { type: 'string', format: 'date-time' }, end: { type: 'string', format: 'date-time' }, limit: { type: 'integer', default: 100, maximum: 1000 } } } }, preHandler: fastify.authenticate // JWT check }, async (request, reply) => { const { source, status, q, start, end, limit } = request.query; const db = fastify.mssql.pool; let query = 'SELECT TOP (@limit) * FROM dbo.reachability_logs WHERE 1=1'; const params = { limit }; if (source) { query += ' AND source = @source'; params.source = source; } if (status) { query += ' AND status = @status'; params.status = status; } if (q) { query += ' AND message LIKE @q'; params.q = %${q}%; } if (start) { query += ' AND timestamp >= @start'; params.start = start; } if (end) { query += ' AND timestamp <= @end'; params.end = end; } query += ' ORDER BY timestamp DESC'; const result = await db.request() .input('limit', fastify.mssql.Int, params.limit) .input('source', fastify.mssql.VarChar, params.source) .input('status', fastify.mssql.VarChar, params.status) .input('q', fastify.mssql.NVarChar, params.q) .input('start', fastify.mssql.DateTime2, params.start) .input('end', fastify.mssql.DateTime2, params.end) .query(query); return { logs: result.recordset, count: result.recordset.length }; }); }; Response: { "logs": [ { "id": 9823471, "timestamp": "2026-08-12T08:47:23.456Z", "source": "dc-01.prod.local", "check_type": "TCP", "target": "dc-01.prod.local:3389", "status": "fail", "latency_ms": null, "message": "Connection refused or timeout (3000ms)" }, { "id": 9823470, "timestamp": "2026-08-12T08:45:11.234Z", "source": "dc-01.prod.local", "check_type": "ICMP", "target": "dc-01.prod.local", "status": "ok", "latency_ms": 12, "message": "Response in 12ms" } ], "count": 2 }

Filtreler: source, status, free text

ShamashAi dokümantasyonu şu filtreleri açıkça tanımlar:
  • source: Device hostname veya IP (örn. "dc-01.prod.local" veya "10.20.30.40").
  • status: ok/warn/fail/unknown enum değeri.
  • q (free text): message alanında arama. Örneğin q=timeout tüm timeout içeren kayıtları döner.
  • start / end: ISO 8601 zaman aralığı (örn. "2026-08-12T00:00:00Z").
Bu filtreler, Device Detail sayfasında veya Reachability UI'da "Son 1 saat erişilemeyen cihazlar" sorgusunda kullanılır.

DeviceHealthConnector Feed Mekanizması

ShamashAi .NET 8 agent'ı içinde DeviceHealthConnector modülü, reachability_logs tablosunu besler. Tasarım: 1. Device Registry: dbo.devices tablosundaki her cihaz için health_check_enabled flag'i true ise, probe ayarları (check_type, interval_seconds, target_port) kaydedilir. 2. Probe Scheduler: Agent, her interval_seconds (default 120) saniyede bir TCP veya ICMP probe gönderir. 3. Result Writer: Probe sonucu (status, latency_ms, message) reachability_logs tablosuna INSERT edilir — dbo.events tablosuna değil. Örnek .NET 8 DeviceHealthConnector kodu (basitleştirilmiş): csharp // Services/DeviceHealthConnector.cs using System.Diagnostics; using System.Net.NetworkInformation; using System.Net.Sockets; using Microsoft.Data.SqlClient; public class DeviceHealthConnector : BackgroundService { private readonly IConfiguration _config; private readonly ILogger<DeviceHealthConnector> _logger; public DeviceHealthConnector(IConfiguration config, ILogger<DeviceHealthConnector> logger) { _config = config; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var connectionString = _config.GetConnectionString("ShamashDb"); var intervalMs = _config.GetValue<int>("HealthCheck:IntervalSeconds", 120) * 1000; while (!stoppingToken.IsCancellationRequested) { await RunProbes(connectionString); await Task.Delay(intervalMs, stoppingToken); } } private async Task RunProbes(string connStr) { using var conn = new SqlConnection(connStr); await conn.OpenAsync(); // dbo.devices tablosundan health_check_enabled=true cihazları çek var cmd = new SqlCommand( "SELECT hostname, ip_address, health_check_type, health_check_port FROM dbo.devices WHERE health_check_enabled=1", conn); using var reader = await cmd.ExecuteReaderAsync(); var tasks = new List<Task>(); while (await reader.ReadAsync()) { var hostname = reader.GetString(0); var ip = reader.GetString(1); var checkType = reader.GetString(2); // "TCP" veya "ICMP" var port = reader.IsDBNull(3) ? 0 : reader.GetInt32(3); tasks.Add(ProbeDevice(connStr, hostname, ip, checkType, port)); } await Task.WhenAll(tasks); } private async Task ProbeDevice(string connStr, string hostname, string ip, string checkType, int port) { string status, message; int? latencyMs = null; var sw = Stopwatch.StartNew(); try { if (checkType == "ICMP") { using var ping = new Ping(); var reply = await ping.SendPingAsync(ip, 3000); if (reply.Status == IPStatus.Success) { status = "ok"; latencyMs = (int)reply.RoundtripTime; message = $"Response in {latencyMs}ms"; } else { status = "fail"; message = $"ICMP failed: {reply.Status}"; } } else // TCP { using var client = new TcpClient(); await client.ConnectAsync(ip, port).WaitAsync(TimeSpan.FromSeconds(3)); sw.Stop(); status = "ok"; latencyMs = (int)sw.ElapsedMilliseconds; message = $"TCP {port} open, latency {latencyMs}ms"; } } catch (Exception ex) { sw.Stop(); status = "fail"; message = ex.Message.Length > 900 ? ex.Message.Substring(0, 900) : ex.Message; } // reachability_logs tablosuna yaz await WriteLog(connStr, hostname, checkType, $"{ip}:{port}", status, latencyMs, message); } private async Task WriteLog(string connStr, string source, string checkType, string target, string status, int? latencyMs, string message) { using var conn = new SqlConnection(connStr); await conn.OpenAsync(); var cmd = new SqlCommand( "INSERT INTO dbo.reachability_logs (timestamp, source, check_type, target, status, latency_ms, message) " + "VALUES (SYSDATETIME(), @source, @checkType, @target, @status, @latencyMs, @message)", conn); cmd.Parameters.AddWithValue("@source", source); cmd.Parameters.AddWithValue("@checkType", checkType); cmd.Parameters.AddWithValue("@target", target); cmd.Parameters.AddWithValue("@status", status); cmd.Parameters.AddWithValue("@latencyMs", (object?)latencyMs ?? DBNull.Value); cmd.Parameters.AddWithValue("@message", message); await cmd.ExecuteNonQueryAsync(); _logger.LogDebug("Reachability log written: {source} {status}", source, status); } } Bu kod, dbo.events tablosuna hiç dokunmaz — sadece reachability_logs yazar.

Retention Politikası: 30 Gün vs. 90 Gün

ShamashAi dokümantasyonu açıkça şunu belirtir:
  • reachability_logs retention: 30 gün (default). Health check log'ları, cihaz erişilebilirlik trendlerini görmek için kısa vadeli kullanılır.
  • dbo.events retention: 90 gün (KVKK Madde 12 uyum, ISO 27001:2022 Annex A kanıt saklama gerekliliği).
Neden bu fark? 1. Hacim farkı: 200 cihaza 2 dakikada bir probe = günde ~144.000 kayıt. 30 günde 4.3M satır. 90 güne çıkarsa 13M satır — disk ve index maliyeti artar. 2. Compliance gerekliliği yok: Reachability log'ları güvenlik tehdidi değil, operasyonel veridir. KVKK raporlarına girmez. 3. Trend analizi yeterli: Bir cihazın son 30 gündeki uptime/downtime trendi, kapasite planlaması için yeterli. Retention job (SQL Server Agent veya Hangfire ile): sql -- Her gece 02:00'de çalışan job DELETE FROM dbo.reachability_logs WHERE timestamp < DATEADD(day, -30, GETDATE()); Events tablosunda ise: sql DELETE FROM dbo.events WHERE timestamp < DATEADD(day, -90, GETDATE()); Bu iki ayrı retention policy, tablolar ayrı olduğu için kolayca uygulanır.

Reachability Sayfası: Ayrı UI

ShamashAi Next.js web uygulamasında Reachability adlı ayrı bir sayfa vardır:
  • URL: /reachability
  • Özellikler:
- Son 24 saat/7 gün/30 gün filtresi. - Status bazlı renk kodlu tablo (ok=yeşil, warn=sarı, fail=kırmızı). - Free text arama (message alanında). - Device Detail sayfasından linkleme: Her cihazın "Health Check History" butonu, /reachability?source=dc-01.prod.local açar.
  • Events sayfasından ayrılık: Events sayfası (dbo.events) event_type, severity, incident_id gösterir. Reachability sayfası ise check_type, latency_ms, status gösterir — karışmaz.
Örnek Next.js component: typescript // pages/reachability.tsx import { useQuery } from '@tanstack/react-query'; import { useState } from 'react'; const ReachabilityPage = () => { const [filters, setFilters] = useState({ status: '', source: '', q: '' }); const { data, isLoading } = useQuery(['reachability', filters], async () => { const params = new URLSearchParams( Object.entries(filters).filter(([_, v]) => v !== '') ); const res = await fetch(/api/reachability/logs?${params}, { headers: { Authorization: Bearer ${localStorage.getItem('token')} } }); return res.json(); }); if (isLoading) return <div>Yükleniyor...</div>; return ( <div className="p-6"> <h1 className="text-2xl font-bold mb-4">Reachability Logs</h1> <div className="flex gap-4 mb-4"> <input placeholder="Source (hostname/IP)" value={filters.source} onChange={e => setFilters({ ...filters, source: e.target.value })} className="border p-2" /> <select value={filters.status} onChange={e => setFilters({ ...filters, status: e.target.value })} className="border p-2" > <option value="">Tüm durumlar</option> <option value="ok">OK</option> <option value="warn">Warn</option> <option value="fail">Fail</option> </select> <input placeholder="Message'da ara (free text)" value={filters.q} onChange={e => setFilters({ ...filters, q: e.target.value })} className="border p-2" /> </div> <table className="w-full border"> <thead> <tr className="bg-gray-100"> <th className="p-2">Timestamp</th> <th>Source</th> <th>Check Type</th> <th>Target</th> <th>Status</th> <th>Latency (ms)</th> <th>Message</th> </tr> </thead> <tbody> {data?.logs.map((log: any) => ( <tr key={log.id} className={log.status === 'fail' ? 'bg-red-50' : ''}> <td className="p-2">{new Date(log.timestamp).toLocaleString('tr-TR')}</td> <td>{log.source}</td> <td>{log.check_type}</td> <td>{log.target}</td> <td> <span className={`px-2 py-1 rounded ${ log.status === 'ok' ? 'bg-green-100 text-green-800' : log.status === 'warn' ? 'bg-yellow-100 text-yellow-800' : 'bg-red-100 text-red-800' }`}> {log.status.toUpperCase()} </span> </td> <td>{log.latency_ms ?? '-'}</td> <td className="text-sm">{log.message}</td> </tr> ))} </tbody> </table> </div> ); }; export default ReachabilityPage;

Performans Kazanımları: Somut Metrikler

200 cihazlı bir ortamda, 2 dakikalık probe interval varsayımıyla:
  • Günlük reachability kayıt: ~144.000 (200 cihaz × 720 probe/gün).
  • Günlük security event: ~500-2000 (brute force, auth fail, anomaly vb.).
Eğer reachability kayıtları events tablosunda tutulunsaydı:
  • Events tablosu büyüklüğü: 90 günde 13M reachability + 90K security = 13.09M satır.
  • Query: "Son 1 saatte BRUTE_FORCE_DETECTED" → WHERE event_type = 'BRUTE_FORCE_DETECTED' AND timestamp > DATEADD(hour, -1, GETDATE()) index scan'i 1 saatte biriken 6000 reachability kaydını da tarar (index selectivity düşer).
  • Index boyutu: event_type index'i 13M satıra yayılır, cache miss riski artar.
Ayrı tablo ile:
  • Events tablosu: 90 günde sadece 90K satır (güvenlik olayları).
  • Reachability_logs: 30 günde 4.3M satır, ama events query'lerine hiç dokunmaz.
  • Query "Son 1 saatte BRUTE_FORCE_DETECTED" sadece 90K satırlık tablodan okur — hız kazancı ~100x.
  • Index boyutu: event_type index'i 90K satır, CPU cache'e sığar.
Disk kullanımı:
  • Events (90 gün, 90K satır, ~500 byte/satır): ~45 MB.
  • Reachability_logs (30 gün, 4.3M satır, ~200 byte/satır): ~860 MB.
  • Toplam: ~905 MB. Eğer reachability events'te tutulunsaydı (90 gün): 13.09M × 400 byte = ~5.2 GB. Disk tasarrufu: ~4.3 GB.

Kullanım Senaryoları

1. Cihaz Downtime Analizi

SOC analisti, "dc-05 sunucusu neden dün gece 03:00-04:00 arası erişilemedi?" sorusunu araştırır: bash curl -H "Authorization: Bearer $TOKEN" \ "https://shamashai.local/api/reachability/logs?source=dc-05.prod.local&start=2026-08-11T03:00:00Z&end=2026-08-11T04:00:00Z" Dönüş: { "logs": [ { "timestamp": "2026-08-11T03:12:45Z", "status": "fail", "message": "Timeout 3000ms" }, { "timestamp": "2026-08-11T03:14:50Z", "status": "fail", "message": "Timeout 3000ms" }, { "timestamp": "2026-08-11T03:58:12Z", "status": "ok", "latency_ms": 18 } ] } Sonuç: 03:12-03:58 arası erişilememiş, 03:58'de normale dönmüş. Bu veriler dbo.events tablosunu kirletmemiş.

2. Yavaş Yanıt Veren Cihazları Bulma

"Latency > 200ms olan tüm cihazlar" sorgusu: sql SELECT source, AVG(latency_ms) AS avg_latency, COUNT(*) AS probe_count FROM dbo.reachability_logs WHERE timestamp > DATEADD(day, -7, GETDATE()) AND status = 'ok' GROUP BY source HAVING AVG(latency_ms) > 200 ORDER BY avg_latency DESC; Bu sorgu, events tablosuna dokunmadan reachability_logs'dan çeker.

3. Device Detail Sayfasında Health History

Kullanıcı Device Detail sayfasında "dc-01" seçer, "Health History" butonu /reachability?source=dc-01.prod.local&start=2026-08-05T00:00:00Z açar. Son 7 gündeki probe sonuçları grafik olarak gösterilir (ok/fail dağılımı).

Limitler ve Dürüst Notlar

1. Probe interval konfigürasyonu UI'da yok: Şu an probe interval (default 120 saniye) dbo.devices tablosunda elle set edilir veya deployment sırasında config'de tanımlanır. ShamashAi Admin UI'da "Device Settings > Health Check Interval" sayfası henüz yok; bu pilot sürecinde manuel yapılandırılır. 2. Reachability log'ları correlation engine'e girmez: dbo.reachability_logs tablosu SIEM correlation kurallarına beslenmez. Yani "cihaz 10 dakikadır erişilemiyor → otomatik incident oluştur" kuralı ShamashAi v1.0'da yok. Bu, roadmap'te "Operational Event Integration" başlığı altında. 3. Free text arama performansı: q parametresi message alanında LIKE sorgusu yapar — index'siz full-text search. 4M+ satırda yavaş olabilir. Eğer sık kullanılırsa SQL Server Full-Text Index eklenebilir, ancak varsayılan kurulumda yok. 4. Alerting reachability'de sınırlı: ShamashAi, reachability status=fail için basit e-posta bildirimi gönderebilir (dbo.devices tablosunda alert_on_fail flag'i varsa), ancak SOAR entegrasyonu (POST /soar/block gibi) reachability olaylarına uygulanmaz — sadece güvenlik olaylarına (dbo.events). 5. Multi-site probe yok: Eğer firmanın İstanbul ve Ankara ofisi varsa, dbo.sites tablosu var ama reachability probe'ları şu an merkezi agent'tan çıkar. Yani Ankara'daki cihaza İstanbul agent'ı probe atar — WAN latency'si gerçek lokal erişilebilirliği yansıtmayabilir. Multi-site probe agent mimarisi roadmap'te.

Sonuç: Ayrı Tablo, Temiz Mimari, Hızlı Sorgular

ShamashAi'nin reachability_logs tablosunu dbo.events'ten ayırması, mimari bir temizlik ve performans optimizasyonudur. Health check log'ları güvenlik olaylarını kirletmez, hot-path sorguları yavaşlatmaz, retention politikaları karışmaz. GET /reachability/logs endpoint'i ve ayrı UI, operasyonel telemetry'yi SIEM semantiğinden izole eder. 200 cihazlı bir ortamda, events tablosu 90K satır, reachability_logs 4.3M satır tutarak disk 4+ GB tasarruf, query hızı ~100x artış sağlar. DeviceHealthConnector .NET 8 modülü, TCP ve ICMP probe sonuçlarını doğru tabloya yazar. Pilot programı 30 gün ücretsiz: shamashai.com.tr/iletisim
Paylaş

Bu konuyu projenize uygulayalım

Pilot programı kapsamında ürünü gerçek altyapınızda 30 gün ücretsiz deneyin.