# Güvenlik Duvarı

### IP Engelleri Sunucu Genelidir

Her engel — Güvenlik Duvarı sayfasından ya da hesap düzeyi uçlardan — sunucu güvenlik duvarında (Debian'da UFW, RHEL'de firewalld) tek bir kuraldır ve sunucudaki her siteyi etkiler. Hesap bazlı bir kapsam yoktur; hesap düzeyi uçlar bunu `warnings` ile söyler ve denetim günlüğüne `scope: server` yazar. Kiracılar engel ekleyemez, kaldıramaz, listeleyemez.

API, isteğin geldiği adresi kapsayan bir engeli reddeder (`SELF_LOCKOUT`); böylece operatör paneli kendi üzerine kapatamaz.

Bir engel iki yere yazılır: paket filtresine kaynak deny olarak ve fail2ban'ın kullandığı HTTP katmanı listesine (`/etc/whost/http-banlist`, kurulu her web sunucusuna işlenir); böylece CDN üzerinden gelen trafik için de geçerlidir. UFW'de engelle birlikte verilen açıklama saklanır ve listede gösterilir; firewalld (RHEL ailesi) açıklamayı saklamaz, orada liste açıklamasız görünür. İzin listesindeki bir adresi engellemek `409 IP_WHITELISTED` ile reddedilir — allow kuralı deny'ın üstünde kalırdı — önce adresi izin listesinden çıkarın. Engeli kaldırmak yalnız deny'ı ve HTTP katmanı girdisini siler, adresin izin listesi kuralına asla dokunmaz; var olmayan bir engeli kaldırmak `404 NOT_FOUND`, hesap düzeyi uçlar var olmayan bir hesap için `404 ACCOUNT_NOT_FOUND` döndürür.

**Tüm Banları Temizle** panelin üretebildiği her engeli kaldırır — düz ve port kapsamlı kaynak deny'lar, HTTP katmanı listesi, hız sınırı ban set'leri ve fail2ban banları — ve katman başına sayaçları döndürür (`ufw_rules`, `http_bans`, `rate_limit_bans`, `fail2ban_jails`, `removed`). Güvenlik günlüğüne dokunmaz; Güvenlik Günlükleri sekmesindeki **Günlüğü Temizle** (`DELETE /firewall/logs`, denetim `firewall_logs_cleared`) olay tablolarını boşaltır.

### Sistem Kuralları

UFW (Debian) veya firewalld (RHEL) soyutlaması. Her kuralı, allow/deny/limit/reject'i ve API'nin kapatmayı ya da genel olarak reddetmeyi kabul etmediği korumalı portları (`PROTECTED_PORTS` ve Ayarlar'da belirlenen SSH portu) listeler (böylece operatör SSH'tan, HTTP/HTTPS'ten veya agent'tan kendini dışarıda bırakamaz) — korumalı bir portu **kapsayan aralık** da reddedilir ve kural formu böyle bir aralık için tam portla aynı onayı ister. Liste kaynak kapsamlı kuralları da kaynağı, açıklaması (yalnız UFW'de — firewalld açıklama saklamaz) ve `port-protokol--kaynak` biçimindeki id'siyle taşır. Düzenleme kuralı değiştirir ve yenisi reddedilirse eskisini geri koyar; güvenlik duvarının taşımadığı bir kuralı düzenlemek ya da silmek `404 NOT_FOUND` döndürür (ufw'nin "non-existent rule" yanıtı okunur, çıkış kodu değil).

**İzin listesi (whitelist):** izin listesindeki adres her porttan geçer ve otomatik banlardan muaftır. Liste her kayıt için `applied` gösterir — güvenlik duvarında kural gerçekten var mı — ve agent açılışta eksik kuralları yeniden kurar; böylece bir güvenlik duvarı sıfırlaması yalnız kâğıt üzerinde var olan kayıtlar bırakmaz. Kayıt yalnız güvenlik duvarı kuralı kabul ettikten sonra yazılır. Kuralı eksik olan kayıt listede **Kural eksik** olarak işaretlenir; adresi yeniden eklemek kuralı yeniden kurar (verilmişse açıklamayı da günceller).

**Hız sınırı kuralları:** eşik, bir adresin pencere içinde açtığı yeni bağlantıları sayar — paket filtresi HTTP isteklerini göremez, bu yüzden açık tutulan bir bağlantının taşıdığı istekler bir kez sayılır. Eşiği aşan adres yasak süresi boyunca yasaklanır ve yasak bitene kadar sunucunun bütün portlarına erişemez. Kurallar kendi zincirinde (`WHOST-RATELIMIT`) durur; zincire INPUT'un başından, ufw / firewalld'den önce atlanır, böylece sunucu güvenlik duvarının geçirdiği trafiği görür; sunucunun kendi trafiği (loopback) ve güvenlik duvarı izin listesindeki adresler hiçbir zaman sayılmaz ve yasaklanmaz. Zincir yalnız en az bir kural etkinken vardır. Kurallar IPv4'e uygulanır. Birden fazla portu olan bir kural (`80,443`) tek bir multiport eşleşmesiyle uygulanır; kural başına en çok 15 port/aralık ve port filtresi için `tcp` ya da `udp` gerekir. Kural yalnız çekirdek nesnelerini taşıdığında kaydedilir: reddedilen kural çekirdeğin gerekçesiyle `500 RATE_LIMIT_APPLY_FAILED` döndürür ve geriye hiçbir şey bırakmaz; çekirdeğin reddettiği bir güncelleme önceki kuralı geri koyar. Kural deposu yalnız root'a açıktır; bir kuralın ban set'i `WHOST_RL_<KURAL ID>`'dir — kural id'si büyük harfle. Hedefsiz unban adresi kaç ban set'inin taşıdığını söyler; IP olmayan bir adres `422`, bilinmeyen kural `404` alır.

### Fail2Ban

Jail listesi (fail2ban'ın yüklediği her jail + panelin devre dışı bıraktıkları), ban listesi, manuel ban/unban, jail seviyesinde etkinleştirme/devre dışı bırakma, jail'in ban süresi / bulma süresi / maksimum deneme değerleri ve beyaz liste (`ignoreip`).

**Jail'ler.** Liste yüklü jail'leri daemon'dan, devre dışı olanları yapılandırma dosyalarından (`jail.local`, `jail.d/*`) yükleneceği filtre, log yolu ve ayarlarla okur. Bir jail'i kapatmak onay ister — mevcut banları kaldırılır — ve panelin override dosyasını yazar (`jail.d/<jail>.local`: `enabled` + **Düzenle** ile verilen ban süresi / bulma süresi / maksimum deneme); sonraki bir düzenleme adını vermediği değerleri korur, jail'i kapatıp açmak da korur. Ban süresi 60–604800 s, bulma süresi 60–86400 s, maksimum deneme 1–100. Jail listesi jail başına fail2ban-client'a sorar; çok jail'li bir sunucuda okuma birkaç saniye sürer.

**Banlar.** `allports` jail'lerinde (sshd, postfix, dovecot, pure-ftpd, recidive) ban paket filtresinde reddir; HTTP'ye bakan jail'lerde (`whost-<kullanıcı>-webscan`, `nginx-http-auth`, `whost-agent`) aşağıdaki HTTP katmanı listesinden geçer ve orada ağ (CIDR) de kabul edilir. Beyaz listenin yok saydığı bir adresi banlamak `409 IP_WHITELISTED` ile reddedilir; banlı olmayan bir adresin banını kaldırmak `404 NOT_FOUND` alır. **Tümünü Kaldır** her jail'deki her banı kaldırır. İsteğin geldiği adres — ya da onu kapsayan bir ağ — banlanamaz (`422 SELF_LOCKOUT`): ban, paneli isteyen operatörün üzerine kapatırdı.

**Agent jail'i.** `whost-agent`, agent günlüğünden başarısız yönetici ve client girişlerini ve reddedilen API imzalarını sayar. Giriş adı oraya kaçışlı tek bir alan olarak yazılır; kendi satırını ekleyemez ve sayım denemenin geldiği adrese gider.

**Beyaz liste.** Her jail için tek liste: eklenen adres yüklü her jail tarafından hemen yok sayılır, `jail.local`'daki `ignoreip`'e yazılır ve taşıdığı ban varsa kaldırılır. Listede olmayan bir adresi silmek `404 NOT_FOUND` alır. `jail.d/*.conf` dosyalarına elle yazılan kayıtlar panelde gösterilmez ve düzenlenmez.

**Saldırı altında modu** sshd'yi (bantime 86400, maxretry 3, findtime 300) panelin jail yazımlarının tetiklediği reload'larda korunan bir `jail.d/whost-attack-mode.local` override dosyasıyla sıkılaştırır; mod kapatılınca dosya silinir.

**Agent'ın kendi jail'i (`whost-agent`)** `/var/log/whost/agent.log`'u agent'ın her açılışta şablonundan ürettiği filtreyle okur (başarısız admin ve client girişleri, geçersiz API imzaları); eski bir installer'ın yazdığı filtre değiştirilir.

**Kullanılan uç noktalar:** `GET /fail2ban/status`, `GET /fail2ban/jails` + `GET/PUT /fail2ban/jails/{jail}` + `POST /fail2ban/jails/{jail}/{enable,disable}`, `GET /fail2ban/banned`, `POST /fail2ban/ban`, `DELETE /fail2ban/ban/{jail}/{ip}`, `POST /fail2ban/unban-all`, `GET/POST /fail2ban/whitelist`, `DELETE /fail2ban/whitelist/{ip}`.

**Hesap başına web jail'i (`whost-<kullanıcı>-webscan`).** Her hosting hesabı kendi erişim günlükleri üzerinde bir jail alır (`whost-web-scan` filtresi: 4xx yanıt patlaması). Yakalanan adres paket filtresinde değil **HTTP katmanında** engellenir: `whost-http-deny` aksiyonu tek bir liste (`/etc/whost/http-banlist`) tutar ve bunu kurulu her web sunucusuna (nginx, Apache, OpenLiteSpeed, LiteSpeed Enterprise) işler; ban, public portu hangi sunucu tutuyorsa orada geçerlidir. Cloudflare arkasında engellenen adres ziyaretçinin kendi adresidir: kurucu nginx'in bu adresi Cloudflare'in başlığından geri almasını sağlar (`/etc/nginx/conf.d/whost-cloudflare-realip.conf`). Başka bir CDN arkasında ya da public portu Apache, OpenLiteSpeed veya LiteSpeed Enterprise tutuyorsa web sunucusu kenar adresini görür — o CDN'in aralıklarını `ignoreip`'e ekleyin. Aksiyonun kendisi yalnız isteği kuyruğa yazar (`/var/lib/fail2ban/whost-http-ban/queue`; SELinux'lu sunucularda kısıtlı fail2ban'ın yazabildiği tek yer); `whost-http-ban.path` systemd birimi kuyruğu root olarak bir saniye içinde uygular, yani ban web sunucusunda fail2ban çağrısının içinde değil kısa bir gecikmeyle görünür. `whost-http-ban list` uygulanan listeyi yazdırır; `whost-http-ban sync` elle yapılan bir web sunucusu yapılandırma değişikliğinden sonra listeyi yeniden uygular; listeyi reddeden web sunucusunu `journalctl -u whost-http-ban-apply` gösterir.

### WAF (ModSecurity)

**ModSecurity WAF** sayfası (Güvenlik → WAF) motoru (kurulu, aktif, mod, OWASP CRS, paranoya seviyesi, denetim günlüğü, kural sayıları), yapılandırma formunu, CRS kural listesini ve denetim günlüğünü gösterir.

**Yapılandırma.** Motor modu `on` (engelle), `detection_only` (yalnız kaydet, engelleme) ya da `off`; paranoya seviyesi 1–4; denetim günlüğü açık/kapalı. Üretilen dosyalar değerler kalıcılaşmadan önce web sunucusunun kendi yapılandırma testinden geçirilir; değişiklik web sunucusunu yeniden yükler, hiçbir şeyi değiştirmeyen kayıt yüklemez. **Yapılandırmayı Test Et** `nginx -t` (nginx + Apache sunucularda `apachectl configtest`) koşar; böyle bir testi olmayan web sunucusunda `409 WAF_TEST_UNAVAILABLE` alır. WHost ModSecurity'yi yalnız nginx katmanında uygular; yalnız Apache ve OpenLiteSpeed sunucularda sayfa bunu söyler, ayarlar kaydedilir ama trafiğe uygulanmaz.

**Yasaklı başlıklar.** CRS ayarı `Content-Encoding`, `Proxy`, `Lock-Token`, `Content-Range` ve `If` istek başlıklarını yasaklar, `Accept-Charset`'i yasaklamaz (CRS 4 bu başlığa yalnız paranoya seviyesi 2'den itibaren bakar): arama motoru ve yapay zekâ tarayıcıları bu başlığı gönderir. Mevcut kurulum listeyi bir sonraki agent açılışında, paylaşılan kural setiyle aynı `nginx -t` denetimli adımda alır; kendi belirlediğiniz liste (`/etc/modsecurity/crs/crs-setup.conf` içinde kural `900250`) korunur.

**Argüman sınırı.** CRS ayarı bir isteğin 255 yerine 1.000 argüman taşımasına izin verir (kural `900300`, `tx.max_num_args` — PHP'nin kendi `max_input_vars` varsayılanı): 255 sınırında çok dilli yönetim formları, örneğin birkaç yüz alanlı bir WISECP ürün ya da eklenti düzenleme formu, `403` ile reddedilir (kural `920380`). Hâlâ eski değeri taşıyan mevcut kurulum yeni değeri bir sonraki agent açılışında, aynı `nginx -t` denetimli adımda alır; kendi belirlediğiniz değer korunur.

**Yeni kurulumun motor modu.** Yeni kurulum `detection_only` ile başlar: istekler denetim günlüğüne yazılır, hiçbiri reddedilmez. Bu sayfadan `on`'a ancak denetim günlüğü sitelerinizin seyrek isteklerini — ödeme sağlayıcısı webhook'ları, iadeler, 3-D Secure dönüşleri, kart kaydı, API ve lisans çağrıları — onları reddedecek bir eşleşme olmadan gösterdikten sonra geçin. Mevcut kurulum kendi modunu korur.

**İstek gövdeleri.** XML ve JSON istek gövdeleri kendi işleyicileriyle ayrıştırılır (`/etc/modsecurity/modsecurity.conf` içinde kural `200000` ve `200001`), böylece her JSON değeri ayrı ayrı denetlenir. Mevcut kurulum iki kuralı bir sonraki agent açılışında, aynı `nginx -t` denetimli adımda alır; kendi yazdığınız JSON kuralı (`id:200001`) korunur.

**Aktif, nginx'in kuralları tuttuğu anlamına gelir.** Sayfa WAF'ı yalnız nginx kural setini yüklediğinde *Aktif* gösterir: bağlayıcı modül ve kurulum aracıyla agent'ın yalnız `nginx -t` kural setini kabul ettikten sonra tuttuğu ortak dahil dosyası `/etc/nginx/conf.d/whost-modsecurity.conf`. nginx kural setini yüklemediği sürece başlık *Pasif* yazar ve **WAF kural seti yüklü değil** notu, motor açık olsa da isteklerin denetlenmediğini söyler; agent her başlangıçta yeniden dener ve nedenini `/var/log/whost/agent.log`'a yazar. Ubuntu 22.04'te bir CRS dosyası kural setinin dışında kalır — bkz. [Bilinen kısıtlar](known-limitations.md).

**Kurallar.** Yüklü kural setinin id taşıyan her kuralı, varsa mesajıyla listelenir. Kapatılan kural `/etc/modsecurity/disabled-rules.json`'a ve `modsecurity.conf`'a `SecRuleRemoveById` olarak yazılır, web sunucusu yeniden yüklenir; kural setinde olmayan bir id `404 WAF_RULE_NOT_FOUND` alır; zaten geçerli olan duruma çevirmek hiçbir şey yazmaz.

**Denetim günlüğü.** `/var/log/modsecurity/audit.log`'un en yeni kayıtları: istemci adresi, host, URI, ilk eşleşen kural, önem ve isteğin *engellendiği*, *tespit edildiği* (yalnız algılama modu) ya da yalnız *kaydedildiği* (hiçbir kuralın eşleşmediği bir 4xx/5xx). libmodsecurity dosyayı hiç yeniden açmadığından rotasyon dosyayı kopyalayıp sıfırlar (`copytruncate`); agent bu logrotate bloğunu her açılışta yazar. **Otomatik Yenile** 10 s'de bir sorar; **Daha Fazla Yükle** pencereyi 1000 kayda kadar genişletir.

**Hesap düzeyi WAF** (API ve bayinin alt hesap sayfası; admin sayfası yok): `GET /accounts/{username}/waf/status` ve `PUT /accounts/{username}/waf/toggle` bir hesap için WAF'ı kapatır/açar: durum `/etc/modsecurity/accounts/<kullanıcı>.json`'a yazılır, hesabın kural dosyası yeniden üretilir ve hesabın her vhost'u yeniden render edilir ki `modsecurity` anahtarı durumu izlesin (WAF kapalıyken render edilmiş bir vhost, açılınca yeniden korunur); `POST /accounts/{username}/waf/rules/exclude` ve `DELETE /accounts/{username}/waf/rules/exclude/{rule_id}` (URI kapsamlı olan için `?uri=`; URI verilmezse hesap geneli girdi, o yoksa tek kalan URI kapsamlı girdi silinir — birden çok URI kapsamlı girdi URI ister, `422`) bir CRS kuralını hesap için genel ya da tek URI'de hariç tutar; `GET /accounts/{username}/waf/audit-log` Host başlığı hesabın alan adlarından birini taşıyan kayıtları listeler. Olmayan hesap `404 ACCOUNT_NOT_FOUND` alır. `modsecurity.per_account_overrides` `false` iken üç yazma (toggle, exclude, remove) `409 FEATURE_DISABLED` alır ve hiçbir şey yazılmaz; okumalar yanıt vermeye devam eder. Hesabın kural dosyası (`/etc/modsecurity/accounts/<kullanıcı>.conf`) üretilen bir dosyadır: her değişiklikte ve agent'ın her açılışında durum dosyasından yeniden render edilir, bu yüzden içine elle yazılan kural düşer. Bir agent açılışı böyle satırlar taşıyan bir dosyayı yeniden yazdığında agent logu hesap başına bir WARNING taşır (kaç satırın düştüğü ve önceki dosyanın tutulduğu klasör, `/var/lib/whost/nginx-modsec-shared-<damga>/`) ve admin panelinde hesapları adıyla sayan bir bildirim görünür. Exclude uçlarının ifade edemediği sunucuya özgü kural (örneğin tek bir argümanı muaf tutan) `/etc/modsecurity/custom/<ad>.conf` dosyasına yazılır — ana WAF dosyası bu klasörü yükler ve agent oraya yazmaz; ekledikten sonra `nginx -t` koşup nginx'i yeniden yükleyin.

**Kullanılan uç noktalar:** `GET /waf/status`, `PUT /waf/config`, `GET /waf/rules`, `PUT /waf/rules/{rule_id}`, `GET /waf/audit-log`, `POST /waf/test`; yukarıdaki hesap rotaları.

### Saldırı Altında Modu

Sağ üst köşedeki toggle. **Otomatik Etkinleştir** anahtarı açıksa (varsayılan olarak kapalıdır) mod, tehdit puanı 5'e ulaşınca kendiliğinden devreye girer (FirewallLogService'in son engellemelere verdiği puanlama tarafından yönlendirilir); anahtar kapalıyken böyle bir puan yalnız *High Threat Level Detected* bildirimi üretir. sysctl sertleştirmesi `systemd-sysctl`'e `/etc/sysctl.d/90-whost-attack-mode.conf` drop-in'i ile verilir (agent `ProtectKernelTunables` ile çalışır, `/proc/sys`'i kendisi yazamaz); mod kapatılınca drop-in kaldırılır ve önceki değerler geri yazılır; `sysctl_hardening` yalnız en az bir değer gerçekten değiştiğinde bildirilir. Paket kuralları — SYN-flood limiti ve 80/443 connlimit'i — ilk `INPUT` kuralının atladığı, ufw zincirlerinin önündeki `WHOST-ATTACK` zincirindedir; içindeki her karar RETURN, DROP ya da REJECT'tir, yani flood denetimini geçen bir bağlantının nereye erişebileceğine yine güvenlik duvarının kendi politikası karar verir ve yönetim portları asla düşürülmez. Yeniden başlatma paket filtresini boşaltır ama mod açık kalır; ajan açılırken zinciri geri kurar. nginx'in real-ip proxy'si olarak güvendiği kaynaklar (`set_real_ip_from`, CDN aralıkları) bağlantı sınırından muaftır: tek bir kenar adresi tüm ziyaretçileri taşır, onu tek istemci saymak hepsini birden keserdi. Nginx `limit_req` ve daha sıkı Fail2Ban eşikleri seti tamamlar; kapatmada mod açılmadan önce okunan Fail2Ban değerleri geri yüklenir. Kart uygulanan korumaları listeler. Manuel mod yeniden başlatmalar arasında kalıcıdır; otomatik mod tehdit puanı düştüğünde devre dışı kalır. Zaten etkin bir modu etkinleştirmek (ya da etkin olmayanı kapatmak) `409 ATTACK_MODE_ACTIVE` / `ATTACK_MODE_INACTIVE` döndürür; her durum değişikliği yeni durumu `data` içinde döndürür.

### Güvenlik Günlükleri

**Güvenlik Günlükleri** sekmesi adres ve türe göre gruplanmış engelleme olaylarını — `count` engel sayısıdır; satırlar yük altında örneklenmişse dakikalık sayaçlardan alınır ve böyle bir grup *örneklenmiş* olarak işaretlenir — ve erişim günlüğü tarayıcısının bulduğu şüpheli istekleri gösterir. Süzgeçler: tam bir adres, adresin bir parçası (`0.2.1` kısmi eşleşmeyle daraltır; bir host'u adlandıramayan girdi `422` alır), engel türü (`rate_limit`, `under_attack`, `manual`, `autoban`), kategori ve ISO-8601 zaman damgası olarak `since` / `until`. Liste agent'ta sayfalanır (sayfa başına 100). Saat grafiği son 24 saati izleyicinin yerel saatinde gösterir; her saat vardır, boş saat sıfır okunur. **Banlı** rozeti yalnız adres şu anda banlıyken doğrudur — bir fail2ban jail'inde (her jail sorulur), HTTP katmanı listesinde ya da bir saatten genç bir otomatik banla. **Banı Kaldır & İzin Listesine Al** önce engeli kaldırır, sonra adresi izin listesine ekler; ikinci adım reddedilirse toast bunu söyler ve adres engelsiz ama güvenilmemiş kalır. **Yenile**, **TXT** dışa aktarma, **Günlüğü Temizle** (iki tabloyu boşaltır; denetim `firewall_logs_cleared`) ve **Tüm Banları Temizle** ikizi araç çubuğundadır. Saklama 24 saattir; 50.000 engelleme ve 10.000 şüpheli satırla sınırlıdır; temizlik silmelerini WAL checkpoint'inden önce commit eder, meşgul bir yazıcı yalnız checkpoint'i erteler. Güvenlik duvarı bildirimleri ortak bildirim servisi üzerinden `firewall` kategorisinde gider; operatörün e-posta ve panel tercihleri onlara da uygulanır.

**Kullanılan endpoint'ler:** `GET /firewall/status`, `GET/POST /firewall/rules` + `PUT/DELETE /firewall/rules/{rule_id}`, `GET/POST /firewall/blocked-ips` + `DELETE /firewall/blocked-ips/{ip}` + `POST /firewall/blocked-ips/clear-all`, `GET/POST /firewall/whitelist`, `GET/POST /firewall/rate-limits`, `POST /firewall/attack-mode/{enable,disable,auto-enable,auto-disable}`, `GET /firewall/logs/{stats,blocked,suspicious}`, `DELETE /firewall/logs`; hesap düzeyi `/accounts/{username}/firewall/blocked-ips` uçları aynı sunucu geneli kuralı uygular.

---
