🌐 WireGuard Ağ Trafiği Takip ve Görselleştirme Sistemi Rehberi
Bu rehber, Almanya'daki bir Oracle VPS üzerinde çalışan WireGuard VPN sunucusunun anlık trafik verilerini, Tailscale tüneli üzerinden evdeki Home Assistant OS (HAOS) içindeki Postgres 17 veri tabanına güvenli bir şekilde aktarma ve Grafana ile dinamik olarak izleme sisteminin kurulum ve bakım adımlarını içerir.
🏗️ Genel Mimari ve Veri Akışı
Sistem 4 ana bileşenin saat gibi tıkır tıkır çalışması üzerine kuruludur: 1. Oracle VPS (Almanya): WireGuard sunucusu buradadır. Kullanıcıların anlık sayaç verilerini üretir. 2. Tailscale Tüneli: Evdeki HAOS ile Almanya'daki VPS arasında şifreli, doğrudan ve güvenli bir sanal köprü kurar. 3. Postgres 17 (HAOS / Ev): Gelen tüm trafik verilerini zaman damgasıyla kaydeden kurşun geçirmez defterimizdir. Server kapansa bile veriler burada kalıcıdır. 4. Grafana (HAOS / Ev): Veri tabanındaki verileri okuyarak anlık durumları, şampiyonları ve toplam tüketimleri görselleştirir.
[!info] Mimarinin Avantajı WireGuard normalde anlık bir sayaçtır ve sunucu yeniden başladığında sıfırlanır. Bu mimaride veriler 5 dakikada bir evdeki Postgres veri tabanına kalıcı olarak yazıldığı için geçmişe dönük günlük, haftalık ve yıllık analizler hatasız bir şekilde yapılabilir.
1. Veri Tabanı Altyapısı (Postgres 17)
Verilerin birikeceği tablo, yerel ağda (192.168.1.110) veya tünel ağında çalışan teslamate veri tabanı altında oluşturulmuştur.
Tablo Şeması (SQL)
CREATE TABLE wg_kullanim_istatistikleri (
id SERIAL PRIMARY KEY,
zaman TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
kullanici_adi VARCHAR(50),
wireguard_ip VARCHAR(50),
indirilen_byte BIGINT,
yuklenen_byte BIGINT
);
2. Veri Taşıyıcı Betik (Python Script)
Oracle VPS üzerinde /home/ubuntu/wg_to_postgres.py dizininde yer alan bu kod, WireGuard verilerini ayıklar, isimlerle eşleştirir ve Tailscale IP'si üzerinden evdeki veri tabanına gönderir.
wg_to_postgres.py İçeriği
import subprocess
import psycopg2
# WireGuard IP ve Kullanıcı Eşleştirmesi
kullanicilar = {
"10.66.66.2": "ali",
"10.66.66.3": "iklim",
"10.66.66.4": "irmak",
"10.66.66.5": "sevda",
"10.66.66.6": "wg-linux",
"10.66.66.7": "wg-win",
"10.66.66.8": "hakan",
"10.66.66.9": "canan",
"10.66.66.10": "didem",
"10.66.66.11": "levent",
"10.66.66.12": "toprak",
"10.66.66.13": "akin",
"10.66.66.14": "misafir1",
"10.66.66.15": "misafir2",
"10.66.66.16": "misafir3",
"10.66.66.17": "okul-1",
"10.66.66.18": "okul-2",
"10.66.66.19": "modem"
}
try:
# Ham WireGuard verisini al
output = subprocess.check_output(["sudo", "wg", "show", "wg0", "dump"]).decode("utf-8")
# Postgres Bağlantısı (Tailscale IP üzerinden)
conn = psycopg2.connect(
dbname="teslamate",
user="admin",
password="password",
host="100.114.186.10",
port="5432"
)
cursor = conn.cursor()
for line in output.splitlines():
parts = line.split("\t")
if len(parts) >= 6:
wg_ip = parts[3].split("/")[0]
rcvd = int(parts[5]) # İndirilen Byte
sent = int(parts[6]) # Yüklenen Byte
if wg_ip in kullanicilar:
isim = kullanicilar[wg_ip]
# Veri tabanına yaz
cursor.execute(
"INSERT INTO wg_kullanim_istatistikleri (kullanici_adi, wireguard_ip, indirilen_byte, yuklenen_byte) VALUES (%s, %s, %s, %s)",
(isim, wg_ip, rcvd, sent)
)
conn.commit()
cursor.close()
conn.close()
print("Islem Basarili: Veriler Postgres'e yazildi.")
except Exception as e:
print(f"Hata Olustu: {e}")
[!tip] Yeni Kullanıcı Ekleme Ağa yeni bir cihaz dahil olduğunda
sudo cat /etc/wireguard/wg0.confkomutuyla IP adresi öğrenilmeli ve yukarıdakikullanicilarsözlüğünevirgülile alt satır olarak eklenmelidir.
3. Otomasyon (Cron Job)
Betiğin her 5 dakikada bir arka planda sessizce çalışması için Linux zamanlayıcısına (Cron) şu görev tanımlanmıştır:
- Komut:
crontab -e - Eklenen Satır:
*/5 * * * * /usr/bin/python3 /home/ubuntu/wg_to_postgres.py
4. Grafana Görselleştirme Panelleri
Grafana üzerinde mevcut olan TeslaMate veri kaynağı (Data Source) ortak kullanılarak tüm grafikler tek bir "Dashboard" altında toplanmıştır.
📊 A. Ana Detay Tablosu (WireGuard Panel)
Kullanıcıların harcamalarını alt alta dizer, zaman filtresine göre tüketimi hesaplar ve son iki kayıt arasındaki farka bakarak kimlerin canlı trafikte olduğunu simgelerle gösterir.
- Panel Türü: Table (Tablo)
- SQL Sorgusu:
WITH zaman_sinirlari AS ( SELECT kullanici_adi, wireguard_ip, MIN(indirilen_byte) AS baslangic_indirilen, MAX(indirilen_byte) AS bitis_indirilen, MIN(yuklenen_byte) AS baslangic_yuklenen, MAX(yuklenen_byte) AS bitis_yuklenen, MAX(zaman) AS son_guncelleme FROM wg_kullanim_istatistikleri WHERE $__timeFilter(zaman) GROUP BY kullanici_adi, wireguard_ip ), son_iki_kayit AS ( SELECT kullanici_adi, indirilen_byte + yuklenen_byte AS toplam_byte, LEAD(indirilen_byte + yuklenen_byte) OVER (PARTITION BY kullanici_adi ORDER BY zaman DESC) AS onceki_toplam_byte FROM wg_kullanim_istatistikleri WHERE zaman >= NOW() - INTERVAL '30 minutes' ) SELECT z.kullanici_adi AS "Kullanıcı", z.wireguard_ip AS "IP Adresi", ROUND((z.bitis_indirilen - z.baslangic_indirilen) / 1048576.0, 2) AS "İndirilen (MB)", ROUND((z.bitis_yuklenen - z.baslangic_yuklenen) / 1048576.0, 2) AS "Yüklenen (MB)", ROUND(((z.bitis_indirilen - z.baslangic_indirilen) + (z.bitis_yuklenen - z.baslangic_yuklenen)) / 1048576.0, 2) AS "Toplam Veri (MB)", CASE WHEN (SELECT toplam_byte FROM son_iki_kayit s WHERE s.kullanici_adi = z.kullanici_adi LIMIT 1) > COALESCE((SELECT onceki_toplam_byte FROM son_iki_kayit s WHERE s.kullanici_adi = z.kullanici_adi LIMIT 1), 0) THEN '🟢 Aktif' ELSE '🔴 Boşta' END AS "Durum", TO_CHAR(z.son_guncelleme, 'DD.MM.YYYY HH24:MI') AS "Son Görülme" FROM zaman_sinirlari z ORDER BY "Toplam Veri (MB)" DESC;
🔢 B. Üst Hızlı Özet Kartları (Stat Panels)
Ekranın en üst kısmına yan yana dizilmesi gereken performans kartlarının sorguları:
1. Toplam Tüketim (GB)
- Panel Türü: Stat
- Unit: Data ➔ Gigabytes (GB)
WITH zaman_sinirlari AS ( SELECT kullanici_adi, MIN(indirilen_byte) AS baslangic_indirilen, MAX(indirilen_byte) AS bitis_indirilen, MIN(yuklenen_byte) AS baslangic_yuklenen, MAX(yuklenen_byte) AS bitis_yuklenen FROM wg_kullanim_istatistikleri WHERE $__timeFilter(zaman) GROUP BY kullanici_adi ) SELECT SUM((bitis_indirilen - baslangic_indirilen) + (bitis_yuklenen - baslangic_yuklenen)) / 1073741824.0 AS "value" FROM zaman_sinirlari;
2. Anlık Aktif Kullanıcı Sayısı
- Panel Türü: Stat (Renk: Yeşil)
WITH SiraliKayitlar AS ( SELECT kullanici_adi, (indirilen_byte + yuklenen_byte) AS toplam_byte, ROW_NUMBER() OVER (PARTITION BY kullanici_adi ORDER BY zaman DESC) AS rn FROM wg_kullanim_istatistikleri WHERE zaman >= NOW() - INTERVAL '15 minutes' ) SELECT COUNT(*) AS "value" FROM ( SELECT kullanici_adi, MAX(CASE WHEN rn = 1 THEN toplam_byte ELSE -1 END) AS son_durum, MAX(CASE WHEN rn = 2 THEN toplam_byte ELSE -1 END) AS onceki_durum FROM SiraliKayitlar WHERE rn <= 2 GROUP BY kullanici_adi ) kiyaslama WHERE son_durum != onceki_durum AND son_durum > 0;
3. Ağın Şampiyonu (En Çok Harcayan)
- Panel Türü: Stat ➔ Format: Table
WITH zaman_sinirlari AS ( SELECT kullanici_adi, MIN(indirilen_byte + yuklenen_byte) AS baslangic, MAX(indirilen_byte + yuklenen_byte) AS bitis FROM wg_kullanim_istatistikleri WHERE $__timeFilter(zaman) GROUP BY kullanici_adi ) SELECT kullanici_adi || ' (' || ROUND((bitis - baslangic) / 1073741824.0, 2) || ' GB)' AS "value" FROM zaman_sinirlari ORDER BY (bitis - baslangic) DESC LIMIT 1;
4. Toplam İndirme & Yükleme (Ayrı Kartlar)
- Download Sorgusu: (Unit: GB)
SELECT SUM(MAX(indirilen_byte) - MIN(indirilen_byte)) / 1073741824.0 FROM wg_kullanim_istatistikleri WHERE $__timeFilter(zaman) GROUP BY kullanici_adi; - Upload Sorgusu: (Unit: GB)
SELECT SUM(MAX(yuklenen_byte) - MIN(yuklenen_byte)) / 1073741824.0 FROM wg_kullanim_istatistikleri WHERE $__timeFilter(zaman) GROUP BY kullanici_adi;
⚠️ Kritik Güvenlik ve Ağ Notları
[!warning] Modem (Keenetic) Yönlendirme Uyarısı Modemi yedek olarak WireGuard ağına bağlarken Peer ayarlarındaki
AllowedIPskısmına kesinlikle0.0.0.0/0yazılmamalıdır. Aksi halde modemin DNS yapısı tıkanır ve tüm evin internet erişimi kesilir. Modeme güvenli erişim için bu değer sadece10.66.66.0/24olmalıdır. (Ben bu ayarı yapmadım galiba)[!success] Gizlilik Beyanı Bu sistem şifreli tünelden geçen paketlerin sadece boyutunu (Byte) tartar, içeriğini analiz etmez. Kullanıcıların hangi web sitelerine veya uygulamalara girdiğini loglamaz. Gizlilik dostu bir izleme panosudur.