在 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 scapy2. 配置 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 是一个非常灵活和可定制的方案,适用于深度定制化的网络流量检测与控制需求。
网友回复


