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)    收藏  举报

导航