1. Home
  2. Aplicaciones y CMS
  3. Wordpress
  4. Proteccion basica DDoS al index.php en WordPress

Proteccion basica DDoS al index.php en WordPress

🛡️ Protección de Emergencia contra Ataques DDoS en WordPress

Un ataque DDoS a un sitio WordPress es, lamentablemente, cada vez más común. Este tipo de ataque de saturación consiste en miles de «visitas» falsas desde distintas partes del mundo que sobrecargan tu servidor, consumiendo todos los recursos y evitando que los visitantes reales puedan acceder a tu sitio.

La Solución Recomendada vs. La Solución de Emergencia

La mejor solución a largo plazo para proteger tu sitio es utilizar un servicio como Cloudflare. Sin embargo, si estás bajo ataque en este preciso momento y necesitas una medida de contención inmediata, este tutorial te enseñará a crear una barrera de verificación manual (un «captcha») para frenar el ataque.

Esta técnica es especialmente útil cuando el ataque se concentra en saturar el archivo principal de tu web, el index.php.

⚠️ ¡Importante! Antes de Empezar

  • Necesitarás acceso a tus archivos: Estos pasos se realizan utilizando el «Administrador de Archivos» de tu panel de control (cPanel o DirectAdmin).

Implementando la Protección Paso a Paso

  1. Accede al Administrador de Archivos de tu panel de control y navega a la carpeta raíz de tu sitio WordPress (normalmente es public_html).
  2. Renombra el archivo original: Renombra el index.php original a wp-index.php. Este es el archivo real de WordPress que queremos proteger.
  3. Crea el nuevo archivo de verificación: Crea un archivo completamente nuevo en la misma carpeta y llámalo index.php.
  4. Pega y configura el código: Abre el nuevo index.php que acabas de crear, pega el código que te proporcionamos a continuación.
  5. Importante: Es posible que debas vaciar el caché de tu plugin de caché si utilizas uno.

⚙️ Configurando el Código de Protección

Codigo del archivo index.php para proteger WordPress en un DDoS en vivo:

<?php
/**
 * Script de Protección Anti-DDoS Final (Stateless + Click Manual)
 * 
 * ESTRATEGIA:
 * 1. Stateless: No guarda sesiones (0 consumo RAM/Disco).
 * 2. Time Lock: Obliga a esperar 5 segundos (Castigo de tiempo).
 * 3. JS Proof-of-Work: Obliga a ejecutar JavaScript.
 * 4. Acción Manual: Obliga a un humano a hacer click (Final Boss).
 */

define('WP_INDEX_FILE', 'wp-index.php');
define('SECRET_KEY', md5($_SERVER['HTTP_HOST'] . 'Final_Button_Salt_v5')); 
$site_name = ucfirst(str_replace('www.', '', $_SERVER['HTTP_HOST']));
$admin_ips = []; 

// 1. FAST TRACK (Cookie Firmada - Acceso Directo)
$ip_address = $_SERVER['REMOTE_ADDR'];
$user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$signature_cookie = hash('sha256', $ip_address . $user_agent . SECRET_KEY);

if (isset($_COOKIE['site_access_token']) && $_COOKIE['site_access_token'] === $signature_cookie) {
    if (file_exists(WP_INDEX_FILE)) {
        // HEADERS: Forzar que esta versión (desbloqueada) sea PRIVADA para este usuario.
        // Esto evita que Cloudflare/LSCache la guarden y se la muestren a gente sin cookie.
        header("Cache-Control: private"); 
        header("Vary: Cookie");
        require_once WP_INDEX_FILE;
        exit();
    }
}

// Whitelists
$whitelisted_bots = ['Googlebot', 'Bingbot', 'Slurp', 'DuckDuckBot', 'Baiduspider', 'Yandex'];
foreach ($whitelisted_bots as $bot) { if (stripos($user_agent, $bot) !== false) grant_access($signature_cookie); }
if (in_array($ip_address, $admin_ips)) grant_access($signature_cookie);

// --- 3. ANTI-CACHE (Crucial para evitar loops en Cloudflare/Varnish/LiteSpeed) ---
// Estas cabeceras fuerzan que la página de "Verificación" NUNCA se guarde en caché.
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("X-LiteSpeed-Cache-Control: no-cache"); // Específico para LiteSpeed

// 2. LÓGICA STATELESS (Validación)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $payload_b64 = $_POST['p'] ?? '';
    $client_sig = $_POST['s'] ?? '';
    $sent_answer = intval($_POST['ans'] ?? 0);

    // Verificar Firma
    if (hash_equals(hash_hmac('sha256', $payload_b64, SECRET_KEY), $client_sig)) {
        $payload = json_decode(base64_decode($payload_b64), true);
        if ($payload) {
            // Verificar Tiempo (> 5s para estar seguros, el UI tarda 5s)
            $time_elapsed = time() - $payload['ts'];
            if ($time_elapsed < 5) { // Un poco más estricto ahora que hay botón
                sleep(2);
                $error = "Por favor espera a que la barra termine.";
            } elseif ($sent_answer === (($payload['seed'] * 3) + 27)) {
                grant_access($signature_cookie);
            } else {
                $error = "Error de validación.";
            }
        }
    } else {
        $error = "Sesión inválida.";
    }
}

