Linux下如何配置Python L2层Socket阻止捕获数据包进入网络
Linux下L2层拦截并阻止数据包传输的解决方案
先澄清混杂模式的误区
混杂模式仅用于让网卡接收所有经过的以太网帧(包括目标MAC不是本机的帧),它没有阻止数据包传输的功能——内核依然会正常处理这些捕获到的包,将其递交给上层协议栈或转发至网络。你的问题核心是需要拦截并丢弃数据包,而非单纯捕获。
推荐方案:结合iptables与NetfilterQueue精准拦截
NetfilterQueue可以让你介入Linux内核的数据包处理流程,捕获指定规则的数据包并决定是否放行/丢弃/修改,是实现L2层拦截阻断的可靠方式。
步骤1:安装依赖
# 安装系统库 sudo apt install libnetfilter-queue-dev python3-pip # 安装Python绑定库 pip3 install netfilterqueue
步骤2:配置iptables规则
将目标数据包导向Netfilter队列(示例为拦截进入eth0的所有IPv4数据包):
sudo iptables -A INPUT -i eth0 -j NFQUEUE --queue-num 1
如果需要拦截转发的数据包,可添加:
sudo iptables -A FORWARD -i eth0 -j NFQUEUE --queue-num 1
步骤3:Python拦截代码
通过NetfilterQueue捕获数据包并丢弃(阻止进入网络):
from netfilterqueue import NetfilterQueue import scapy.all as scapy def handle_packet(packet): # 解析数据包(可选,用于判断是否需要阻断) scapy_pkt = scapy.IP(packet.get_payload()) print(f"捕获到数据包: {scapy_pkt.summary()}") # 丢弃数据包,阻止其进入网络 packet.drop() # 若需放行特定包,替换为 packet.accept() if __name__ == "__main__": nfqueue = NetfilterQueue() # 绑定到队列号1,与iptables规则对应 nfqueue.bind(1, handle_packet) try: print("开始拦截数据包...按Ctrl+C停止") nfqueue.run() except KeyboardInterrupt: print("\n停止拦截") finally: nfqueue.unbind() # 可选:清空iptables规则 # import subprocess # subprocess.run(["sudo", "iptables", "-F"])
注意:需以
sudo权限运行代码,因为操作Netfilter和iptables需要管理员权限。
替代方案:关闭网卡转发(粗暴阻断)
如果仅需整体阻止网卡转发数据包,可直接关闭系统转发功能:
# 临时关闭IPv4转发 sudo sysctl -w net.ipv4.ip_forward=0 # 永久关闭(需重启生效) echo "net.ipv4.ip_forward=0" | sudo tee -a /etc/sysctl.conf
这种方式适合全局阻断,但无法精准控制单个数据包的放行/丢弃。
修正你的混杂模式配置(若仍需捕获更多数据包)
如果需要保留混杂模式以捕获非本机目标的数据包,可使用更简洁的fcntl实现:
import fcntl import socket def toggle_promiscuous(iface, enable=True): SIOCGIFFLAGS = 0x8913 SIOCSIFFLAGS = 0x8914 IFF_PROMISC = 0x100 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 构造ifreq结构体数据 ifr = iface.encode() + b'\x00' * (16 - len(iface)) # 获取当前网卡标志 flags = fcntl.ioctl(sock.fileno(), SIOCGIFFLAGS, ifr)[16:18] current_flags = int.from_bytes(flags, byteorder='little') if enable: new_flags = current_flags | IFF_PROMISC else: new_flags = current_flags & ~IFF_PROMISC # 设置新的网卡标志 ifr = iface.encode() + b'\x00'*(16 - len(iface)) + new_flags.to_bytes(2, byteorder='little') fcntl.ioctl(sock.fileno(), SIOCSIFFLAGS, ifr) sock.close() # 开启eth0的混杂模式 toggle_promiscuous("eth0")
内容的提问来源于stack exchange,提问作者KeisyKeij
相关产品推荐
相关产品推荐

