Ele Geçirilmiş Hesabı IP Karalistelenmeden Yakalamak: rspamd ile Giden Trafiği Tarama
Gelen için mükemmel ayarladığın rspamd, giden trafikte işe yaramaz — çünkü ele geçirilmiş bir hesap geçerli DKIM ve SMTP AUTH ile gönderir, içeriği tertemizdir. Asıl imza davranışsaldır. Postfix'in giden yolunu ayrı bir rspamd politikasına sokup hesap bazlı ratelimit, reputation ve bileşik sinyallerle spam'i IP karalistelenmeden yakalamanın kurulum notları.
EvilMail Team23 Temmuz 202613 dk okuma
Saat 03:40. Nöbet telefonu, aynı /24'teki iki IP'nizin Spamhaus CSS'e düştüğünü haber veriyor. Log'lara bakıyorsunuz: faturasını üç aydır ödemeyen bir müşterinin parola123 kalibresinde parolaya sahip hesabı, gece boyunca 9.000 mesaj basmış. Hepsi geçerli DKIM imzalı, hepsi SPF PASS, hepsi 587 üzerinden düzgün SMTP AUTH ile. İçerik açısından her biri tertemiz.
Gelen taraf için haftalar harcayıp cilaladığınız rspamd bunların hiçbirini görmedi. Sebep basit: giden yol taranmıyordu. Bu yazı, o gecenin tekrarlanmaması için giden trafiği rspamd'a nasıl soktuğumuzun notları — evilmail.pro'nun giden altyapısında oturmuş, çalışan bir kurulumdan.
Neden gelen rspamd konfigürasyonu giden trafikte çöker
Gelen spam filtresinin tüm mantığı içerik ve köken şüphesi üzerine kuruludur: bu IP'nin reputation'ı ne, DKIM tutuyor mu, SPF hizalı mı, body Bayesian'a göre ne kokuyor. Ele geçirilmiş bir hesap bu sinyallerin hepsini meşru üretir. Saldırgan sizin altyapınızı, sizin selector'ınızla imzalanmış, sizin IP'nizden çıkan, kimliği doğrulanmış bir oturumla kullanıyor. Spam skoru mantığına göre bu trafik no action.
Asıl imza içerikte değil, davranıştadır: bir hesabın 40 dakikada ürettiği hacim, alıcı çeşitliliği, gönderim saati, aynı
rspamd ile Giden Spam'i Yakala: Ele Geçirilmiş Hesap Savunması — EvilMail Blog
From
ile ani sıçrama, karantinaya düşen bounce oranı. Bu yüzden giden yolu ayrı bir politika olarak ele almak zorundasınız. rspamd'da bunun aracı
settings
bloğudur — aynı instance, ayrı
id
, tamamen farklı sembol seti. Gelen için değerli olan
BAYES_SPAM
,
SPF_FAIL
gibi semboller giden için gürültüdür; giden için değerli olanlar
RATELIMIT
, user reputation ve kendi yazdığınız davranış sembolleridir.
Giden yolu ayrı bir politika olarak izole etmek
Ayrı bir rspamd process çalıştırmanıza gerek yok. Aynı milter'a bağlanır, farkı master.cf'te submission ve smtps portlarına verdiğiniz override'lar ve rspamd tarafındaki settings.conf yaratır. Kritik nokta, Postfix'in kimliği doğrulanmış SASL kullanıcısını milter makrosu olarak rspamd'a taşımasıdır. Bunu yapmazsanız rspamd user değişkenini asla göremez, hesap bazlı hiçbir şey kuramazsınız.
/etc/postfix/master.cf içinde submission bloğu:
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_milters=inet:127.0.0.1:11332
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_milters=inet:127.0.0.1:11332
milter_macro_daemon_name=ORIGINATING gelen (:25) ile giden trafiği rspamd'ın gözünde birbirinden ayıran bayrağınızdır. Postfix main.cf'te makronun milter'a gönderildiğinden emin olun:
milter_mail_macros = i {auth_type} {auth_authen} {client_addr} {client_name} {mail_addr}
Kullanıcı kimliğini rspamd'a taşımak: her şeyin anahtarı
Neden IP değil de kullanıcıya göre gruplanıyoruz? Çünkü tek bir submission IP'sinin arkasında 500 müşteri olabilir; hepsi de rspamd'a 127.0.0.1'den geliyor gibi görünür. IP'ye limit koyarsanız ya masum çoğunluğu boğar ya da saldırganı serbest bırakırsınız. Doğru anahtar ${user} — yani SASL ile doğrulanmış hesap.
/etc/rspamd/settings.conf içinde giden politikayı seçen blok:
authenticated = yes koşulu, yalnızca SASL doğrulaması olan (yani submission/smtps'ten gelen) oturumları bu bloğa sokar. Gelen :25 trafiği hiç dokunmadan standart yoldan akmaya devam eder.
Ratelimit: asıl savunma hattı
Giden savunmanın belkemiği ratelimit modülüdür ve doğru kurulumun tek koşulu Redis'tir. In-memory sayaç kalıcı değildir; rspamd restart olduğunda saldırganın sayacı sıfırlanır. Redis'i ayrı bir DB numarasında tutun ki gelen Bayes/fuzzy verisiyle karışmasın.
/etc/rspamd/local.d/ratelimit.conf — kritik nokta, her bucket'ı IP'ye değil doğrulanmış kullanıcıya anahtarlayan selector = "user":
# /etc/rspamd/local.d/redis.conf
servers = "127.0.0.1:6379";
db = "2";
60/dk, 200/dk, 2000/saat, 10000/gün başlangıç değerleridir — evilmail'de bunlar müşteri paketine göre multimap üzerinden override edilir. Ücretsiz kademe bunun onda birinde gezer, kurumsal paket iki katına çıkar. Sabit tek limit ya iş yapan müşteriyi engeller ya da saldırgana fazla alan bırakır; kademeli ve paket-bazlı olması şart. Bucket'ın burst'ünü aşan mesaj varsayılan olarak soft reject yer; ilk (60/dk) bucket'ı yumuşak, ikincisini (200/dk) sert eylemle eşleyerek iki katmanlı bir tavan kurarsınız.
Bileşik sinyaller ve reputation: ratelimit'in kaçırdıkları
Zeki saldırgan ratelimit'i bilir ve low-and-slow gider: dakikada 55 mesaj, limitin hemen altında, ama kesintisiz 18 saat. Bu hız 59.000'i aşan mesaj eder ve tek bir bucket bile taşmaz. Bunu yakalamak için hacim mutlak değil, kendine göre görece ölçülmeli.
Burada reputation modülünün user reputation'ı ve bir multimap custom sembolü devreye girer. Bir hesabın son 24 saatlik ortalamasına göre ani sıçramayı, alışılmadık gönderim saatini ve alıcı çeşitliliği patlamasını işaretlersiniz:
Sıçramayı ölçen Lua pratikte küçük bir parçadır — hesabın saatlik sayacını 24 saatlik hareketli ortalamayla karşılaştırıp katsayıyı sembol skoruna çeviren bir rspamd_config:register_symbol bloğu. neural modülü de bu işi öğrenebilir ama çoğu kurulum için overkill; sinir ağını eğitecek kadar temiz etiketli giden veriniz yoksa multimap + reputation daha öngörülebilir ve hata ayıklaması kolaydır.
Yakalayınca ne yapmalı: karantina, throttle, öldür
Tespit yarısı; tepki diğer yarısı. Üç katman kurun:
Soft (defer): rspamd soft reject → Postfix 451 4.7.1 Try again later. Meşru ama coşkun kullanıcıyı yavaşlatır, mesaj kaybolmaz, client tekrar dener. İlk savunma hattınız bu olmalı çünkü false positive maliyeti düşük.
Hard (reject): rspamd reject → 550. Hesaba bir bayrak (compromised_suspect) düşürün ve mesajı geri çevirin.
Kill:force_actions üzerinden dış bir script tetikleyin. Script Dovecot tarafında doveadm ile hesabın parolasını rotate eder / auth policy ile SMTP AUTH'u keser, aktif oturumu sonlandırır. Saldırganın elindeki geçerli kimlik bilgisini o an geçersizleştirmezseniz 550 yağmuru altında hesap yeni oturum açmaya devam eder.
Karantina için bcc action ile şüpheli mesajın bir kopyasını ayrı bir inceleme mailbox'ına düşürün; insan gözü 30 saniyede "bu gerçekten fatura mı yoksa Nijerya prensi mi" ayrımını yapar. Alarm tarafında ağır bir yığına gerek yok: force_actions'tan çıkan olayı bir webhook'a POST edip Slack'e veya Grafana'ya düşürmek yeterli.
Prod'da bir saldırı beklemeyin; simüle edin. swaks ile döngü kurup limiti tetikleyin ve 451'i kendi gözünüzle görün:
bash
for i in $(seq 1 100); do
swaks --to [email protected] --from [email protected] \
--server 127.0.0.1:587 --auth LOGIN \
--auth-user [email protected] --auth-password 'xxxx' \
--header "Subject: rl-test $i" --body "load" 2>&1 | grep -E '451|550'
done
Redis'te bucket sayaçlarının gerçekten arttığını doğrulayın. rspamd anahtarları hash'lediği için önce tarayıp tam anahtarı alın, sonra HGETALL ile içine bakın:
rspamd web UI'ında (:11334) throttle sembollerinin (RATELIMIT, OUTBOUND_VOLUME_SPIKE) history'de göründüğünü kontrol edin. rspamc ile tek mesaj üstünde de sembol çıktısını inceleyebilirsiniz. Test hesabınızın parolasını sonra rotate etmeyi unutmayın.
Operasyonel kontrol listesi
Giden yol master.cf'te ORIGINATING daemon adıyla izole edildi mi?
{auth_authen} makrosu milter_mail_macros ile rspamd'a taşınıyor mu?
rspamd'da user değişkeni okunuyor mu (rspamc history'de görülüyor mu)?
Ratelimit anahtarı selector = "user", IP değil — doğrulandı mı?
Redis ayrı bir DB'de (örn. db=2) ve backend kalıcı mı?
Low-and-slow için 24 saatlik hacim sıçraması sembolü çalışıyor mu?
force_action webhook'u + doveadm ile hesap kilitleme test edildi mi?
Karantina/inceleme mailbox'ı (bcc) tanımlı mı?
Giden dkim_signing milter sıralamasında bozulmuyor, imza hâlâ PASS mı?
Grafana/Slack alarmı tetikleniyor mu ve aylık limit review'ı takvimde mi?
O gece bize bir hafta reputation onarımına ve iki müşteriye özür mailine mal oldu. Giden tarafı içeriğe göre değil davranışa göre kurduğunuz gün, saldırgan geçerli kimlik bilgisiyle bile 200. mesajın ötesine geçemez — siz sabaha karşı değil, ilk buckette haberdar olursunuz.