Mail sunucusu yöneten herkesin karşılaştığı temel problemlerden biri spam, phishing ve zararlı içerikli e-postaları kullanıcıya ulaşmadan önce mümkün olduğunca doğru şekilde filtrelemektir. Proxmox Mail Gateway, bu konuda oldukça başarılı bir gateway çözümüdür. Ancak bazı yapılarda Rspamd gibi modern ve güçlü bir antispam motorunu da ek skor motoru olarak kullanmak ciddi avantaj sağlayabilir.
Bu yazıda Proxmox Mail Gateway üzerinde Rspamd’i doğrudan PMG içine kurmak yerine ayrı bir Docker sunucusunda çalıştırıp, PMG custom check mekanizması ile entegre etmeyi anlatacağım. Ayrıca DNS sorguları için Unbound kullanımı ve cPanel üzerindeki mail hesaplarını PMG bypass girişimlerine karşı koruma konusunu da ele alacağız.
Kurulum Mimarisi
Kurduğumuz yapının genel mimarisi şu şekilde:
Internet
↓
Proxmox Mail Gateway
↓
PMG custom_check script
↓
rspamc ile Docker üzerindeki Rspamd
↓
Rspamd + Redis + Unbound
↓
cPanel / Mail Server
Bu modelde Proxmox Mail Gateway ana mail gateway olarak çalışmaya devam eder. Rspamd ise PMG’ye ek bir antispam skor motoru gibi davranır. PMG maili alır, custom check script ile Rspamd’e gönderir, Rspamd analiz sonucunu döndürür ve PMG bu skora göre kendi rule/quarantine sistemini işletir.
Neden Rspamd’i Ayrı Docker Sunucusunda Çalıştırdık?
Rspamd’i doğrudan PMG üzerine kurmak mümkündür. Ancak ayrı bir Docker sunucusunda çalıştırmanın bazı avantajları vardır:
- PMG sistemi daha temiz kalır.
- Rspamd bağımsız şekilde güncellenebilir.
- Redis, Unbound ve Rspamd birlikte izole çalışır.
- Birden fazla PMG sunucusu aynı Rspamd servisini kullanabilir.
- Hata durumunda PMG mail akışı bozulmadan devam edebilir.
Docker Compose ile Rspamd, Redis ve Unbound Kurulumu
Örnek Docker Compose dosyamız şu şekilde olabilir:
version: '3.8'services:
rspamd:
image: rspamd/rspamd:latest
container_name: rspamd
ports:
- "11333:11333"
- "11334:11334"
volumes:
- /opt/rspamd/config:/etc/rspamd/local.d
- /opt/rspamd/data:/var/lib/rspamd
- /opt/rspamd/logs:/var/log/rspamd
depends_on:
- redis
- unbound
dns:
- 172.28.0.53
networks:
rspamd_net:
ipv4_address: 172.28.0.10
restart: unless-stopped redis:
image: redis:alpine
container_name: rspamd-redis
volumes:
- /opt/rspamd/redis:/data
networks:
rspamd_net:
ipv4_address: 172.28.0.20
restart: unless-stopped unbound:
image: mvance/unbound:latest
container_name: rspamd-unbound
networks:
rspamd_net:
ipv4_address: 172.28.0.53
restart: unless-stoppednetworks:
rspamd_net:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/24
Burada Rspamd container DNS olarak Unbound container’ını kullanır. Bu özellikle RBL, URIBL, SURBL, SPF, DKIM, DMARC ve ASN sorguları için daha sağlıklı bir yapı sağlar.
Rspamd Portları Ne İşe Yarar?
Rspamd tarafında portları karıştırmamak önemlidir:
11333 = Normal scan worker, PMG custom check için kullanılır
11334 = Controller / Web UI
11332 = Milter / proxy worker
PMG custom check entegrasyonunda genellikle 11333 portunu kullanırız. Web arayüzüne erişmek için ise 11334 kullanılır. 11334 portunu mümkünse public internete açmamak, VPN veya SSH tunnel ile erişmek daha güvenlidir.
Rspamd Temel Config Dosyaları
Docker volume yapımıza göre Rspamd local config dosyaları host üzerinde şu dizinde tutulur:
/opt/rspamd/config
Redis Config
# /opt/rspamd/config/redis.conf
servers = "redis:6379";
Bayes Classifier Config
# /opt/rspamd/config/classifier-bayes.conf
backend = "redis";
servers = "redis:6379";
Normal Worker Config
# /opt/rspamd/config/worker-normal.inc
bind_socket = "0.0.0.0:11333";
Controller Config
# /opt/rspamd/config/worker-controller.inc
bind_socket = "0.0.0.0:11334";
password = "$2$HASH_BURAYA";
enable_password = "$2$HASH_BURAYA";
Controller şifresini oluşturmak için:
docker exec -it rspamd rspamadm pw
Unbound DNS Kullanımı
Rspamd DNS tabanlı kontrolleri yoğun kullandığı için Unbound kullanmak mantıklıdır. İlk aşamada Cloudflare DNS-over-TLS gibi forward yapıları kullanılabilir. Ancak antispam tarafında en doğru sonuçlar için Unbound’un tam recursive resolver olarak çalışması daha sağlıklıdır.
Recursive Unbound çalıştığında loglarda root, TLD ve authoritative DNS sunucularına direkt sorgular görürsünüz:
priming . IN NS
reply from <.> 202.12.27.33#53
reply from <com.> 192.12.94.30#53
reply from <google.com.> 216.239.32.10#53
Bu, Unbound’un Cloudflare gibi public resolver üzerinden değil, doğrudan recursive çalıştığını gösterir.
PMG Üzerinde rspamc Kurulumu
PMG, Docker’daki Rspamd servisine bağlanmak için rspamc client aracına ihtiyaç duyar.
apt update
apt install rspamd-client jq -y
Eğer rspamd-client paketi bulunamazsa:
apt install rspamd jq -y
systemctl disable --now rspamd
PMG üzerinde Rspamd servisini çalıştırmak zorunda değiliz. Sadece rspamc binary’si yeterlidir.
PMG Custom Check Script
PMG tarafında custom check script’i ile mail dosyası Rspamd’e gönderilir. Rspamd skoruna göre PMG’ye OK veya SCORE: x döndürülür.
Script dosyası:
/usr/local/bin/pmg-rspamd-check.sh
Örnek sade ve stabil script:
#!/bin/bash
set -euo pipefail
API_VERSION="${1:-}"
QUEUE_FILE="${2:-}"
RSPAMD_HOST="X.X.X.X"
RSPAMD_PORT="11333"
TIMEOUT_SECONDS="5"
if [[ -z "$API_VERSION" || -z "$QUEUE_FILE" || ! -f "$QUEUE_FILE" ]]; then
echo "OK"
exit 0
fi
logger -t pmg-rspamd-check "called api=${API_VERSION} file=${QUEUE_FILE}"
RESULT="$(timeout "${TIMEOUT_SECONDS}" rspamc -h "${RSPAMD_HOST}:${RSPAMD_PORT}" -j symbols "$QUEUE_FILE" 2>/dev/null || true)"
logger -t pmg-rspamd-check "result_len=${#RESULT}"
if [[ -z "$RESULT" ]]; then
echo "OK"
exit 0
fi
SCORE="$(echo "$RESULT" | jq -r '.score // 0' 2>/dev/null || echo 0)"
ACTION="$(echo "$RESULT" | jq -r '.action // "no action"' 2>/dev/null || echo "no action")"
logger -t pmg-rspamd-check "rspamd_score=${SCORE} action=${ACTION}"
if ! [[ "$SCORE" =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then
echo "OK"
exit 0
fi
case "$ACTION" in
"reject")
echo "SCORE: 12"
exit 0
;;
"add header")
echo "SCORE: 5"
exit 0
;;
"rewrite subject")
echo "SCORE: 4"
exit 0
;;
esac
if awk "BEGIN {exit !($SCORE >= 15)}"; then
echo "SCORE: 10"
elif awk "BEGIN {exit !($SCORE >= 8)}"; then
echo "SCORE: 5"
elif awk "BEGIN {exit !($SCORE >= 5)}"; then
echo "SCORE: 3"
else
echo "OK"
fi
exit 0
Yetki ve syntax kontrolü:
chmod +x /usr/local/bin/pmg-rspamd-check.sh
bash -n /usr/local/bin/pmg-rspamd-check.sh
PMG Config İçinde Custom Check Aktif Etme
PMG üzerinde /etc/pmg/pmg.conf dosyasına şu satırlar eklenir:
section: admin
custom_check 1
custom_check_path /usr/local/bin/pmg-rspamd-check.sh
Sonrasında:
pmgconfig sync --restart 1
systemctl restart pmg-smtp-filter
Test
PMG üzerinden Rspamd bağlantısı test edilebilir:
rspamc -h X.X.X.X:11333 -j symbols /tmp/test.eml | jq
Controller / Web UI istatistiği için:
rspamc -h X.X.X.X:11334 -P 'WEB_UI_SIFRENIZ' stat
PMG custom script test:
/usr/local/bin/pmg-rspamd-check.sh v1 /tmp/test.eml
Log izleme:
journalctl -f | grep pmg-rspamd-check
GTUBE ile Spam Testi
Spam filtresini test etmek için GTUBE test string’i kullanılabilir. Bu gerçek spam değildir; spam filtreleri için standart test içeriğidir.
cat > /tmp/gtube.eml <<'EOF'
From: spammer@example.com
To: test@example.com
Subject: GTUBE spam testXJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
EOF
Test:
rspamc -h X.X.X.X:11333 -j symbols /tmp/gtube.eml | jq
/usr/local/bin/pmg-rspamd-check.sh v1 /tmp/gtube.eml
Rspamd Üzerinde Local Domain Blacklist
Rspamd’de kendi domain blacklist map’inizi tanımlayabilirsiniz.
mkdir -p /opt/rspamd/config/maps
nano /opt/rspamd/config/maps/blacklist_sender_domains.map
Örnek:
spamdomain.example
bad-domain.tld
phishing-example.net
multimap.conf içine:
BLACKLIST_SENDER_DOMAIN {
type = "from";
filter = "email:domain";
map = "/etc/rspamd/local.d/maps/blacklist_sender_domains.map";
score = 8.0;
symbol = "LOCAL_BLACKLIST_SENDER_DOMAIN";
description = "Sender domain is in local blacklist";
}Rspamd Üzerinde IP Whitelist
Güvenilir IP adreslerini whitelistlemek için:
nano /opt/rspamd/config/maps/ip_whitelist.map
Örnek:
1.2.3.4
5.6.7.0/24
multimap.conf içine:
LOCAL_IP_WHITELIST {
type = "ip";
map = "/etc/rspamd/local.d/maps/ip_whitelist.map";
score = -10.0;
symbol = "LOCAL_IP_WHITELIST";
description = "Sender IP is in local IP whitelist";
}Config kontrol ve restart:
docker exec -it rspamd rspamadm configtest
docker compose restart rspamd
ASN Bazlı Skorlama
Spam yoğunluğu yüksek bazı ASN’leri tamamen engellemek yerine puanlandırmak daha sağlıklıdır. Bunun için bad_asn.map kullanılabilir.
nano /opt/rspamd/config/maps/bad_asn.map
Örnek:
14061 2 # DigitalOcean
16276 2 # OVH
53755 5 # Input Output Flood
63018 4 # Dedicated.com
multimap.conf içine:
LOCAL_BL_ASN {
type = "asn";
map = "/etc/rspamd/local.d/maps/bad_asn.map";
score = 1.0;
symbol = "LOCAL_BL_ASN";
description = "Sender ASN is on local blacklist";
}Burada score = 1.0 kullanılması önemlidir. Çünkü map içindeki ikinci kolon zaten skor etkisini taşır.
cPanel Üzerinde PMG Bypass Koruması
Mail domainlerinin MX kaydını PMG’ye yönlendirmek tek başına yeterli değildir. Eğer saldırgan gerçek cPanel mail sunucusunun IP adresini bulursa, MX’i bypass ederek doğrudan cPanel’e mail göndermeyi deneyebilir.
Bunu engellemek için cPanel Exim tarafında domain bazlı ACL eklenebilir. Mantık şudur:
Eğer alıcı domain PMG korumalı listedeyse
ve bağlantı PMG IP’sinden gelmiyorsa
RCPT aşamasında reddet.
PMG IP Listesi
nano /etc/exim_pmg_allowed_hosts
Örnek:
127.0.0.1
Buraya sadece cPanel’in Exim loglarında PMG’den gelen bağlantı olarak gördüğü gerçek IP adresi yazılmalıdır.
PMG Korumalı Domain Listesi
nano /etc/exim_pmg_protected_domains
Örnek:
enkitech.com.tr
example.com
customer-domain.com
cPanel Exim ACL
cPanel 128 üzerinde doğru custom ACL alanı şu şekilde olabilir:
/usr/local/cpanel/etc/exim/acls/ACL_RECIPIENT_BLOCK/custom_begin_recipient
İçeriği:
deny
domains = lsearch;/etc/exim_pmg_protected_domains
!hosts = net-iplsearch;/etc/exim_pmg_allowed_hosts
!authenticated = *
message = This domain accepts mail only through EnkiTech SafeMail gateway.
log_message = PMG_BYPASS_BLOCKED: direct SMTP to protected domain=$domain from $sender_host_address sender=$sender_address recipient=$local_part@$domain
Burada net-iplsearch kullanılması önemlidir. Eğer dosyada CIDR subnet kullanılacaksa iplsearch yerine net-iplsearch tercih edilmelidir.
Rebuild ve restart:
/scripts/buildeximconf --force
/scripts/restartsrv_exim
Kuralın Exim config’e girdiğini kontrol etmek için:
grep -n "PMG_BYPASS_BLOCKED" /etc/exim.conf
Bypass Testi
Dış bir sunucudan doğrudan cPanel IP’sine test:
swaks \
--server CPANEL_IP \
--from test@example.net \
--to user@protected-domain.com \
--helo mail.example.net
Beklenen cevap:
550 This domain accepts mail only through EnkiTech SafeMail gateway.
PMG üzerinden gelen mail ise kabul edilmelidir.
Güvenlik Önerileri
- Rspamd 11333 portunu sadece PMG IP adresine açın.
- Rspamd 11334 Web UI portunu public internete açmayın.
- Unbound query loglarını testten sonra kapatın.
- Redis volume’unu düzenli yedekleyin.
- ASN blacklist gibi agresif kurallarda düşük skorla başlayın.
- cPanel tarafında sadece gerçek PMG IP’sini allow list’e ekleyin; mümkünse /24 gibi geniş subnetlerden kaçının.
- PMG ve cPanel loglarını ilk birkaç gün yakından izleyin.
Sonuç
Proxmox Mail Gateway tek başına güçlü bir mail gateway çözümüdür. Ancak Rspamd’i Docker üzerinde ayrı bir servis olarak çalıştırıp PMG custom check ile entegre etmek, spam tespit kalitesini artırmak ve daha esnek kurallar yazmak için oldukça etkili bir yöntemdir.
Bu yapı sayesinde PMG’nin quarantine, tracking center ve rule engine avantajları korunurken; Rspamd’in modern scoring, Redis tabanlı öğrenme, DNSBL/URIBL, ASN ve custom map özelliklerinden de yararlanılabilir.
Ek olarak cPanel Exim üzerinde yapılan PMG bypass koruması sayesinde gerçek mail sunucusunun IP adresi bilinse bile korunan domainlere doğrudan mail gönderimi engellenmiş olur. Bu, özellikle hosting ve çoklu müşteri barındıran yapılarda önemli bir güvenlik katmanıdır.

İlk Yorumu Siz Yapın