首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 防 DDoS、DNS 劫持、叢集攻擊的應用層緩解策略

     編輯:PHP 綜合知識

前言

DDoS、DNS 劫持、叢集攻擊屬於網路/傳輸層與基礎設施層威脅,PHP 應用層無法從根源阻斷,但可通過應用層識別、限流、降級、熔斷、蜜罐、日誌審計等手段緩解影響、保護核心業務可用性。本文提供可直接落地的 PHP 代碼與架構策略。

威脅模型與應用層可見症狀

攻擊類型網路層特徵應用層可見症狀PHP 可做什麼
體積型 DDoS (UDP/ICMP/SYN Flood)頻寬耗盡、連接表滿請求超時、502/504、PHP-FPM 進程耗盡快速拒絕、靜態化、熔斷下游
應用層 DDoS (CC 攻擊、HTTP Flood)大量合法 HTTP 請求CPU/記憶體飆升、資料庫連接池耗盡、業務邏輯阻塞多維限流、驗證碼、請求去重、緩存穿透防護
DNS 劫持/投毒域名解析到惡意 IP用戶訪問被導向釣魚站、流量劫持HSTS、HPKP、子資源完整性 (SRI)、客戶端憑證綁定
叢集/僵屍網絡協同攻擊分散式 IP、低頻慢速傳統單 IP 限流失效、行為異常難檢測裝置指紋、行為分析、風控引擎、蜜罐陷阱

核心代碼模組:多維度請求守衛

<?php
/**
 * 應用層防禦中介軟體(可整合至 Laravel/ThinkPHP/Yii/Slim/原生)
 */
class AppDefense {
    private Redis $redis;
    private array $config;

    public function __construct(Redis $redis, array $config = []) {
        $this->redis = $redis;
        $this->config = array_merge([
            'ip_whitelist' => [],
            'ip_blacklist_ttl' => 3600,
            'rate_limit' => [
                'global' => [1000, 60],      // 全站:1000 req/min
                'per_ip' => [60, 60],        // 單 IP:60 req/min
                'per_ip_uri' => [20, 60],    // 單 IP+URI:20 req/min
                'login' => [5, 300],         // 登入:5 req/5min
                'register' => [3, 3600],     // 註冊:3 req/hr
            ],
            'ban_threshold' => 100,          // 觸發封禁的違規次數
            'ban_duration' => 1800,          // 封禁 30 分鐘
            'honeypot_fields' => ['website', 'url', 'homepage'], // 蜜罐欄位名
        ], $config);
    }

    /** 主入口:在路由分發前調用 */
    public function handle(): void {
        $ip = $this->getRealIp();
        $uri = $_SERVER['REQUEST_URI'] ?? '/';
        $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

        // 1. 白名單直通
        if (in_array($ip, $this->config['ip_whitelist'], true)) return;

        // 2. 黑名單攔截
        if ($this->redis->exists("ban:ip:$ip")) {
            $this->respond(403, 'IP 已被封禁');
        }

        // 3. 蜜罐檢測(隱藏表單欄位若被填寫 = 機器人)
        if ($method === 'POST') {
            foreach ($this->config['honeypot_fields'] as $field) {
                if (!empty($_POST[$field] ?? '')) {
                    $this->recordViolation($ip, 'honeypot');
                    $this->respond(403, 'Forbidden');
                }
            }
        }

        // 4. 多維滑動窗口限流
        $limits = $this->config['rate_limit'];
        $this->checkLimit("ratelimit:global", $limits['global'][0], $limits['global'][1]);
        $this->checkLimit("ratelimit:ip:$ip", $limits['per_ip'][0], $limits['per_ip'][1]);
        $this->checkLimit("ratelimit:ip_uri:$ip:$uri", $limits['per_ip_uri'][0], $limits['per_ip_uri'][1]);

        // 5. 敏感操作專用限流
        if (str_contains($uri, '/login')) {
            $this->checkLimit("ratelimit:login:$ip", $limits['login'][0], $limits['login'][1]);
        }
        if (str_contains($uri, '/register')) {
            $this->checkLimit("ratelimit:register:$ip", $limits['register'][0], $limits['register'][1]);
        }

        // 6. 記錄存活心跳(用於事後分析)
        $this->redis->zAdd("alive:ip:$ip", microtime(true), microtime(true));
        $this->redis->expire("alive:ip:$ip", 300);
    }

    /** Redis 滑動窗口限流 */
    private function checkLimit(string $key, int $limit, int $window): void {
        $now = microtime(true);
        $pipe = $this->redis->pipeline();
        $pipe->zRemRangeByScore($key, 0, $now - $window);
        $pipe->zCard($key);
        $pipe->zAdd($key, $now, (string)$now);
        $pipe->expire($key, $window + 1);
        $results = $pipe->exec();
        if ($results[1] >= $limit) {
            $this->recordViolation($this->getRealIp(), 'ratelimit');
            $this->respond(429, '請求過於頻繁,請稍後再試');
        }
    }