// Preparar Desafío
$seed = rand(1000, 9999);
$data = ['ts' => time(), 'seed' => $seed];
$payload_b64 = base64_encode(json_encode($data));
$server_sig = hash_hmac('sha256', $payload_b64, SECRET_KEY);

function grant_access($sig) {
    setcookie('site_access_token', $sig, time() + (86400 * 30), "/", "", false, true);
    header("Location: " . $_SERVER['REQUEST_URI']);
    exit();
}

?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Seguridad | <?php echo htmlspecialchars($site_name); ?></title>
    <style>
        body { font-family: system-ui, -apple-system, sans-serif; background: #f0f2f5; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; color: #1c1e21; }
        .card { background: white; padding: 40px; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); text-align: center; width: 90%; max-width: 380px; transition: height 0.3s; }
        
        h2 { font-size: 20px; margin: 0 0 15px; color: #202124; }
        p { font-size: 14px; color: #5f6368; margin: 0 0 20px; line-height: 1.5; }
        
        .loader-track { background: #e8eaed; height: 4px; border-radius: 2px; margin: 25px 0; overflow: hidden; width: 100%; }
        .loader-bar { background: #1a73e8; height: 100%; width: 0%; transition: width 0.1s linear; }
        
        .btn-enter {
            background-color: #1a73e8;
            color: white;
            border: none;
            padding: 12px 24px;
            font-size: 16px;
            font-weight: 500;
            border-radius: 4px;
            cursor: pointer;
            width: 100%;
            display: none; /* Oculto inicialmente */
            transition: background-color 0.2s;
        }
        .btn-enter:hover { background-color: #1557b0; }
        
        .status-text { font-size: 13px; color: #80868b; }
        .error { color: #d93025; background: #fce8e6; padding: 10px; border-radius: 4px; font-size: 13px; margin-bottom: 15px; display: block; }
    </style>
    <script>
        window.onload = function() {
            var seed = <?php echo $seed; ?>;
            var bar = document.getElementById('progress');
            var btn = document.getElementById('btn-enter');
            var status = document.getElementById('status');
            var width = 0;
            var duration = 5000; 
            var interval = 50; 
            var stepSize = 100 / (duration / interval);
            
            var timer = setInterval(function() {
                width += stepSize;
                bar.style.width = width + "%";
                
                if (width >= 100) {
                    clearInterval(timer);
                    // 1. Calcular respuesta
                    document.getElementById('ans').value = (seed * 3) + 27;
                    
                    // 2. UI: Mostrar botón y cambiar texto
                    status.innerText = "Verificación completada.";
                    status.style.color = "#137333";
                    status.style.fontWeight = "bold";
                    btn.style.display = "block";
                    
                    // Opcional: Auto-focus al botón
                    btn.focus();
                }
            }, interval);
        };
    </script>
</head>
<body>
    <div class="card">
        <h2>Protección DDoS</h2>
        
        <?php if (isset($error)): ?>
            <span class="error"><?php echo htmlspecialchars($error); ?></span>
        <?php endif; ?>

        <p>Verificando que eres humano. Por favor espera a que termine la barra.</p>
        
        <div class="loader-track">
            <div id="progress" class="loader-bar"></div>
        </div>
        
        <p id="status" class="status-text">Analizando navegador...</p>

        <form id="challenge_form" method="post" action="">
            <input type="hidden" name="p" value="<?php echo $payload_b64; ?>">
            <input type="hidden" name="s" value="<?php echo $server_sig; ?>">
            <input type="hidden" id="ans" name="ans" value="">
            
            <button type="submit" id="btn-enter" class="btn-enter">Entrar al Sitio</button>
        </form>
    </div>
</body>
</html>

✅ ¿Cómo Funciona y Qué Verán tus Visitantes?

¡Listo! Con estos cambios, la situación será la siguiente:

  • Cualquier visitante nuevo (o bot de ataque) no cargará tu WordPress. En su lugar, verá una página simple con una pregunta matemática. Esto consume una cantidad mínima de recursos del servidor.
  • Una vez que un visitante humano resuelve la suma, el sistema lo recordará y no le volverá a pedir la verificación durante su sesión de navegación.
  • Los bots de buscadores importantes (Google, Bing, etc.) están en una lista blanca para que puedan indexar tu sitio sin problemas y no afectar tu SEO.

Esta es una excelente medida de contención para recuperar el control de tu sitio. Una vez que el ataque haya cesado, te recomendamos investigar e implementar una solución permanente como Cloudflare.

Updated on 27 de enero de 2026

Was this article helpful?

Related Articles

Leave a Comment