TCP三次握手以及发送http请求示例
知识点
源IP 源端口 目标IP 目标端口
sourceIP sou PORT des IP des PORT
A浏览器 Bweb服务器
A-IP 随机端口 B-IP 80 syn(问) flags=S 直接构造会收到SA回包
B-IP 80 A-IP 随机端口 ACK(答)+SYN flags=SA 直接构造会收到RST回包
A-IP 随机端口 B-IP 80 ack flags=A 直接构造会收到RST回包
A-IP 随机端口 B-IP 80 TCP(HTTP REQUEST)
B-IP 80 A-IP 随机端口 TCP (HTTP REPLY)
三次握手过程
客户端 → 服务器 :发送 SYN 包
→ 表示请求建立连接
→ 携带:SYN=1, seq=x (x 是客户端随机初始化的序列号)
服务器 → 客户端 :发送 SYN-ACK 包
→ 表示同意建立连接
→ 携带:SYN=1, ACK=1, seq=y (服务端也生成自己的随机 seq),ack=x+1(确认客户端的 seq)
客户端 → 服务器 :发送 ACK 包
→ 表示确认收到了服务端的 SYN-ACK
→ 携带:ACK=1, seq=x+1, ack=y+1
代码如下
from scapy.all import *
target_ip = "180.101.49.44"
target_port = 22
# 1. 发送SYN
syn_pkt = IP(dst=target_ip)/TCP(dport=target_port, flags="S", sport=RandShort())
print("发送 SYN 包...")
syn_ack_resp = sr1(syn_pkt, timeout=3, verbose=1)
if syn_ack_resp and syn_ack_resp.haslayer(TCP) and syn_ack_resp[TCP].flags == 0x12: # SA标志
print("收到 SYN-ACK 响应!")
# 2. 发送ACK
ack_pkt = IP(dst=target_ip)/TCP(
dport=target_port,
sport=syn_pkt[TCP].sport, # 使用相同的源端口
flags="A",
seq=syn_ack_resp[TCP].ack, # 序列号应为对方确认号
ack=syn_ack_resp[TCP].seq + 1 # 确认号应为对方序列号+1
)
print("发送 ACK 包完成三次握手...")
# 增加超时时间到5秒,等待可能的后续数据
final_response = sr1(ack_pkt, timeout=5, verbose=1)
if final_response:
print("连接已建立!收到后续数据:")
final_response.show()
else:
print("ACK已发送。连接可能已建立,但未收到后续数据。")
else:
print("未收到SYN-ACK响应,握手失败。")
DROP掉RST包命令sudo iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
完整TCP握手+HTTP
from scapy.all import *
import random
target_ip = "47.117.47.208"
target_port = 80
source_port = random.randint(1024, 65535)
ip = IP(dst=target_ip)
syn = ip / TCP(sport=source_port, dport=target_port, flags="S", seq=1000)
syn_ack = sr1(syn, timeout=2, verbose=0)
server_seq = syn_ack[TCP].seq
server_ack = syn_ack[TCP].ack
ack = ip / TCP(sport=source_port, dport=target_port, flags="A", seq=server_ack, ack=server_seq + 1)
send(ack, verbose=0)
http_get = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n"
http_payload = raw(http_get.encode("UTF-8"))
get_request = ip / TCP(sport=source_port, dport=target_port, flags="PA", seq=server_ack, ack=server_seq + 1) / http_payload
response = sr1(get_request, timeout=5, verbose=0)
完整解释
from scapy.all import * # 导入Scapy网络包处理库
import random # 导入随机数生成模块
target_ip = "47.117.47.208" # 设置目标服务器IP地址
target_port = 80 # 设置HTTP服务默认端口
source_port = random.randint(1024, 65535) # 随机生成客户端源端口
ip = IP(dst=target_ip) # 创建IP层数据包,目标地址为target_ip
syn = ip / TCP(sport=source_port, dport=target_port, flags="S", seq=1000) # 构造SYN包,flags="S"表示SYN标志,seq设置初始序列号
syn_ack = sr1(syn, timeout=2, verbose=0) # 发送SYN包并等待响应,timeout设置2秒超时,verbose=0关闭输出
server_seq = syn_ack[TCP].seq # 从服务端响应包中提取序列号
server_ack = syn_ack[TCP].ack # 从服务端响应包中提取确认号
ack = ip / TCP(sport=source_port, dport=target_port, flags="A", seq=server_ack, ack=server_seq + 1) # 构造ACK包,确认服务端序列号+1
send(ack, verbose=0) # 发送ACK包完成三次握手
http_get = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n" # 构造HTTP GET请求
http_payload = raw(http_get.encode("UTF-8")) # 将HTTP请求编码为字节流
get_request = ip / TCP(sport=source_port, dport=target_port, flags="PA", seq=server_ack, ack=server_seq + 1) / http_payload # 构造带PSH+ACK标志的HTTP请求包
response = sr1(get_request, timeout=5, verbose=0) # 发送HTTP请求并等待响应
posted on 2025-09-17 19:00 suiseiseki 阅读(24) 评论(0) 收藏 举报
浙公网安备 33010602011771号