+
29
-

回答

在 Linux 系统中,要检测并阻止特定网络协议(如 HTTP)报文中包含特定关键词的数据返回给客户端,通常需要结合使用内核的包过滤框架(如 Netfilter 的 iptables 或 nftables)和用户空间的程序来进行深度包检测(Deep Packet Inspection, DPI)。

最灵活且功能强大的方法是使用 iptables 的 NFQUEUE 目标,将网络数据包转发到用户空间的应用程序进行分析和处理。以下是实现该功能的详细步骤和说明:

核心思路

内核层面:使用 iptables 或 nftables 规则,将进入的、目标端口为80的HTTP响应流量重定向到一个特定的 NFQUEUE 队列中。这样做可以避免在内核空间进行复杂的字符串匹配,从而保持网络性能。

用户空间层面:编写一个应用程序(通常使用 Python 并借助 NetfilterQueue 和 Scapy 库),该程序会监听指定的 NFQUEUE 队列。

数据包处理

当有数据包进入队列时,用户空间程序会接收到该数据包。

程序解析数据包,提取出 TCP 载荷(payload),即 HTTP 响应的内容。

在 HTTP 响应内容中搜索预定义的关键词。

决策与操作

如果未检测到关键词,则接受(ACCEPT)该数据包,允许其返回给客户端。

如果检测到关键词,则丢弃(DROP)该数据包,从而阻止其到达客户端。

技术实现步骤

1. 安装必要的软件库

首先,需要安装用于与 NFQUEUE 交互和解析数据包的 Python 库。

sudo apt-get update
sudo apt-get install build-essential python3-dev libnetfilter-queue-dev
pip3 install NetfilterQueue scapy
2. 配置 iptables 规则

接下来,需要设置 iptables 规则,将 HTTP 响应流量(通常是来自服务器的80端口)发送到 NFQUEUE。

sudo iptables -I FORWARD -p tcp --sport 80 -j NFQUEUE --queue-num 1

-I FORWARD:在 FORWARD 链的开头插入规则。如果您的 Linux 服务器是作为路由器或网关,流量会经过 FORWARD 链。如果是在本地服务器上阻止对外的请求的响应,可能需要使用 OUTPUT 链。

-p tcp --sport 80:匹配源端口为80的 TCP 协议数据包,这通常是 HTTP 响应。

-j NFQUEUE --queue-num 1:将匹配的数据包跳转到编号为1的 NFQUEUE 队列。

3. 编写 Python 脚本进行关键词检测和阻止

现在,创建一个 Python 脚本来处理 NFQUEUE 队列中的数据包。

http_keyword_blocker.py

import socket
from netfilterqueue import NetfilterQueue
from scapy.all import *

# 定义要阻止的关键词列表
BLOCKED_KEYWORDS = [b"example_keyword_1", b"another_bad_word"]

def process_packet(packet):
    """
    处理每个进入队列的数据包
    """
    try:
        # 将 NetfilterQueue 的数据包转换为 Scapy 的 IP 包
        scapy_packet = IP(packet.get_payload())

        # 检查是否是 TCP 数据包
        if scapy_packet.haslayer(TCP) and scapy_packet.haslayer(Raw):
            # 获取 TCP 载荷
            payload = scapy_packet[Raw].load

            # 搜索关键词
            for keyword in BLOCKED_KEYWORDS:
                if keyword in payload:
                    print(f"[!] Keyword '{keyword.decode()}' found. Dropping packet.")
                    packet.drop()  # 丢弃数据包
                    return

    except Exception as e:
        print(f"Error processing packet: {e}")

    # 如果没有找到关键词,则接受数据包
    packet.accept()


if __name__ == "__main__":
    # 创建一个 NetfilterQueue 实例
    nfqueue = NetfilterQueue()

    # 将队列编号1与处理函数绑定
    nfqueue.bind(1, process_packet)

    try:
        print("Starting HTTP keyword blocker...")
        nfqueue.run()
    except KeyboardInterrupt:
        print("Stopping HTTP keyword blocker.")
    finally:
        nfqueue.unbind()
4. 运行脚本并测试

运行 Python 脚本

sudo python3 http_keyword_blocker.py

脚本会开始监听 NFQUEUE 队列1。

测试:当客户端通过这台 Linux 服务器访问一个包含您设定的关键词(例如 "example_keyword_1")的 HTTP 网站时,您会看到 Python 脚本输出 "Keyword ... found. Dropping packet." 的信息,并且客户端的网页将无法正常加载或显示不完整。不包含这些关键词的网站则可以正常访问。

注意事项和进一步优化

HTTPS 流量:此方法对未加密的 HTTP 流量有效。对于 HTTPS 流量,由于其载荷是加密的,您无法直接检测关键词。要检查 HTTPS 流量,您需要部署一个中间人代理(Man-in-the-Middle Proxy),在服务器上解密流量,检查内容,然后再重新加密并发送给客户端。这是一个更复杂且涉及安全证书管理的过程。

性能:将数据包从内核空间传递到用户空间会带来一定的性能开销。对于高流量网络,需要进行性能测试和优化。

nftables:nftables 是 iptables 的继任者,提供了更强大和一致的语法。您也可以使用 nftables 实现类似的功能。

nft add table inet filter
nft add chain inet filter forward { type filter hook forward priority 0\; }
nft add rule inet filter forward tcp sport 80 queue num 1

清除规则:测试完成后,记得清除 iptables 规则,以恢复正常的网络流量。

sudo iptables -D FORWARD -p tcp --sport 80 -j NFQUEUE --queue-num 1

TCP 流重组:HTTP 响应可能被分割成多个 TCP 包。上述简单的脚本是逐包检查的。对于跨越多个数据包的关键词,您需要在用户空间程序中实现 TCP 流的重组,将属于同一个 TCP 连接的数据包载荷拼接起来再进行搜索。这是一个更高级的主题,可能需要使用更专业的库或自行实现。

其他工具和方法

代理服务器 (Proxy):可以设置像 Squid 这样的代理服务器,并使用其内容过滤功能(如 acl)来根据 URL 或内容中的关键词阻止访问。

专业的深度包检测工具:像 Suricata 或 Snort 这样的入侵检测系统(IDS/IPS)也具备强大的深度包检测能力,可以基于规则集来检测和阻止包含特定内容的流量。

综上所述,使用 iptables/nftables + NFQUEUE + Python 是一个非常灵活和可定制的方案,适用于深度定制化的网络流量检测与控制需求。

网友回复

我知道答案,我要回答