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

Scapy自定义源地址发送请求失败,排查原因求助

自定义源IP请求未被服务器响应的原因分析

问题背景

在8000端口运行基于python3 -m http.server的Python服务器,尝试用Scapy发送自定义源IP的请求,代码如下:

from scapy.all import IP, TCP, send
from scapy.layers.http import HTTP, HTTPRequest

# Set the source and destination IP addresses
src_ip = "127.0.0.1"  # Custom source IP address
dst_ip = "127.0.0.1"  # Destination IP (your server's IP)
dst_port = 8000  # Port your server is listening on

# Create the IP packet
ip_packet = IP(src=src_ip, dst=dst_ip)

# Create the TCP packet
tcp_packet = TCP(sport=12345, dport=dst_port, flags="S")  # SYN packet

# Send the SYN packet and receive the response
response = send(ip_packet / tcp_packet, verbose=False)

# Check if a response was received
if response:
    src_port = response[TCP].sport
else:
    print("No response received from the server.")
    exit(1)

# Create the HTTP GET request
get_request = HTTP() / HTTPRequest(
    method="GET",
    Path="/",
    Http_Version="HTTP/1.1",
    Host=dst_ip,
    headers={
        "User-Agent": "Mozilla/5.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    },
)

# Create the TCP packet with the HTTP GET request
tcp_packet = TCP(sport=src_port, dport=dst_port, flags="PA") / str(get_request)

# Send the HTTP GET request
send(ip_packet / tcp_packet, verbose=False)

执行后提示"No response received from the server."并退出,服务器端也未接收到任何请求。

核心原因

  • 错误使用send()函数:Scapy的send()仅负责发送数据包,不会监听和接收服务器的响应,因此response始终为None,直接触发退出逻辑。要接收响应,需改用sr1()(接收第一个响应)或sr()(接收所有响应)。
  • TCP三次握手未完成:TCP连接需要三次握手(SYN → SYN-ACK → ACK),当前代码仅发送了SYN包,未处理服务器返回的SYN-ACK包,也未发送ACK包完成握手。服务器在未收到ACK前,不会认为连接建立,自然不会处理后续的HTTP请求。
  • 源端口逻辑错误:即使收到SYN-ACK响应,代码中src_port = response[TCP].sport获取的是服务器的8000端口,而客户端发送后续请求应该使用初始指定的12345作为源端口,这会导致TCP包的端口不匹配,服务器无法识别。
  • HTTP请求构造问题:将get_request转为字符串str(get_request)会破坏Scapy HTTP层的正确格式,直接拼接TCP() / get_request即可,无需转字符串。

修复思路示例

from scapy.all import IP, TCP, sr1, send
from scapy.layers.http import HTTP, HTTPRequest

src_ip = "127.0.0.1"
dst_ip = "127.0.0.1"
dst_port = 8000
client_sport = 12345

# 发送SYN并接收SYN-ACK
syn_packet = IP(src=src_ip, dst=dst_ip) / TCP(sport=client_sport, dport=dst_port, flags="S")
syn_ack_response = sr1(syn_packet, verbose=False)

if not syn_ack_response:
    print("No SYN-ACK received.")
    exit(1)

# 发送ACK完成三次握手
ack_packet = IP(src=src_ip, dst=dst_ip) / TCP(sport=client_sport, dport=dst_port, flags="A", seq=syn_ack_response[TCP].ack, ack=syn_ack_response[TCP].seq + 1)
send(ack_packet, verbose=False)

# 构造并发送HTTP GET请求
get_request = HTTP() / HTTPRequest(
    method="GET",
    Path="/",
    Http_Version="HTTP/1.1",
    Host=dst_ip,
    headers={
        "User-Agent": "Mozilla/5.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    },
)

http_packet = IP(src=src_ip, dst=dst_ip) / TCP(sport=client_sport, dport=dst_port, flags="PA", seq=ack_packet[TCP].seq, ack=ack_packet[TCP].ack) / get_request
send(http_packet, verbose=False)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:58:10