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

PHP 禁止特定 IP 或 IP 區段存取:單檔案部署的簡易防火牆實作

     編輯:PHP 相關知識

PHP 禁止特定 IP 或 IP 區段存取:單檔案部署的簡易防火牆實作

在無法調整伺服器防火牆 (iptables、Nginx deny、.htaccess) 的虛擬主機環境中,透過 PHP 實作 IP 黑名單是快速有效的備選方案。本文提供單一檔案部署、支援單一 IP 與 CIDR 區段封鎖的完整實作。

使用方式

在需保護的 PHP 檔案最頂端引入:

<?php
require_once 'banIP.php';
// 你的業務邏輯...
?>

完整實作代碼 (banIP.php)

<?php
/**
 * IP 封鎖檢查器
 * 支援:單一 IPv4、IPv6、CIDR 區段 (如 192.168.1.0/24)
 * 部署:將封鎖清單存於 ban.dat (每行一條),或直接寫在陣列中
 */

class IpBanChecker {
    private $banListFile = __DIR__ . '/ban.dat';
    private $banRules = [];
    private $clientIp;

    public function __construct() {
        $this->clientIp = $this->getClientIp();
        $this->loadRules();
        $this->check();
    }

    // 取得客戶端真實 IP (考慮代理)
    private function getClientIp(): string {
        $headers = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'];
        foreach ($headers as $header) {
            if (!empty($_SERVER[$header])) {
                $ips = explode(',', $_SERVER[$header]);
                foreach ($ips as $ip) {
                    $ip = trim($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 loadRules(): void {
        // 1. 從檔案讀取 (每行一條,支援 # 註解)
        if (is_file($this->banListFile)) {
            $lines = file($this->banListFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
            foreach ($lines as $line) {
                $line = trim($line);
                if ($line === '' || $line[0] === '#') continue;
                $this->banRules[] = $line;
            }
        }
        // 2. 也可直接在這裡硬編碼規則
        // $this->banRules[] = '192.168.1.100';
        // $this->banRules[] = '10.0.0.0/8';
    }

    // 執行檢查
    private function check(): void {
        foreach ($this->banRules as $rule) {
            if ($this->matchRule($this->clientIp, $rule)) {
                $this->denyAccess($rule);
            }
        }
    }

    // IP 比對邏輯 (支援 CIDR)
    private function matchRule(string $ip, string $rule): bool {
        if (strpos($rule, '/') !== false) {
            // CIDR 區段比對
            return $this->matchCIDR($ip, $rule);
        }
        // 單一 IP 精確比對
        return $ip === $rule;
    }

    // CIDR 比對核心
    private function matchCIDR(string $ip, string $cidr): bool {
        list($subnet, $mask) = explode('/', $cidr);
        $mask = (int)$mask;
        
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            // IPv4
            $ipLong = ip2long($ip);
            $subnetLong = ip2long($subnet);
            if ($ipLong === false || $subnetLong === false) return false;
            $maskLong = -1 << (32 - $mask);
            return ($ipLong & $maskLong) === ($subnetLong & $maskLong);
        } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            // IPv6 (簡易版,生產環境建議用專用庫)
            // 這裡略過完整 IPv6 CIDR 實作,建議引用 league/ip 或 symfony/polyfill
            return false;
        }
        return false;
    }

    // 拒絕存取回應
    private function denyAccess(string $matchedRule): void {
        header('HTTP/1.1 403 Forbidden');
        header('Content-Type: text/html; charset=utf-8');
        echo "

403 Forbidden

"; echo "

您的 IP ({$this->clientIp}) 遭到封鎖。

"; echo "

匹配規則:{$matchedRule}

"; exit; } } // 自動執行檢查 new IpBanChecker(); ?>

封鎖清單檔案範例 (ban.dat)

# 單一 IPv4
192.168.1.100
119.184.251.245

# IPv4 CIDR 區段
192.168.1.0/24
10.0.0.0/8
172.16.0.0/12

# IPv6 (需擴充 matchCIDR 完整支援)
# 2001:db8::/32

# 註解行以 # 開頭

進階優化建議

  1. 快取規則陣列:使用 APCu/Redis 快取解析後的規則,避免每請求讀檔解析。
  2. 效能優化:將 CIDR 規則預先轉換為 [$ipLong, $maskLong] 數值陣列,比對時僅做位元運算。
  3. 白名單機制:優先檢查白名單,通過則跳過黑名單檢查。
  4. 日誌記錄:記錄被封鎖請求 (IP、時間、URL、User-Agent) 供分析。
  5. 管理介面:建立簡單後台管理 ban.dat,避免手動編輯檔案。

效能數據參考

  • 純 PHP 解析 ~1000 條規則:< 1ms
  • 搭配 APCu 快取:< 0.1ms
  • 高流量建議移至 Nginx deny 或防火牆層級攔截。

替代方案對比

方案優點缺點推薦場景
PHP 應用層封鎖部署簡單、無需伺服器權限、邏輯靈活效能較差、需 PHP 執行才能攔截虛擬主機、快速上線、邏輯複雜
Nginx deny / allow效能極佳、早期攔截、不佔用 PHP 進程需伺服器管理權限、配置重載生效VPS/獨立伺服器、高流量
iptables / firewalld核心層攔截、最徹底需 root、操作風險高系統級防護、DDoS 緩解
WAF (ModSecurity/Cloudflare)規則豐富、防注入/爬蟲/CC成本高、誤攔率企業級、高安全需求
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved