Python Scapy 中的 3 次握手
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26480854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
3 way handshake in Scapy
提问by felix001
Im trying to build a 3 way handshake in Scapy. Using the following code,
我试图在 Scapy 中建立一个 3 路握手。使用以下代码,
#!/usr/local/bin/python
from scapy.all import *
sport = random.randint(1024,65535)
# SYN
ip=IP(src='172.16.120.5',dst='172.16.100.101')
SYN=TCP(sport=sport,dport=443,flags='S',seq=1000)
SYNACK=sr1(ip/SYN)
# ACK
my_ack = SYNACK.seq + 1
ACK=TCP(sport=sport, dport=443, flags='A', seq=1001, ack=my_ack)
send(ip/ACK)
However on the server I see only SYN_RECV even though the return SYN-ACK is sent and the ACK is sent in return. Here is a capture from the server (172.16.100.101),
然而,在服务器上我只看到 SYN_RECV,即使发送了返回的 SYN-ACK 并且返回了 ACK。这是来自服务器(172.16.100.101)的捕获,
08:10:19.455038 IP 172.16.120.5.58972 > 172.16.100.101.https: S 1000:1000(0) win 8192
08:10:19.455343 IP 172.16.100.101.https > 172.16.120.5.58972: S 2541678705:2541678705(0) ack 1001 win 18484 <mss 1460>
08:10:19.545808 IP 172.16.120.5.58972 > 172.16.100.101.https: . ack 1 win 8192
08:10:24.015204 IP 172.16.100.101.https > 172.16.120.5.58972: S 2541678705:2541678705(0) ack 1001 win 18484 <mss 1460>
As you can see the SYN-ACK is being sent twice so it looks like the server doesnt like the final ACK. Any ideas ?
正如您所看到的,SYN-ACK 被发送了两次,所以看起来服务器不喜欢最终的 ACK。有任何想法吗 ?
EDIT :
编辑 :
Ive also printed the output of each of the packets directly from python. Note this was for a different connection.
我还直接从 python 打印了每个数据包的输出。请注意,这是针对不同的连接。
>>> SYN
<TCP sport=26193 dport=https seq=1000 flags=S |>
>>>
>>> SYNACK
<IP version=4L ihl=5L tos=0x0 len=44 id=0 flags=DF frag=0L ttl=63 proto=tcp chksum=0x741 src=172.16.100.101 dst=172.16.120.5 options=[] |<TCP sport=https dport=26193 seq=1023579974 ack=1001 dataofs=6L reserved=0L flags=SA window=18484 chksum=0xdb18 urgptr=0 options=[('MSS', 1460)] |<Padding load='\x00\x00' |>>>
>>>
>>> ACK
<TCP sport=26193 dport=https seq=1001 ack=1023579975 flags=A |>
EDIT 2 :
编辑 2:
Below shows a successful and unsucessful connection.
下面显示了成功和不成功的连接。
SCAPY
SCAPY
20:58:37.357056 IP 172.16.120.5.35957 > 172.16.100.101.https: S 10:10(0) win 8192
20:58:37.357369 IP 172.16.100.101.https > 172.16.120.5.35957: S 900629853:900629853(0) ack 11 win 18484 <mss 1460>
20:58:37.445888 IP 172.16.120.5.35957 > 172.16.100.101.https: . ack 900629854 win 8192
CURL
卷曲
20:58:46.165413 IP 172.16.120.5.33241 > 172.16.100.101.https: S 2266708589:2266708589(0) win 5840 <mss 1460,sackOK,timestamp 17370497 0,nop,wscale 6>
20:58:46.166296 IP 172.16.100.101.https > 172.16.120.5.33241: S 2138155488:2138155488(0) ack 2266708590 win 18460 <mss 1460,sackOK,timestamp 107550664 17370497,nop,wscale 7>
20:58:46.169026 IP 172.16.120.5.33241 > 172.16.100.101.https: . ack 2138155489 win 92 <nop,nop,timestamp 17370497 107550664>
采纳答案by felix001
I managed to fix this in the end by incrementing the final SEQ number of the ACK.
我最终通过增加 ACK 的最终 SEQ 编号设法解决了这个问题。
from scapy.all import *
sport = random.randint(1024,65535)
# SYN
ip=IP(src='172.16.120.5',dst='172.16.100.101')
SYN=TCP(sport=sport,dport=443,flags='S',seq=1000)
SYNACK=sr1(ip/SYN)
# SYN-ACK
ACK=TCP(sport=sport, dport=443, flags='A', seq=SYNACK.ack + 1, ack=SYNACK.seq + 1)
send(ip/ACK)
Heres a tcpdump showing the behaviour...
这是一个显示行为的 tcpdump...
20:47:54.226591 IP 172.16.120.5.55348 > 172.16.100.101.443: S 1000:1000(0) win 8192
20:47:54.227220 IP 172.16.100.101.443 > 172.16.120.5.55348: S 4265040634:4265040634(0) ack 1001 win 18484 <mss 1460>
20:47:54.317452 IP 172.16.120.5.55348 > 172.16.100.101.443: . ack 4265040635 win 8192
回答by tintin
This gistimplements a simple scapy three-way handshake class based on the example in scapy.layers.inet. For reference, this is the code:
这个要点基于 中的示例实现了一个简单的 scapy 三向握手类scapy.layers.inet。供参考,这是代码:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author : [email protected] <github.com/tintinweb>
'''
A simple TCP three-way handshake example
#> python scapy_tcp_handshake.py
DEBUG:__main__:init: ('oststrom.com', 80)
DEBUG:__main__:start
DEBUG:__main__:SND: SYN
DEBUG:__main__:RCV: SYN+ACK
DEBUG:__main__:SND: SYN+ACK -> ACK
DEBUG:__main__:RCV: None
DEBUG:__main__:RCV: None
None
DEBUG:__main__:SND: FIN
DEBUG:__main__:RCV: None
Note: linux might send an RST for forged SYN packets. Disable it by executing:
#> iptables -A OUTPUT -p tcp --tcp-flags RST RST -s <src_ip> -j DROP
'''
from scapy.all import *
import logging
logger = logging.getLogger(__name__)
class TcpHandshake(object):
def __init__(self, target):
self.seq = 0
self.seq_next = 0
self.target = target
self.dst = iter(Net(target[0])).next()
self.dport = target[1]
self.sport = random.randrange(0,2**16)
self.l4 = IP(dst=target[0])/TCP(sport=self.sport, dport=self.dport, flags=0,
seq=random.randrange(0,2**32))
self.src = self.l4.src
self.swin = self.l4[TCP].window
self.dwin=1
logger.debug("init: %s"%repr(target))
def start(self):
logger.debug("start")
return self.send_syn()
def match_packet(self, pkt):
if pkt.haslayer(IP) and pkt[IP].dst == self.l4[IP].src \
and pkt.haslayer(TCP) and pkt[TCP].dport == self.sport \
and pkt[TCP].ack == self.seq_next:
return True
return False
def _sr1(self, pkt):
send(pkt)
ans = sniff(filter="tcp port %s"%self.target[1],lfilter=self.match_packet,count=1,timeout=1)
return ans[0] if ans else None
def handle_recv(self, pkt):
if pkt and pkt.haslayer(IP) and pkt.haslayer(TCP):
if pkt[TCP].flags & 0x3f == 0x12: # SYN+ACK
logger.debug("RCV: SYN+ACK")
return self.send_synack_ack(pkt)
elif pkt[TCP].flags & 4 != 0: # RST
logger.debug("RCV: RST")
raise Exception("RST")
elif pkt[TCP].flags & 0x1 == 1: # FIN
logger.debug("RCV: FIN")
return self.send_finack(pkt)
elif pkt[TCP].flags & 0x3f == 0x10: # FIN+ACK
logger.debug("RCV: FIN+ACK")
return self.send_ack(pkt)
logger.debug("RCV: %s"%repr(pkt))
return None
def send_syn(self):
logger.debug("SND: SYN")
self.l4[TCP].flags = "S"
self.seq_next = self.l4[TCP].seq + 1
response = self._sr1(self.l4)
self.l4[TCP].seq += 1
return self.handle_recv(response)
def send_synack_ack(self, pkt):
logger.debug("SND: SYN+ACK -> ACK")
self.l4[TCP].ack = pkt[TCP].seq+1
self.l4[TCP].flags = "A"
self.seq_next = self.l4[TCP].seq
response = self._sr1(self.l4)
return self.handle_recv(response)
def send_data(self, d):
self.l4[TCP].flags = "PA"
response = self._sr1(self.l4/d)
self.seq_next = self.l4[TCP].seq + len(d)
self.l4[TCP].seq += len(d)
return self.handle_recv(response)
def send_fin(self):
logger.debug("SND: FIN")
self.l4[TCP].flags = "F"
self.seq_next = self.l4[TCP].seq + 1
response = self._sr1(self.l4)
self.l4[TCP].seq += 1
return self.handle_recv(response)
def send_finack(self, pkt):
logger.debug("SND: FIN+ACK")
self.l4[TCP].flags = "FA"
self.l4[TCP].ack = pkt[TCP].seq+1
self.seq_next = self.l4[TCP].seq + 1
response = send(self.l4)
self.l4[TCP].seq += 1
raise Exception("FIN+ACK")
def send_ack(self, pkt):
logger.debug("SND: ACK")
self.l4[TCP].flags = "A"
self.l4[TCP].ack = pkt[TCP].seq+1
self.seq_next = self.l4[TCP].seq + 1
response = self._sr1(self.l4)
self.l4[TCP].seq += 1
if __name__=='__main__':
logging.basicConfig(level=logging.DEBUG)
logger.setLevel(logging.DEBUG)
conf.verb = 0
tcp_hs = TcpHandshake(("oststrom.com",80))
tcp_hs.start()
print repr(tcp_hs.send_data("INTENTIONAL BAD REQUEST\r\n\r\n\r\n"))
tcp_hs.send_fin()

