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

結合 Snort 與 PHP 構建自動化網絡入侵阻擋系統:架構設計與關鍵代碼實現

     編輯:PHP 綜合知識

系統目標

  • 即時接收 Snort IDS 警報 (Unix Domain Socket)
  • 解析攻擊源 IP、攻擊類型、嚴重度
  • 自動下發 iptables 規則封鎖來源 IP (可配置封鎖時長)
  • 提供 PHP Web 管理介面:查看封鎖列表、手動解封、調整策略
  • 高併發、高可靠:服務進程獨立於 Snort,採用多線程/多進程模型

整體架構

+----------------+     Unix Socket      +------------------+     iptables      +----------+
|   Snort IDS    | ───────────────────▶ |  PHP Daemon      | ────────────────▶ |  Kernel  |
|  (Alert Output)|   Alertpkt 結構體    |  (AO_Handler)    |   ipset/iptables  |  Netfilter|
+----------------+                      |  (Block_Handler) |                   +----------+
                                       |  (Web_Handler)   |                      ▲
                                       +------------------+                      │
                                              ▲                                 │
                                              │ HTTP/JSON                        │
                                              ▼                                 │
                                       +------------------+
                                       |  PHP Web UI      |
                                       |  (Admin Panel)   |
                                       +------------------+

核心資料結構 (C 風格對應 PHP 陣列)


// Alertpkt 關鍵欄位 (Snort spo_alert_unixsock.h)
$alert = [
    'msg'        => 'ATTACK-RESPONSES id check returned root', // 警報訊息
    'pkt'        => [ ... ], // pcap_pkthdr + 原始封包
    'event'      => [
        'sid'      => 1234,      // 規則 SID
        'gid'      => 1,
        'rev'      => 5,
        'classification' => 2,   // 攻擊分類
        'priority' => 1,         // 優先級
        'timestamp' => 1700000000,
    ],
    'ip_src'     => '192.168.1.100',
    'ip_dst'     => '10.0.0.50',
    'port_src'   => 54321,
    'port_dst'   => 80,
    'proto'      => 6, // TCP
];

PHP Daemon 關鍵代碼骨架 (Swoole 4.8+ 協程版)

<?php
// daemon.php
use Swoole\Process;
use Swoole\Coroutine;
use Swoole\Coroutine\Socket;

$snortSockPath = '/var/log/snort_alert';
$adminSockPath = '/var/run/ids_admin.sock';
$blockTTL      = 3600; // 秒

// 共享記憶體表:封鎖列表 IP => 過期時間戳
$blockTable = new Swoole\Table(1024);
$blockTable->column('expire', Swoole\Table::TYPE_INT);
$blockTable->create();

// ---------- 1. Snort 警報接收協程 ----------
Coroutine::create(function () use ($snortSockPath, $blockTable, $blockTTL) {
    $sock = new Socket(AF_UNIX, SOCK_DGRAM, 0);
    $sock->bind($snortSockPath);
    echo "[AO_Handler] Listening on $snortSockPath\n";

    while (true) {
        $data = $sock->recv(65535);
        if ($data === false) continue;
        $alert = parseAlertpkt($data); // 解析二進制結構體
        if (!$alert) continue;

        $ip = $alert['ip_src'];
        // 白名單檢查
        if (in_array($ip, ['10.0.0.1', '127.0.0.1'])) continue;

        // 原子檢查並加入封鎖表
        if (!$blockTable->exist($ip)) {
            $expire = time() + $blockTTL;
            $blockTable->set($ip, ['expire' => $expire]);
            // 下發 iptables 規則 (非阻塞)
            exec("ipset add blacklist $ip timeout $blockTTL 2>/dev/null || iptables -I INPUT -s $ip -j DROP");
            syslog(LOG_INFO, "[IDS] Blocked $ip for {$blockTTL}s: {$alert['msg']}");
        }
    }
});

// ---------- 2. 封鎖過期清理協程 ----------
Coroutine::create(function () use ($blockTable) {
    while (true) {
        Coroutine::sleep(60);
        foreach ($blockTable as $ip => $row) {
            if ($row['expire'] < time()) {
                $blockTable->del($ip);
                exec("ipset del blacklist $ip 2>/dev/null || iptables -D INPUT -s $ip -j DROP");
                syslog(LOG_INFO, "[IDS] Unblocked expired $ip");
            }
        }
    }
});

// ---------- 3. Web 管理 API (HTTP Server) ----------
$http = new Swoole\Http\Server('0.0.0.0', 9501);
$http->on('Request', function ($req, $resp) use ($blockTable) {
    $resp->header('Content-Type', 'application/json');
    $path = $req->server['request_uri'];

    if (preg_match('#^/api/blocks$#', $path)) {
        $list = [];
        foreach ($blockTable as $ip => $row) {
            $list[] = ['ip' => $ip, 'expire' => $row['expire'], 'remaining' => max(0, $row['expire'] - time())];
        }
        $resp->end(json_encode(['blocks' => $list]));
    } elseif (preg_match('#^/api/unblock/(\d+\.\d+\.\d+\.\d+)$#', $path, $m)) {
        $ip = $m[1];
        if ($blockTable->exist($ip)) {
            $blockTable->del($ip);
            exec("ipset del blacklist $ip 2>/dev/null || iptables -D INPUT -s $ip -j DROP");
            $resp->end(json_encode(['success' => true]));
        } else {
            $resp->status(404);
            $resp->end(json_encode(['error' => 'Not blocked']));
        }
    } else {
        $resp->status(404);
        $resp->end(json_encode(['error' => 'Not found']));
    }
});
$http->start();

function parseAlertpkt(string $data): ?array {
    // 實際需根據 Snort 版本 unpack Alertpkt 結構體
    // 此處略過二進制解析,假設返回關鍵陣列
    return [
        'msg'    => '...',
        'ip_src' => '192.168.1.' . random_int(1, 254),
        // ...
    ];
}

關鍵技術點解析

模組技術選型理由
Snort 輸出output alert_unixsock低延遲、無磁盤 I/O、易於程式讀取
封鎖載體ipset + iptablesipset 批量操作 O(1)、支援 timeout 自動過期、效能優於純 iptables
Daemon 框架Swoole 協程單進程高併發、原生 Unix Socket/HTTP Server、共享記憶體表免鎖
資料同步Swoole\Table進程間無鎖讀寫、自動過期掃描
權限Daemon 需 root (iptables) / Web UI 以 www-data 通過 Unix Socket 與 Daemon 通訊最小權限原則

Web 管理介面 (Vue 3 + Axios 片段)

<template>
  <div class="container">
    <h2>當前封鎖列表 (<span class="badge">{{ blocks.length }}</span>)</h2>
    <table class="table">
      <thead><tr><th>IP</th><th>剩餘秒數</th><th>操作</th></tr></thead>
      <tbody>
        <tr v-for="b in blocks" :key="b.ip">
          <td>{{ b.ip }}</td>
          <td>{{ b.remaining }}s</td>
          <td><button @click="unblock(b.ip)" class="btn btn-danger btn-sm">解封</button></td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const blocks = ref([])
async function load() { blocks.value = (await axios.get('/api/blocks')).data.blocks }
async function unblock(ip) { await axios.post('/api/unblock/' + ip); load() }
onMounted(() => { load(); setInterval(load, 5000) })
</script>

部署與運維清單

  1. Snort 配置:`output alert_unixsock` → 重啟 Snort。
  2. 建立 ipset:`ipset create blacklist hash:ip timeout 3600`;`iptables -I INPUT -m set --match-set blacklist src -j DROP`。
  3. Daemon 以 systemd 服務運行 (User=root, Capability=CAP_NET_ADMIN)。
  4. Web UI 反向代理 Nginx + HTTPS + Basic Auth / OAuth2 Proxy。
  5. 日誌輪轉:`/var/log/ids_daemon.log` 配置 logrotate。
  6. 監控:Prometheus 抓取 `/metrics` (Swoole 內建) + Grafana 儀表板 (封鎖數、警報率、CPU/記憶體)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved