rspamd'de Davranışa Uyarlanabilir Spam Skorlaması: ratelimit ve neural Modüllerini Birbirine Bağlamak
Sabit sembol skorları aynı sembol setini her gönderende aynı sayar; oysa BAYES_SPAM + MIME_HTML_ONLY üçlüsü kimi gönderende spam, kiminde newsletter'dır. rspamd'nin ratelimit modülünü davranış sensörüne, neural modülünü de o davranışı öğrenen katmana çevirip Redis üzerinden bağlayarak elle skor tuning yapmayı bırakın — gerçek config, eşik ve komutlarla.
EvilMail Team23 Temmuz 202613 dk okuma
Bir gönderende BAYES_SPAM, MIME_HTML_ONLY ve R_SUSPICIOUS_URL aynı anda düşüyor, toplam skor 6.9'a çıkıyor ve add_header action tetikleniyor. Sorun şu: bu tam üçlü, kupon fişi atan meşru bir SaaS newsletter'ında da düşüyor, saatte 4000 mail fırlatan bir snowshoe kampanyasında da. Statik metric skor tablosu ikisini ayıramaz, çünkü tabloya göre MIME_HTML_ONLY = 0.2 her mesajda 0.2'dir. Sembolün değeri gönderenin davranışından bağımsızdır.
Klasik refleks yeni sembol eklemek ya da mevcut ağırlıkları elle kurcalamaktır. Her ikisi de aynı hataya düşer: kararı hâlâ sabit bir sayıya bağlıyorsunuz. Doğru hamle sembol setini değiştirmek değil, karar ağırlığını davranışa bağlamak. rspamd'de bunun iki parçası hazır duruyor — ratelimit davranışı ölçen sensör, neural ise o davranışı sembol vektörüne katıp kendi ağırlıklarını yeniden öğrenen katman. İkisini Redis üzerinden birbirine bağladığınızda elle skor tuning'i bırakır, gönderene göre uyarlanan bir skorlama hattı kurarsınız.
Peşinen bir uyarı: bu bir "yapay zeka spam'i çözer" yazısı değil. rspamd'nin ANN'i sıfırdan içerik analizi yapmaz; sadece mesajda düşen sembollerin kombinasyonunu yeniden ağırlıklandırır. Çöp girdiyle overtrain edilirse filtrenizi bozar. Aşağıdaki her eşik bunu göz önünde tutarak seçildi.
Ratelimit: davranışı sayıya çeviren katman
Çoğu kişi ratelimit'i bir spam bloklayıcı sanır. Değil. O bir leaky-bucket sensörü: "bu gönderen / IP / kullanıcı ne hızda davranıyor" sinyalini üretir. Token bucket semantiği net — burst anlık kapasite, rate ise kovadan token'ların sızma hızı. Kova dolup taşarsa mesaj geciktirilir veya reddedilir.
/etc/rspamd/local.d/ratelimit.conf içinde selector tabanlı bucket tanımlanır. Selector, kovanın kime göre sayılacağını belirler: user (kimlik doğrulamış gönderen), from_tld, rcpt, ip gibi.
Ratelimit Redis olmadan çalışmaz — bucket durumu orada tutulur. /etc/rspamd/local.d/redis.conf içinde servers = "127.0.0.1:6379"; yeterli. Bucket anahtarları RL_<bucket>_<hash> formatında hash'lenir; redis-cli --scan --pattern 'RL_*' ile canlı görebilirsiniz.
Kilit nokta: default davranışta ratelimit yalnızca geciktirir veya reddeder — skora hiçbir şey katmaz. Bir gönderen hızlıysa mesaj bekletilir ama neural ağ bunu asla göremez, çünkü hız sinyali skor uzayında yaşamıyor. Biz onu skora çevireceğiz.
Ratelimit çıktısını skora bağlamak
Amacımız hızlı gönderene hard rate uygulamak değil — skor uzayına bir işaret bırakmak ki ANN onu girdi olarak görebilsin. Ratelimit bir bucket'ı taşırdığında RATELIMIT sembolünü mesaja iliştirir; küçük bir Lua kuralıyla bu ikili sinyali kendi davranış sembolümüze çeviririz.
rspamd.conf.local içinden dofile ile yüklenen bir kural iş görür:
lua
-- /etc/rspamd/lua/sender_rate.lua
-- ratelimit prefilter'dan sonra çalışır; RATELIMIT sembolü varsa
-- davranış sinyalini skor uzayına taşıyıp ANN'e girdi yaparız
rspamd_config.SENDER_RATE_HIGH = {
callback = function(task)
if task:has_symbol('RATELIMIT') then
return true, 1.0
end
return false
end,
score = 2.5, -- düşük; asıl karar ANN'e kalacak
description = 'Gönderim hızı bucket kapasitesinin üstünde',
group = 'behaviour',
}
score = 2.5 bilinçli olarak düşük. Amaç bu sembolle mesajı tek başına reddetmek değil; onu ANN'in girdi vektörüne sokmak. Neural ağ "yüksek hız + şu içerik desenleri birlikte gelince spam" ilişkisini kendisi öğrenecek. Sembolü group = 'behaviour' altında toplamak, sonradan rspamc stat çıktısında davranış sinyallerini ayrı izlemenizi kolaylaştırır. Kuralın ratelimit'ten sonra çalışması için RATELIMIT sembolüne bağımlılık verebilir ya da normal sembol sırasına güvenebilirsiniz — ratelimit prefilter aşamasında koştuğu için sembol callback anında hazırdır.
ANN'in ne yaptığını netleştirelim. Mesajda düşen sembollerin bir vektörünü alır — her sembol için 0/1 ya da skor değeri — ve bu vektörü eğittiği ağdan geçirip NEURAL_SPAM veya NEURAL_HAM üretir. İçeriği okumaz, URL çözmez, dil analizi yapmaz. Sadece "hangi semboller birlikte düştüğünde sonuç spam çıktı" örüntüsünü öğrenir. Yani mevcut sembollerinizin üstüne oturan bir yeniden-ağırlıklandırıcıdır.
hcl
# /etc/rspamd/local.d/neural.conf
enabled = true;
train {
max_trains = 5000; # ağ başına eğitim örneği tavanı
max_usages = 40; # bir vektör kaç kez kullanılabilir
max_iterations = 25; # eğitim iterasyonu
learning_rate = 0.01;
spam_score = 8; # >=8 verdikt = güvenli spam örneği
ham_score = -2; # <=-2 verdikt = güvenli ham örneği
train_prob = 1.0; # örneklem seyreltme (1.0 = hepsi)
}
symbol_spam = "NEURAL_SPAM";
symbol_ham = "NEURAL_HAM";
max_inputs = 200; # >0 => PCA ile boyut indirgeme aktif
ann_expire = 100800; # ~28 saat sonra ağ eskir, yenisi eğitilir
roc_enabled = true; # ROC ile eşik kalibrasyonu
Birkaç değer hayati. max_inputs = 200 PCA'yı devreye sokar: yüzlerce sembollü seyrek bir vektörü sıkıştırıp ağın ezberlemesini değil genellemesini sağlar. spam_score = 8 ve ham_score = -2 eğitim örneklerinin hangi güven seviyesinden seçileceğini belirler — bunlar overtraining'e karşı ilk savunma hattınız. ann_expire ile ağ periyodik olarak taze veriyle yeniden eğitilir, böylece geçen ayın spam desenine saplanıp kalmaz.
Bağımlılık notu: neural modülü kann kütüphanesine karşı derlenmiş bir rspamd binary'si ister. Dağıtım paketlerinin çoğunda gelir, ama kendi derlemenizi yapıyorsanız kann'ın linklendiğinden emin olun; yoksa neural modülü sessizce yüklenmez.
Az önce bastığımız SENDER_RATE_HIGH sembolünü bu vektöre dahil ettiğinizde işin özü ortaya çıkar: ANN artık içerik sembollerini davranış sembolüyle birlikte görür ve "burst hızı + bu içerik = spam" bağını kendi ağırlığıyla öğrenir. Siz hiçbir yerde if hız yüksek then skor += 3 yazmazsınız.
Eğitim döngüsü, profiller ve overtraining
ANN nasıl beslenir? Otomatik olarak. Bir mesaj spam_score eşiğinin (8) üstünde final skor aldıysa, o mesajın sembol vektörü pozitif eğitim örneği olarak Redis'e yazılır; ham_score eşiğinin (-2) altındaysa negatif örnek olur. Ayrıca rspamc learn_spam < msg ve rspamc learn_ham < msg ile elle besleyebilir, Bayes ve fuzzy geri beslemesini de dolaylı katkı olarak kullanabilirsiniz.
Trafiği yüksek bir sunucuda train.max_usages ve train_prob ile örneklem seyreltirsiniz — her mesajı eğitime sokmak ağı gürültüyle boğar. max_iterations = 25 çoğu kurulum için yeter; artırmak overfitting riskini büyütür.
En kritik uyarı: kirli otomatik eğitim ağı bozar.spam_score eşiğini 4'e çekerseniz, greylist sınırındaki belirsiz mesajlar spam örneği sayılır ve ağ yanlış öğrenir. Eşiği yüksek (8 / -2) tutmak, yalnızca yüksek güvenli verdiktleri eğitime sokar. roc_enabled = true ile rspamd, ROC eğrisi üzerinden NEURAL_SPAM eşiğini false positive oranını gözeterek kalibre eder. ann_expire de eski, kaymış ağı otomatik düşürür.
Eğitim durumunu Redis ve log'tan izleyebilirsiniz:
bash
redis-cli --scan --pattern 'rn_*'
# rn_default_..._ann -> serialize edilmiş ağ
# rn_default_..._spam -> biriken spam vektörleri
# rn_default_..._ham -> biriken ham vektörleri
grep 'neural' /var/log/rspamd/rspamd.log | tail
# ... neural: ANN <digest> trained; 5000 spam, 4870 ham; MSE 0.021
trained satırını görene kadar ağ NEURAL_* sembolü basmaz. Yeni bir kurulumda birkaç bin mesaj birikene dek sabırlı olun.
İkisini birleştirmek: uyarlanabilir hat
Tam akış şöyle işler: mesaj gelir → içerik sembolleri + SENDER_RATE_HIGH davranış sembolü çıkarılır → vektör PCA'dan geçer → ANN NEURAL_SPAM/NEURAL_HAM üretir → metric toplayıcı hepsini toplar → action seçilir. Üstüne reputation modülünü (ip_reputation, url_reputation) ayrı bir katman olarak koyabilirsiniz; o da davranış sinyaline benzer şekilde geçmiş itibarı skora yansıtır.
Aynı içeriğin iki gönderende neden farklı final skor aldığını somut görün:
İçerik birebir aynı. Tek fark gönderim davranışı: yavaş gönderende davranış sembolü hiç düşmedi, ANN geçmiş örüntüden NEURAL_HAM -0.8 verdi, final 2.1'de kaldı ve hiçbir action tetiklenmedi. Ani burst yapan gönderende SENDER_RATE_HIGH düştü, ANN bu kombinasyonu spam olarak öğrenmiş olduğu için NEURAL_SPAM +3.4 bastı, final 7.6'ya fırladı. Siz hiçbir sabit ağırlığı elle değiştirmediniz.
İzleme ve tuning
Efektif config'i her zaman canlı sunucudan doğrulayın — local.d dosyalarının gerçekten yüklendiğini varsaymayın:
bash
rspamadm configdump ratelimit # etkin bucket/selector'lar
rspamadm configdump neural # train bloğu, max_inputs, roc
rspamc stat | grep -i neural # NEURAL_SPAM/HAM tetiklenme sayısı
redis-cli --scan --pattern 'RL_*' | head # aktif bucket'lar
redis-cli --scan --pattern 'rn_*' # ANN durumu
systemctl reload rspamd # config değişikliği sonrası
Web UI'da (:11334) sembol frekans grafiğinde NEURAL_SPAM/NEURAL_HAM oranına bakın. Sağlıklı bir ağda ikisi de düzenli düşer; sadece biri düşüyorsa eğitim dengesizdir.
Ağ öğrenmiyorsa checklist: (1) yeterli train birikmiş mi — max_trains'e ulaşmadan ağ eğitilmez; (2) güven eşiği çok mu dar — spam_score/ham_score aralığı gerçekte hiç örnek üretmiyor olabilir; (3) Redis erişimi — neural ve ratelimit aynı Redis'i görüyor mu.
False positive artarsa panik yapıp eşik kurcalamayın. Önce ağı sıfırlayın ve yeniden eğitin:
bash
redis-cli --scan --pattern 'rn_default_*' | xargs redis-cli DEL
systemctl reload rspamd # temiz veriyle yeniden eğitim başlar
Kurulum kontrol listesi
Redis ayakta ve tek instance — hem ratelimit.conf hem neural.conf aynı redis.conf'u kullanmalı.
`ratelimit.conf`'ta selector tanımlı — user/from_tld/ip, trafiğinize uygun olan; max_delay ile soft davranış.
Davranış sembolü basılıyor — SENDER_RATE_HIGH (score ~2.5, düşük) skor uzayında yaşıyor ki ANN girdi olarak görsün.