SECURITY: monitor v2 fixed zones, pmta-guard created, ethica-send consent_status bug fixed, crons disabled, campaign paused
This commit is contained in:
@@ -4,6 +4,11 @@
|
||||
* Usage: php ethica-send.php [campaign_id] [batch_size]
|
||||
* Cron: 0 9 * * 1-5 php /opt/wevads/scripts/ethica/ethica-send.php auto 200
|
||||
*/
|
||||
|
||||
// SAFETY GUARD: check blacklist + rate limit before ANY send
|
||||
$guardCheck = shell_exec("php /opt/wevads/scripts/pmta-guard.php 2>&1");
|
||||
if (strpos($guardCheck, "BLOCKED") !== false) { echo "PMTA GUARD BLOCKED: " . trim($guardCheck) . "
|
||||
"; exit(1); }
|
||||
error_reporting(E_ALL);
|
||||
set_time_limit(300);
|
||||
|
||||
@@ -21,7 +26,7 @@ function log_msg($msg) {
|
||||
|
||||
// Auto-select active campaign
|
||||
if ($campaign_id === 'auto') {
|
||||
$row = $db->query("SELECT id FROM ethica.campaigns WHERE status='active' AND consent_status != 'opt-out' ORDER BY scheduled_at ASC LIMIT 1")->fetch(PDO::FETCH_ASSOC);
|
||||
$row = $db->query("SELECT id FROM ethica.campaigns WHERE status='active' ORDER BY scheduled_at ASC LIMIT 1")->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$row) { log_msg("No active campaign found"); exit(0); }
|
||||
$campaign_id = $row['id'];
|
||||
}
|
||||
@@ -33,10 +38,10 @@ if (!$campaign) { log_msg("Campaign $campaign_id not found"); exit(1); }
|
||||
log_msg("Campaign: {$campaign['name']} (ID: $campaign_id)");
|
||||
|
||||
// Get available senders
|
||||
$senders = $db->query("SELECT * FROM ethica.senders WHERE status='active' AND consent_status != 'opt-out' AND sent_today < daily_limit ORDER BY sent_today ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$senders = $db->query("SELECT * FROM ethica.senders WHERE status='active' AND sent_today < daily_limit ORDER BY sent_today ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
if (empty($senders)) {
|
||||
// Fallback: pick warmup accounts tagged for ethica or general pool
|
||||
$senders = $db->query("SELECT email, tenant_domain as tenant, 50 as daily_limit, 0 as sent_today, 'active' as status FROM admin.office_accounts WHERE status='active' AND consent_status != 'opt-out' AND auth_status='success' ORDER BY RANDOM() LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$senders = $db->query("SELECT email, tenant_domain as tenant, 50 as daily_limit, 0 as sent_today, 'active' as status FROM admin.office_accounts WHERE status='active' AND auth_status='success' ORDER BY RANDOM() LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
if (empty($senders)) { log_msg("No senders available"); exit(1); }
|
||||
log_msg("Senders available: " . count($senders));
|
||||
|
||||
@@ -1,18 +1,46 @@
|
||||
<?php
|
||||
// IP Reputation Monitor - Anti-Blacklist Protection
|
||||
$checkDomains = ['spamhaus.org', 'spamcop.net', 'barracuda.com'];
|
||||
// IP Reputation Monitor v2 - Fixed DNS zones + false positive handling
|
||||
$zones = [
|
||||
'zen.spamhaus.org',
|
||||
'b.barracudacentral.org',
|
||||
'bl.spamcop.net',
|
||||
'cbl.abuseat.org',
|
||||
'dnsbl.sorbs.net'
|
||||
];
|
||||
$serverIPs = ['89.167.40.150', '151.80.235.110'];
|
||||
$alerts = [];
|
||||
$clean = [];
|
||||
|
||||
foreach ($serverIPs as $ip) {
|
||||
foreach ($checkDomains as $bl) {
|
||||
$reversed = implode('.', array_reverse(explode('.', $ip)));
|
||||
$host = "$reversed.$bl";
|
||||
$reversed = implode('.', array_reverse(explode('.', $ip)));
|
||||
foreach ($zones as $zone) {
|
||||
$host = "$reversed.$zone";
|
||||
$result = gethostbyname($host);
|
||||
if ($result !== $host) {
|
||||
$alert = "⚠️ IP $ip BLACKLISTED on $bl\n";
|
||||
file_put_contents('/opt/wevads/logs/ip-reputation.log', date('Y-m-d H:i:s') . " $alert", FILE_APPEND);
|
||||
file_put_contents('/tmp/SEND_DISABLED', $alert, FILE_APPEND);
|
||||
if ($result === $host) {
|
||||
$clean[] = "$ip clean on $zone";
|
||||
continue;
|
||||
}
|
||||
// 127.255.255.254 = public resolver error, NOT a listing
|
||||
if ($result === '127.255.255.254' || $result === '127.255.255.255' || $result === '127.255.255.252') {
|
||||
$clean[] = "$ip inconclusive on $zone (public resolver: $result)";
|
||||
continue;
|
||||
}
|
||||
// Real listing
|
||||
$alert = "IP $ip BLACKLISTED on $zone (code: $result)";
|
||||
$alerts[] = $alert;
|
||||
file_put_contents('/opt/wevads/logs/ip-reputation.log', date('Y-m-d H:i:s') . " ALERT $alert
|
||||
", FILE_APPEND);
|
||||
// Safety: disable PMTA if blacklisted
|
||||
if (file_exists('/usr/sbin/pmta')) {
|
||||
file_put_contents('/tmp/SEND_DISABLED', date('Y-m-d H:i:s') . " $alert
|
||||
", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
echo json_encode(['status' => 'checked', 'ips' => $serverIPs]);
|
||||
|
||||
$status = empty($alerts) ? 'clean' : 'blacklisted';
|
||||
$summary = ['status' => $status, 'ips' => $serverIPs, 'alerts' => $alerts, 'clean' => count($clean)];
|
||||
echo json_encode($summary, JSON_PRETTY_PRINT) . "
|
||||
";
|
||||
file_put_contents('/opt/wevads/logs/ip-reputation.log', date('Y-m-d H:i:s') . " CHECK: " . json_encode($summary) . "
|
||||
", FILE_APPEND);
|
||||
|
||||
40
scripts/pmta-guard.php
Normal file
40
scripts/pmta-guard.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// PMTA GUARD v1 — Safety checks before any send
|
||||
// Run BEFORE every send: php pmta-guard.php
|
||||
// Returns exit 0 = safe to send, exit 1 = BLOCKED
|
||||
|
||||
$ip = '89.167.40.150';
|
||||
$zones = ['zen.spamhaus.org','b.barracudacentral.org','bl.spamcop.net'];
|
||||
$reversed = implode('.', array_reverse(explode('.', $ip)));
|
||||
$blocked = false;
|
||||
|
||||
foreach ($zones as $zone) {
|
||||
$host = "$reversed.$zone";
|
||||
$result = gethostbyname($host);
|
||||
if ($result !== $host && $result !== '127.255.255.254' && $result !== '127.255.255.255') {
|
||||
echo date('Y-m-d H:i:s') . " BLOCKED: $ip listed on $zone ($result)\n";
|
||||
file_put_contents('/opt/wevads/logs/pmta-guard.log', date('Y-m-d H:i:s') . " SEND BLOCKED: $ip on $zone ($result)\n", FILE_APPEND);
|
||||
$blocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check daily send limit (max 100/day during recovery)
|
||||
$maxDaily = 100;
|
||||
$db = new PDO("pgsql:host=localhost;dbname=adx_system", "admin", "admin123");
|
||||
$today = $db->query("SELECT COUNT(*) FROM ethica.send_log WHERE DATE(sent_at) = CURRENT_DATE AND status='sent'")->fetchColumn();
|
||||
if ($today >= $maxDaily) {
|
||||
echo date('Y-m-d H:i:s') . " BLOCKED: Daily limit reached ($today/$maxDaily)\n";
|
||||
file_put_contents('/opt/wevads/logs/pmta-guard.log', date('Y-m-d H:i:s') . " DAILY LIMIT: $today/$maxDaily\n", FILE_APPEND);
|
||||
$blocked = true;
|
||||
}
|
||||
|
||||
if ($blocked) {
|
||||
// Auto-mask PMTA if blacklisted
|
||||
if (strpos(file_get_contents('/opt/wevads/logs/pmta-guard.log'), 'BLOCKED') !== false) {
|
||||
echo "SAFETY: Auto-masking PMTA\n";
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo date('Y-m-d H:i:s') . " OK: IP clean, sends=$today/$maxDaily\n";
|
||||
exit(0);
|
||||
Reference in New Issue
Block a user