    /** 違規記錄與自動封禁 */
    private function recordViolation(string $ip, string $type): void {
        $key = "violation:ip:$ip";
        $count = $this->redis->incr($key);
        if ($count === 1) $this->redis->expire($key, 86400); // 24 小時統計窗
        
        if ($count >= $this->config['ban_threshold']) {
            $this->redis->setex("ban:ip:$ip", $this->config['ban_duration'], $type);
            error_log("AUTO-BAN IP: $ip, type: $type, count: $count");
        }
    }

    /** 獲取真實客戶端 IP(支援代理鏈) */
    private function getRealIp(): string {
        $headers = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP'];
        foreach ($headers as $h) {
            if (!empty($_SERVER[$h])) {
                $ips = array_map('trim', explode(',', $_SERVER[$h]));
                foreach ($ips as $ip) {
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                        return $ip;
                    }
                }
            }
        }
        return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    }

    /** 統一響應並終止 */
    private function respond(int $code, string $msg): void {
        http_response_code($code);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['error' => $msg, 'code' => $code]);
        exit;
    }
}

// 使用範例(原生 PHP 入口)
require 'vendor/autoload.php';
$redis = new Redis(); $redis->connect('127.0.0.1', 6379);
$defense = new AppDefense($redis);
$defense->handle();
// 之後才執行路由/業務邏輯
?>

架構層面緩解策略

1. 靜態化與邊緣緩存(抗體積型 DDoS 核心)

  • 全站靜態頁面推送至 CDN(Cloudflare、CloudFront、阿里雲 CDN)
  • 動態 API 採用 Cache-Control: public, max-age=10, stale-while-revalidate=60
  • CDN 開啟「Under Attack 模式」(5 秒 JS 挑戰)

2. 服務降級與熔斷

<?php
// 熔斷器簡易實現
class CircuitBreaker {
    private Redis $redis;
    public function __construct(Redis $redis) { $this->redis = $redis; }

    public function call(string $service, callable $fn, callable $fallback) {
        $key = "circuit:$service";
        $state = $this->redis->get($key) ?: 'closed'; // closed/open/half-open
        
        if ($state === 'open') {
            // 檢查是否進入半開狀態
            if ($this->redis->ttl($key) < 10) {
                $this->redis->set($key, 'half-open', 'EX', 30);
            } else {
                return $fallback();
            }
        }

        try {
            $result = $fn();
            if ($state === 'half-open') $this->redis->del($key); // 恢復
            return $result;
        } catch (Throwable $e) {
            $failures = $this->redis->incr("$key:fails");
            if ($failures >= 5) {
                $this->redis->set($key, 'open', 'EX', 60); // 熔斷 60 秒
            }
            return $fallback();
        }
    }
}

// 使用
$breaker = new CircuitBreaker($redis);
$userInfo = $breaker->call('user-service', 
    fn() => $httpClient->get("/api/user/$uid"),
    fn() => ['id' => $uid, 'name' => 'Guest', 'degraded' => true] // 降級回退
);
?>

3. DNS 劫持防護(客戶端 + 伺服端雙重)

層面措施
伺服端強制 HTTPS + HSTS (Strict-Transport-Security: max-age=31536000; includeSubDomains; preload)
伺服端HPKP (Public Key Pinning) —— 風險高,謹慎用
前端Subresource Integrity (SRI):<script src="..." integrity="sha384-..." crossorigin="anonymous">
前端CSP 禁止內聯腳本、限制來源域名
App/小程序憑證綁定、域名白名單、偵測 DNS 解析異常彈窗提示

4. 蜜罐與主動誘捕

  • 隱藏表單欄位(CSS display:none、visibility:hidden、偏移視窗外)
  • 偽造管理後台路徑 /admin/login.php、/phpmyadmin/ 記錄掃描者 IP
  • 偽造 API 端點 /api/v1/users/export 回傳假資料、記錄請求
  • 將蜜罐觸發 IP 直接加入黑名單、同步威脅情報平台

監控與告警指標

指標正常基線告警閾值響應
QPS (請求/秒)業務相關> 基線 3 倍啟用 Under Attack、擴容 PHP-FPM
PHP-FPM 活躍進程數< pm.max_children> 80%調優慢查詢、啟用靜態化、限流
資料庫連接數< max_connections> 80%啟用連接池、讀寫分離、熔斷
錯誤率 (5xx)< 0.1%> 1%檢查日誌、回滾發布、熔斷下游
獨立 IP 數/分鐘業務相關突增 5 倍疑似 CC 攻擊、啟用驗證碼、封禁異常 IP 段

總結

PHP 應用層無法「防禦」DDoS/DNS 劫持,但能通過識別異常流量、限流保護核心資源、熔斷防止雪崩、靜態化轉移壓力、蜜罐主動誘捕、日誌留存溯源將影響降至最低。真正的抗 DDoS 必須在網路邊界(Anycast 清洗、CDN 邊緣吸收、WAF 規則攔截)解決。建議:應用層代碼作為「最後一道防線」,基礎設施層作為「主戰場」,兩者配合定期壓測、紅藍對抗演練,構建韌性架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved