scapy 在已建立的连接上发送 tcp 数据包

fha*_*mad 6 c network-programming tcp scapy

我有以下几点:

服务器端:TCP python 服务器(非 scapy) 客户端:Scapy 建立连接并发送 TCP 数据包

我试图在 3 次握手后通过 scapy 在已建立的连接上发送 TCP 数据包

我能够构建 3 路握手和服务器端(另一端 -python TCP 服务器 - 不是 scapy - 创建 TCP 套接字、绑定、侦听、accpet、recv())显示新连接来了,accept() 返回创建的 FD

我试图在 3 次握手成功后从 scapy 发送数据包,但非 scapy 端的 recv() 无法获取数据包

丑陋的一面:

#!/usr/bin/env python
from scapy.all import *
import time

# VARIABLES
src = sys.argv[1]
dst = sys.argv[2]
sport = random.randint(1024,65535)
dport = int(sys.argv[3])

# SYN
ip=IP(src=src,dst=dst)
SYN=TCP(sport=sport,dport=dport,flags='S',seq=1000)
SYNACK=sr1(ip/SYN)

# ACK
ACK=TCP(sport=sport, dport=dport, flags='A', seq=SYNACK.ack, ack=SYNACK.seq + 1)
send(ip/ACK)

time.sleep(15)

ip = IP(src=src, dst=dst)
tcp = ip / TCP(sport=sport, dport=dport, flags="PA", seq=123, ack=1) / "scapy packet 123"
tcp.show2()

send(tcp)
Run Code Online (Sandbox Code Playgroud)

不丑的一面:

#!/usr/bin/python

import socket
from scapy.all import *

ip = sys.argv[1]
port = sys.argv[2]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ip, int(port)))
s.listen(1)

while True :
    conn, addr = s.accept()
    print 'Connection address:', addr
    data = conn.recv(1024) # Stuck here .....
Run Code Online (Sandbox Code Playgroud)

tcpdump 输出显示:

tcpdump: listening on ens1f1, link-type EN10MB (Ethernet), capture size 65535 bytes
18:09:35.820865 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto TCP (6), length 40)
    11.4.3.31.63184 > 11.4.3.30.strexec-d: Flags [S], cksum 0x6543 (correct), seq 1000, win 8192,                                                                        length 0
18:09:35.821017 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
    11.4.3.30.strexec-d > 11.4.3.31.63184: Flags [S.], cksum 0x748d (correct), seq 3017593595, ac                                                                       k 1001, win 29200, options [mss 1460], length 0
18:09:35.930593 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto TCP (6), length 40)
    11.4.3.31.63184 > 11.4.3.30.strexec-d: Flags [.], cksum 0xde5a (correct), seq 1, ack 1, win 8                                                                       192, length 0
18:09:51.057904 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto TCP (6), length 56)
    11.4.3.31.63184 > 11.4.3.30.strexec-d: Flags [P.], cksum 0x8eef (correct), seq 4294966419:429                                                                       4966435, ack 1277373702, win 8192, length 16
18:09:51.057996 IP (tos 0x0, ttl 64, id 1194, offset 0, flags [DF], proto TCP (6), length 40)
    11.4.3.30.strexec-d > 11.4.3.31.63184: Flags [.], cksum 0x8c4a (correct), seq 1, ack 1, win 2                                                                       9200, length 0
Run Code Online (Sandbox Code Playgroud)

我的问题为什么接收方没有收到发送的数据包?

注意:我的目标是在已建立的连接上发送带有错误校验和的 TCP 数据包,并通过非 scapy tcp 服务器接收它提前致谢!

Gil*_*ton 3

您的序列号必须准确跟踪您发送的有效负载字节。设置了 SYN 或 FIN 标志的数据包是一个例外,并且被视为具有长度为 1 的有效负载。换句话说,您可以使用您喜欢的任何初始序列号,但它必须逐字节增加您发送的有效负载(SYN 或 SYN+ACK [或 FIN] 为 +1)。

因此,如果 SYN 数据包中的序列号为 1000,则下一个带有有效负载的数据包(称为 pktA)的序列号应为 1001。那么下一个数据包 (pktB) 的序列号应为 1001 + pktA。 Payload_size 等等。

同样,您不能简单地将 TCP 标头中的确认号字段设置为 1(就像您对“scapy packet 123”所做的那样)。每当您在标头中提供 ACK 标志时,您都需要通过将标头中的确认号设置为对方最后一个有效负载中最后接收到的序列号来确认对方的有效负载。在这种情况下,您已经发送了带有该确认号的裸 ACK 数据包,因此您并不严格需要包含 ACK 标志,但通常总是包含它,如果要包含该标志,则确认序列号应设置正确。

请参阅此链接以获得良好的概述: http://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/