You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:如何用Python实现无状态网络函数的数据包过滤与转发

嘿,你已经搞定了数据包捕获和合法性校验的核心部分,接下来要实现转发合法包、丢弃非法包的逻辑其实没那么复杂,我给你拆解下思路,再附上修改后的代码示例:

关键实现思路

1. 非法包的“丢弃”逻辑

其实你现在的代码已经天然实现了丢弃功能——当你用AF_PACKET类型的原始套接字捕获数据包后,默认不会把数据包传递给系统的上层协议栈,所以只要你不对非法包做任何转发操作,它就会直接被丢弃,不需要额外处理~

2. 合法包的转发实现

转发需要我们重新构造可发送的数据包,这里推荐数据链路层转发的方案(更贴合你当前的代码逻辑):

  • 首先要获取当前监听网卡的MAC地址(作为转发包的源MAC)
  • 找到目标IP对应的下一跳网关MAC(作为转发包的目的MAC)
  • 修改原始数据包的以太网帧头,替换成新的源/目的MAC
  • 创建一个发送用的原始套接字,把修改后的数据包发送出去
修改后的完整代码示例
import socket
import sys
from struct import unpack, pack
from scapy.all import get_if_hwaddr, getmacbyip  # 用scapy快速获取MAC,避免手动解析ARP

# 初始化监听套接字
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))
# 配置网络参数(根据你的实际环境修改)
INTERFACE = "eth0"  # 监听的网卡名称,比如eth0、wlan0
GATEWAY_IP = "192.168.0.1"  # 网络网关IP

# 获取网卡MAC和网关MAC
iface_mac = get_if_hwaddr(INTERFACE)
gateway_mac = getmacbyip(GATEWAY_IP)

allowed_services = [80, 443]
allowed_hosts = [f'192.168.0.{x}' for x in range(1, 11)]  # 允许192.168.0.1-10

def forward_packet(original_packet, src_mac, dst_mac):
    # 拆解原始以太网帧头
    eth_header = original_packet[:14]
    eth = unpack('!6s6sH', eth_header)
    eth_protocol = eth[2]
    
    # 构造新的以太网帧头:替换源MAC和目的MAC
    new_eth_header = pack('!6s6sH', bytes.fromhex(dst_mac.replace(':', '')), 
                          bytes.fromhex(src_mac.replace(':', '')), eth_protocol)
    # 拼接新帧头和原始数据包的负载部分
    new_packet = new_eth_header + original_packet[14:]
    
    # 创建发送套接字并发送数据包
    send_sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))
    send_sock.bind((INTERFACE, 0))
    send_sock.send(new_packet)
    send_sock.close()

while True:
    try:
        packet = s.recvfrom(65565)[0]
        eth_length = 14
        eth_header = packet[:eth_length]
        eth = unpack('!6s6sH', eth_header)
        eth_protocol = socket.ntohs(eth[2])
        
        # 处理IP数据包(协议号8)
        if eth_protocol == 8:
            ip_header = packet[eth_length:20+eth_length]
            iph = unpack('!BBHHHBBH4s4s', ip_header)
            version_ihl = iph[0]
            ihl = version_ihl & 0xF
            iph_length = ihl * 4
            protocol = iph[6]
            saddr = socket.inet_ntoa(iph[8])
            daddr = socket.inet_ntoa(iph[9])
            
            # 处理TCP数据包(协议号6)
            if protocol == 6:
                t = iph_length + eth_length
                tcp_header = packet[t:t+20]
                tcph = unpack('!HHLLBBHHH', tcp_header)
                sport = tcph[0]
                dport = tcph[1]
                
                # 判断数据包是否合法
                is_valid = (daddr in allowed_hosts and dport in allowed_services) or \
                           (saddr in allowed_hosts and sport in allowed_services)
                
                if is_valid:
                    print(f'Good TCP packet from {saddr} -> Forwarding')
                    forward_packet(packet, iface_mac, gateway_mac)
                else:
                    print(f'Bad Packet from {saddr} -> Dropping (Verify IP/Port)')
                print('---------------------------------------------------------------\n')
    except KeyboardInterrupt:
        print("\nStopping packet capture...")
        s.close()
        sys.exit(0)
注意事项
  • 运行脚本需要root权限(执行sudo python3 your_script.py),因为原始套接字需要系统级权限
  • 依赖scapy库,需要先安装:pip install scapy
  • 请务必根据你的实际网络环境修改INTERFACE和GATEWAY_IP参数
  • 如果不想依赖scapy,也可以自己实现ARP请求逻辑来获取网关MAC,只是会多写一些代码

内容的提问来源于stack exchange,提问作者João Barraca Filipe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:40:57