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
相关产品推荐
相关产品推荐

