438 lines
19 KiB
PHP
Executable File
438 lines
19 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* WEVAL Tracking Deployment Manager v3.1
|
|
* + Domain Warming System
|
|
*/
|
|
session_start();
|
|
$tracking_ip = '151.80.235.110';
|
|
$wevads_ip = '89.167.40.150';
|
|
|
|
// Warming thresholds
|
|
define('SCORE_ACTIVE', 70); // >= 70 = Active
|
|
define('SCORE_WARMING', 50); // 50-69 = Warming
|
|
// < 50 = Restricted
|
|
|
|
function checkDomainReputation($domain) {
|
|
$tldScores = [
|
|
'com' => 95, 'net' => 90, 'org' => 90, 'io' => 75, 'co' => 75,
|
|
'de' => 85, 'fr' => 85, 'uk' => 85, 'eu' => 80,
|
|
'info' => 60, 'biz' => 55, 'charity' => 45, 'site' => 40,
|
|
'xyz' => 40, 'top' => 35, 'click' => 30
|
|
];
|
|
|
|
$parts = explode('.', $domain);
|
|
$tld = strtolower(end($parts));
|
|
$score = $tldScores[$tld] ?? 50;
|
|
|
|
// Blacklist check
|
|
$blacklists = ['zen.spamhaus.org', 'bl.spamcop.net'];
|
|
$blHits = 0;
|
|
foreach ($blacklists as $bl) {
|
|
if (@dns_get_record("$domain.$bl", DNS_A)) {
|
|
$score -= 15;
|
|
$blHits++;
|
|
}
|
|
}
|
|
|
|
// DNS bonus
|
|
if (@dns_get_record($domain, DNS_A)) $score += 3;
|
|
if (@dns_get_record($domain, DNS_MX)) $score += 2;
|
|
|
|
$score = max(0, min(100, $score));
|
|
|
|
// Determine status
|
|
if ($score >= SCORE_ACTIVE) {
|
|
$status = 'active';
|
|
$statusLabel = 'ACTIVE';
|
|
$statusColor = '#10b981';
|
|
$recommendation = 'Ready for full volume sending';
|
|
$maxDaily = 'Unlimited';
|
|
} elseif ($score >= SCORE_WARMING) {
|
|
$status = 'warming';
|
|
$statusLabel = 'WARMING';
|
|
$statusColor = '#f59e0b';
|
|
$recommendation = 'Use progressive volume: Start 100/day, increase 20% daily';
|
|
$maxDaily = 'Start 100, +20%/day';
|
|
} else {
|
|
$status = 'restricted';
|
|
$statusLabel = 'RESTRICTED';
|
|
$statusColor = '#ef4444';
|
|
$recommendation = 'Not recommended. Use only as backup or acquire better domain.';
|
|
$maxDaily = 'Backup only';
|
|
}
|
|
|
|
$rating = $score >= 80 ? 'Excellent' : ($score >= 60 ? 'Good' : ($score >= 40 ? 'Fair' : 'Poor'));
|
|
|
|
return [
|
|
'score' => $score,
|
|
'rating' => $rating,
|
|
'tld' => ".$tld",
|
|
'status' => $status,
|
|
'statusLabel' => $statusLabel,
|
|
'statusColor' => $statusColor,
|
|
'recommendation' => $recommendation,
|
|
'maxDaily' => $maxDaily,
|
|
'blacklistHits' => $blHits,
|
|
'warmingPlan' => $status === 'warming' ? [
|
|
'day1' => 100,
|
|
'day2' => 120,
|
|
'day3' => 144,
|
|
'day4' => 173,
|
|
'day5' => 207,
|
|
'day6' => 249,
|
|
'day7' => 299,
|
|
'day14' => 743,
|
|
'day21' => 1847,
|
|
'day30' => 5765
|
|
] : null
|
|
];
|
|
}
|
|
|
|
function testServer($ip) {
|
|
$fp = @fsockopen($ip, 80, $errno, $errstr, 5);
|
|
if ($fp) { fclose($fp); return ['status' => 'online']; }
|
|
return ['status' => 'offline', 'error' => $errstr];
|
|
}
|
|
|
|
// Handle AJAX
|
|
if (isset($_REQUEST['action'])) {
|
|
header('Content-Type: application/json');
|
|
|
|
switch ($_REQUEST['action']) {
|
|
case 'test':
|
|
echo json_encode(testServer($_POST['ip'] ?? '151.80.235.110'));
|
|
break;
|
|
|
|
case 'check_domain':
|
|
echo json_encode(checkDomainReputation($_POST['domain'] ?? ''));
|
|
break;
|
|
|
|
case 'deploy':
|
|
$ip = $_POST['ip'] ?? '';
|
|
$pass = $_POST['password'] ?? '';
|
|
$domain = $_POST['domain'] ?? $ip;
|
|
|
|
if (!$ip || !$pass) {
|
|
echo json_encode(['success' => false, 'message' => 'IP and password required']);
|
|
break;
|
|
}
|
|
|
|
$script = '#!/bin/bash
|
|
set -e
|
|
apt-get update -qq
|
|
apt-get install -y -qq nginx php-fpm
|
|
mkdir -p /var/www/tracking/{c,o,u} /var/log/tracking
|
|
|
|
cat > /var/www/tracking/c/index.php << "INNEREOF"
|
|
<?php
|
|
header("X-Robots-Tag: noindex");
|
|
$d = explode("/", trim($_SERVER["REQUEST_URI"], "/"))[1] ?? "";
|
|
@file_put_contents("/var/log/tracking/clicks.log", date("Y-m-d H:i:s")." | ".$_SERVER["REMOTE_ADDR"]." | $d\n", FILE_APPEND);
|
|
$ctx = stream_context_create(["http" => ["timeout" => 3]]);
|
|
$r = @file_get_contents("http://'.$wevads_ip.':5821/api/track/click?data=".urlencode($d), false, $ctx);
|
|
$j = @json_decode($r, true);
|
|
if (isset($j["redirect"])) { header("Location: ".$j["redirect"], true, 302); exit; }
|
|
header("Content-Type: image/gif");
|
|
echo base64_decode("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
|
|
INNEREOF
|
|
|
|
cat > /var/www/tracking/o/index.php << "INNEREOF"
|
|
<?php
|
|
header("X-Robots-Tag: noindex");
|
|
header("Cache-Control: no-cache");
|
|
$d = explode("/", trim($_SERVER["REQUEST_URI"], "/"))[1] ?? "";
|
|
@file_put_contents("/var/log/tracking/opens.log", date("Y-m-d H:i:s")." | ".$_SERVER["REMOTE_ADDR"]." | $d\n", FILE_APPEND);
|
|
@file_get_contents("http://'.$wevads_ip.':5821/api/track/open?data=".urlencode($d), false, stream_context_create(["http"=>["timeout"=>1]]));
|
|
header("Content-Type: image/gif");
|
|
echo base64_decode("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
|
|
INNEREOF
|
|
|
|
cat > /var/www/tracking/u/index.php << "INNEREOF"
|
|
<?php
|
|
$d = explode("/", trim($_SERVER["REQUEST_URI"], "/"))[1] ?? "";
|
|
@file_put_contents("/var/log/tracking/unsubs.log", date("Y-m-d H:i:s")." | ".$_SERVER["REMOTE_ADDR"]." | $d\n", FILE_APPEND);
|
|
header("Location: http://'.$wevads_ip.':5821/unsubscribe?d=".urlencode($d));
|
|
INNEREOF
|
|
|
|
PHP_VER=$(php -r "echo PHP_MAJOR_VERSION.\".\".PHP_MINOR_VERSION;")
|
|
cat > /etc/nginx/sites-available/tracking << NGINXEOF
|
|
server {
|
|
listen 80;
|
|
server_name '.$domain.' _;
|
|
root /var/www/tracking;
|
|
location /c/ { try_files \\\$uri /c/index.php; }
|
|
location /o/ { try_files \\\$uri /o/index.php; }
|
|
location /u/ { try_files \\\$uri /u/index.php; }
|
|
location ~ \\.php\\\$ {
|
|
include snippets/fastcgi-php.conf;
|
|
fastcgi_pass unix:/var/run/php/php\${PHP_VER}-fpm.sock;
|
|
}
|
|
}
|
|
NGINXEOF
|
|
|
|
ln -sf /etc/nginx/sites-available/tracking /etc/nginx/sites-enabled/
|
|
rm -f /etc/nginx/sites-enabled/default
|
|
chown -R www-data:www-data /var/www/tracking /var/log/tracking
|
|
nginx -t && systemctl restart nginx php*-fpm
|
|
echo "DEPLOY_SUCCESS"';
|
|
|
|
$tmpFile = '/tmp/deploy_' . md5($ip) . '.sh';
|
|
file_put_contents($tmpFile, $script);
|
|
|
|
$cmd = "sshpass -p " . escapeshellarg($pass) . " ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 root@$ip 'bash -s' < $tmpFile 2>&1";
|
|
$output = shell_exec($cmd);
|
|
@unlink($tmpFile);
|
|
|
|
echo json_encode([
|
|
'success' => strpos($output, 'DEPLOY_SUCCESS') !== false,
|
|
'output' => $output
|
|
]);
|
|
break;
|
|
}
|
|
exit;
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>WEVAL | Tracking Deployment</title>
|
|
<link href="plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="plugins/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
|
<style>
|
|
body { background: #0a0e17; color: #f1f5f9; font-family: 'Segoe UI', sans-serif; }
|
|
.container-main { max-width: 1300px; margin: 30px auto; padding: 20px; }
|
|
.card-dark { background: #1a2332; border: 1px solid #2a3a50; border-radius: 12px; margin-bottom: 20px; }
|
|
.card-dark .card-header { background: #111827; border-bottom: 1px solid #2a3a50; padding: 15px 20px; font-weight: 600; }
|
|
.card-dark .card-body { padding: 20px; }
|
|
.form-control-dark { background: #0d1219; border: 1px solid #2a3a50; color: #fff; border-radius: 8px; padding: 10px 15px; width: 100%; }
|
|
.form-control-dark:focus { border-color: #00e5ff; outline: none; background: #0d1219; color: #fff; }
|
|
.btn-cyber { padding: 10px 20px; border-radius: 8px; font-weight: 600; border: none; cursor: pointer; transition: all 0.2s; }
|
|
.btn-cyber:hover { transform: translateY(-2px); }
|
|
.btn-primary-cyber { background: linear-gradient(135deg, #00e5ff, #0891b2); color: #000; }
|
|
.btn-success-cyber { background: linear-gradient(135deg, #10b981, #059669); color: #fff; }
|
|
.status-badge { padding: 8px 16px; border-radius: 20px; font-weight: 600; font-size: 14px; display: inline-block; }
|
|
.status-active { background: rgba(16,185,129,0.2); color: #10b981; border: 1px solid #10b981; }
|
|
.status-warming { background: rgba(245,158,11,0.2); color: #f59e0b; border: 1px solid #f59e0b; }
|
|
.status-restricted { background: rgba(239,68,68,0.2); color: #ef4444; border: 1px solid #ef4444; }
|
|
.status-online { color: #10b981; }
|
|
.status-offline { color: #ef4444; }
|
|
.score-box { font-size: 56px; font-weight: 700; font-family: 'Courier New', monospace; }
|
|
.info-box { background: rgba(0,229,255,0.1); border: 1px solid rgba(0,229,255,0.3); border-radius: 8px; padding: 15px; margin-bottom: 20px; }
|
|
.warning-box { background: rgba(245,158,11,0.1); border: 1px solid rgba(245,158,11,0.3); border-radius: 8px; padding: 15px; }
|
|
.log-box { background: #0d1219; border: 1px solid #2a3a50; border-radius: 8px; padding: 15px; font-family: monospace; font-size: 13px; max-height: 250px; overflow-y: auto; }
|
|
h1 { color: #00e5ff; margin-bottom: 5px; }
|
|
label { color: #94a3b8; font-size: 13px; margin-bottom: 5px; display: block; }
|
|
.rule-box { background: #111827; border-radius: 8px; padding: 15px; margin-top: 15px; }
|
|
.rule-item { display: flex; align-items: center; padding: 8px 0; border-bottom: 1px solid #2a3a50; }
|
|
.rule-item:last-child { border-bottom: none; }
|
|
.rule-score { width: 100px; font-weight: 600; }
|
|
.rule-status { width: 120px; }
|
|
.rule-action { flex: 1; color: #94a3b8; font-size: 13px; }
|
|
.warming-plan { margin-top: 15px; }
|
|
.warming-plan table { width: 100%; font-size: 13px; }
|
|
.warming-plan th { color: #64748b; font-weight: 500; padding: 8px; text-align: left; }
|
|
.warming-plan td { padding: 8px; border-top: 1px solid #2a3a50; }
|
|
.form-group { margin-bottom: 15px; }
|
|
</style>
|
|
|
|
</head>
|
|
<body>
|
|
<div class="container-main">
|
|
<h1><i class="fa fa-rocket"></i> Tracking Server Deployment</h1>
|
|
<p style="color:#64748b;margin-bottom:25px;">Deploy tracking servers and manage domain warming for optimal deliverability</p>
|
|
|
|
<!-- Current Status -->
|
|
<div class="card-dark">
|
|
<div class="card-header"><i class="fa fa-server"></i> Current Tracking Server</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<label>IP Address</label>
|
|
<div style="font-size:24px;font-family:monospace;"><?= $tracking_ip ?></div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label>Status</label>
|
|
<div id="current-status"><i class="fa fa-spinner fa-spin"></i> Checking...</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label>Domain</label>
|
|
<div style="color:#f59e0b;">No domain configured</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label>Action</label>
|
|
<button class="btn btn-cyber btn-primary-cyber btn-sm" onclick="testCurrent()">
|
|
<i class="fa fa-refresh"></i> Refresh
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Deploy Section -->
|
|
<div class="col-md-6">
|
|
<div class="card-dark">
|
|
<div class="card-header"><i class="fa fa-cloud-upload"></i> Deploy to New Server</div>
|
|
<div class="card-body">
|
|
<div class="form-group">
|
|
<label>New Server IP</label>
|
|
<input type="text" class="form-control-dark" id="new-ip" placeholder="e.g., 5.161.xxx.xxx">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Root Password</label>
|
|
<input type="password" class="form-control-dark" id="new-pass" placeholder="SSH password">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Domain (optional)</label>
|
|
<input type="text" class="form-control-dark" id="new-domain" placeholder="track.example.com">
|
|
</div>
|
|
<button class="btn btn-cyber btn-primary-cyber" onclick="deployServer()">
|
|
<i class="fa fa-rocket"></i> Deploy Tracking
|
|
</button>
|
|
<div class="log-box mt-3" id="deploy-log" style="display:none;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Domain Checker -->
|
|
<div class="col-md-6">
|
|
<div class="card-dark">
|
|
<div class="card-header"><i class="fa fa-shield"></i> Domain Reputation & Warming</div>
|
|
<div class="card-body">
|
|
<div class="form-group">
|
|
<label>Check Domain</label>
|
|
<div class="input-group" style="display:flex;gap:10px;">
|
|
<input type="text" class="form-control-dark" id="check-domain" placeholder="example.com" style="flex:1;">
|
|
<button class="btn btn-cyber btn-success-cyber" onclick="checkDomain()">
|
|
<i class="fa fa-search"></i> Check
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="domain-result" style="display:none;">
|
|
<div style="display:flex;align-items:center;gap:20px;margin:20px 0;">
|
|
<div class="score-box" id="domain-score">--</div>
|
|
<div>
|
|
<div id="domain-status-badge" class="status-badge">--</div>
|
|
<div style="color:#64748b;margin-top:5px;font-size:13px;" id="domain-tld"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="warning-box" id="domain-recommendation"></div>
|
|
|
|
<div id="warming-plan-box" style="display:none;">
|
|
<div class="warming-plan">
|
|
<h6 style="color:#f59e0b;margin-top:15px;"><i class="fa fa-fire"></i> Warming Schedule</h6>
|
|
<table>
|
|
<tr><th>Day</th><th>Max Emails</th><th>Day</th><th>Max Emails</th></tr>
|
|
<tr><td>Day 1</td><td id="wp-d1">100</td><td>Day 7</td><td id="wp-d7">299</td></tr>
|
|
<tr><td>Day 3</td><td id="wp-d3">144</td><td>Day 14</td><td id="wp-d14">743</td></tr>
|
|
<tr><td>Day 5</td><td id="wp-d5">207</td><td>Day 30</td><td id="wp-d30">5,765</td></tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Rules Reference -->
|
|
<div class="rule-box">
|
|
<h6 style="color:#00e5ff;margin-bottom:10px;"><i class="fa fa-list-ul"></i> Warming Rules</h6>
|
|
<div class="rule-item">
|
|
<div class="rule-score" style="color:#10b981;">≥ 70</div>
|
|
<div class="rule-status"><span class="status-badge status-active">ACTIVE</span></div>
|
|
<div class="rule-action">Full volume, no restrictions</div>
|
|
</div>
|
|
<div class="rule-item">
|
|
<div class="rule-score" style="color:#f59e0b;">50-69</div>
|
|
<div class="rule-status"><span class="status-badge status-warming">WARMING</span></div>
|
|
<div class="rule-action">Progressive: 100/day +20%</div>
|
|
</div>
|
|
<div class="rule-item">
|
|
<div class="rule-score" style="color:#ef4444;">< 50</div>
|
|
<div class="rule-status"><span class="status-badge status-restricted">RESTRICTED</span></div>
|
|
<div class="rule-action">Backup only, acquire better domain</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="plugins/jquery.min.js"></script>
|
|
<script>
|
|
function testCurrent() {
|
|
$('#current-status').html('<i class="fa fa-spinner fa-spin"></i> Checking...');
|
|
$.post('?action=test', {ip: '<?= $tracking_ip ?>'}, function(r) {
|
|
$('#current-status').html(r.status === 'online'
|
|
? '<span class="status-online"><i class="fa fa-check-circle"></i> Online</span>'
|
|
: '<span class="status-offline"><i class="fa fa-times-circle"></i> Offline</span>');
|
|
});
|
|
}
|
|
|
|
function checkDomain() {
|
|
var domain = $('#check-domain').val().trim();
|
|
if (!domain) return alert('Enter a domain');
|
|
|
|
$('#domain-score').text('...');
|
|
$('#domain-result').show();
|
|
|
|
$.post('?action=check_domain', {domain: domain}, function(r) {
|
|
// Score color
|
|
var scoreColor = r.score >= 70 ? '#10b981' : (r.score >= 50 ? '#f59e0b' : '#ef4444');
|
|
$('#domain-score').text(r.score).css('color', scoreColor);
|
|
|
|
// Status badge
|
|
$('#domain-status-badge')
|
|
.text(r.statusLabel)
|
|
.removeClass('status-active status-warming status-restricted')
|
|
.addClass('status-' + r.status);
|
|
|
|
$('#domain-tld').text('TLD: ' + r.tld + ' | Rating: ' + r.rating);
|
|
$('#domain-recommendation').html('<strong>Recommendation:</strong> ' + r.recommendation + '<br><strong>Max Daily:</strong> ' + r.maxDaily);
|
|
|
|
// Show warming plan if needed
|
|
if (r.status === 'warming' && r.warmingPlan) {
|
|
$('#wp-d1').text(r.warmingPlan.day1);
|
|
$('#wp-d3').text(r.warmingPlan.day3);
|
|
$('#wp-d5').text(r.warmingPlan.day5);
|
|
$('#wp-d7').text(r.warmingPlan.day7);
|
|
$('#wp-d14').text(r.warmingPlan.day14);
|
|
$('#wp-d30').text(r.warmingPlan.day30.toLocaleString());
|
|
$('#warming-plan-box').show();
|
|
} else {
|
|
$('#warming-plan-box').hide();
|
|
}
|
|
});
|
|
}
|
|
|
|
function deployServer() {
|
|
var ip = $('#new-ip').val().trim();
|
|
var pass = $('#new-pass').val();
|
|
var domain = $('#new-domain').val().trim();
|
|
|
|
if (!ip || !pass) return alert('IP and password required');
|
|
|
|
$('#deploy-log').show().html('<i class="fa fa-spinner fa-spin"></i> Connecting to ' + ip + '...');
|
|
|
|
$.post('?action=deploy', {ip: ip, password: pass, domain: domain || ip}, function(r) {
|
|
if (r.success) {
|
|
$('#deploy-log').html('<span style="color:#10b981;"><i class="fa fa-check"></i> Deployment successful!</span><br><br>Tracking ready at:<br>http://' + (domain || ip) + '/c/{data}<br>http://' + (domain || ip) + '/o/{data}');
|
|
} else {
|
|
$('#deploy-log').html('<span style="color:#ef4444;"><i class="fa fa-times"></i> Deployment failed</span><br><pre style="color:#94a3b8;font-size:11px;white-space:pre-wrap;">' + (r.output || r.message) + '</pre>');
|
|
}
|
|
}).fail(function() {
|
|
$('#deploy-log').html('<span style="color:#ef4444;">Connection error</span>');
|
|
});
|
|
}
|
|
|
|
$(document).ready(function() {
|
|
testCurrent();
|
|
// Auto-check culturellemejean.charity
|
|
$('#check-domain').val('culturellemejean.charity');
|
|
checkDomain();
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|