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

使用Python+Scapy向本地地址发送UDP数据包失败问题排查

问题原因

在Ubuntu系统中,Scapy的send()/sendp()等默认发送函数依赖原始套接字传输数据包。当目标为本地回环地址(127.0.0.1)时,Scapy可能错误地选择非回环接口发送,导致二层目的地址被设为组播/广播地址。而netcat这类常规监听程序是通过标准套接字监听回环栈的数据包,仅能接收符合单播格式的回环数据包,因此无法捕获Scapy直接发送的原始套接字包。

另外,Scapy自身的监听功能(如sniff())同样基于原始套接字,所以能接收到自己发送的数据包,这和netcat的监听机制存在本质差异。

解决方法

以下两种方式可直接解决问题:

1. 强制指定回环接口发送

调用Scapy发送函数时,通过iface="lo"参数强制数据包从回环接口发送,此时二层地址会自动匹配回环接口的单播MAC地址,符合系统常规监听程序的接收逻辑。修改后的代码如下:

from scapy.all import *

if __name__ == "__main__":
    send(IP(dst="127.0.0.1")/UDP(sport=19600,dport=39600)/"abc", iface="lo")

2. 使用标准套接字发送(兼容常规监听逻辑)

如果无需构造复杂数据包,可直接用Python标准库socket模块发送,完全走系统回环栈,和netcat的发送逻辑一致:

import socket

if __name__ == "__main__":
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(b"abc", ("127.0.0.1", 39600))
    sock.close()

若需要用Scapy构造复杂数据包再通过标准套接字发送,可将Scapy构造的数据包转换为字节流后发送(注意跳过Scapy的IP层,由标准套接字自动处理):

from scapy.all import *
import socket

if __name__ == "__main__":
    pkt = IP(dst="127.0.0.1")/UDP(sport=19600,dport=39600)/"abc"
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(bytes(pkt[UDP]), ("127.0.0.1", 39600))
    sock.close()

内容的提问来源于stack exchange,提问作者Pavel Siderov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 06:30:37