为什么tcp raw socket在recvfrom上挂起?

时间:2017-04-23 21:07:08

标签: python wireshark raw-sockets tcpsocket recvfrom

我已经实现了这段代码,可以通过pc与我的设备进行通信。它得到几个数据包,然后它挂在recvfrom()in while循环?

import socket, sys, random
from struct import *
import struct
import select
import codecs
import base64
import time
import pdb

def checksum(msg):
    s = 0
    for i in range(0, len(msg), 2):
        w = (ord(msg[i]) <<8) + (ord(msg[i+1]) )
        s = s + w

    s = (s>>16) + (s & 0xffff);
    s = ~s & 0xffff
    return s

def create_socket(source_ip,dest_ip):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)            
    except socket.error , msg:
        print 'Socket could not be created.  Error: ',str(msg[0]),' Message: ',msg[1]
        sys.exit()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
    return s

def create_ip_header(source_ip, dest_ip):
    packet = ''
    headerlen = 5
    version = 4
    tos = 0
    tot_len = 20 + 20
    id = random.randrange(18000,65535,1)
    flags = 2
    frag_off = 0
    ttl = 255
    protocol = socket.IPPROTO_TCP
    check = 10
    saddr = socket.inet_aton ( source_ip )
    daddr = socket.inet_aton ( dest_ip )
    hl_version = (version << 4) + headerlen
    flags = (flags << 13) + frag_off
    ip_header = pack('!BBHHHBBH4s4s', hl_version, tos, tot_len, id, flags, ttl, protocol, check, saddr, daddr)
    return ip_header    

def create_tcp_syn_header(source_ip, source, dest_ip, dest_port, syn_flag, ack_num, ack_flag, seq_num, psh_flag, user_data):
    seq = seq_num
    ack_seq = ack_num
    doff = 5
    # tcp flags
    fin = 0
    syn = syn_flag
    rst = 0
    psh = psh_flag
    ack = ack_flag
    urg = 0
    window = socket.htons(19253500)
    check = 0
    urg_ptr = 0
    offset_res = (doff << 4) + 0
    tcp_flags = fin + (syn<<1) + (rst<<2) + (psh<<3) + (ack<<4) + (urg<<5)
    tcp_header = pack('!HHLLBBHHH', source, dest_port, seq, ack_seq, offset_res, tcp_flags, window, check, urg_ptr)

    source_address = socket.inet_aton( source_ip )
    dest_address = socket.inet_aton( dest_ip )
    placeholder = 0
    protocol = socket.IPPROTO_TCP
    if user_data:
       tcp_length = len(tcp_header) + len(user_data)
    else:
       tcp_length = len(tcp_header)
    psh = pack('!4s4sBBH', source_address, dest_address, placeholder, protocol, tcp_length);
    if user_data:
       psh = psh + tcp_header + user_data;
    else:
       psh = psh + tcp_header;
    tcp_checksum = checksum(psh)

    tcp_header = pack('!HHLLBBHHH', source, dest_port, seq, ack_seq, offset_res, tcp_flags, window, tcp_checksum, urg_ptr)
    return tcp_header


def decode_packet(packet):
    packet = packet[0]    
    ip_header = packet[0:20]        
    iph = unpack('!BBHHHBBH4s4s' , ip_header)
    version_ihl = iph[0]
    version = version_ihl >> 4
    ihl = version_ihl & 0xF
    iph_length = ihl * 4
    ttl = iph[5]
    protocol = iph[6]
    s_addr = socket.inet_ntoa(iph[8]);
    d_addr = socket.inet_ntoa(iph[9]);
    print 'Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + ' TTL : ' + str(ttl) + ' Protocol : ' + str(protocol) + ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr)
    tcp_header = packet[iph_length:iph_length+20]        
    tcph = unpack('!HHLLBBHHH' , tcp_header)
    source_port = tcph[0]
    dest_port = tcph[1]
    sequence = tcph[2]
    acknowledgement = tcph[3]
    doff_reserved = tcph[4]
    flags = tcph[5]
    tcph_length = doff_reserved >> 4
    print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Sequence Number : ' + str(sequence) + ' Acknowledgement : ' + str(acknowledgement) + ' TCP header length : ' + str(tcph_length)
    h_size = iph_length + tcph_length * 4
    data_size = len(packet) - h_size
    #get data from the packet
    data = packet[h_size:]
    return acknowledgement, sequence, data, flags, dest_port

def pre_communicate(s, ip_header, source_ip, dest_ip, source_port, dest_port, user_data):
    #### SYN packet    
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 1, 0, 0, 0, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))
    rcv_data = s.recvfrom(2024)
    ack, seq, rcv_data, flags, src_port = decode_packet(rcv_data)

    #### ACK packet
    ackn = seq + 1
    seqn = ack        
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))

    ##### PSH ACK packet
    user_data = user_data.decode('hex')
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 1, user_data)
    packet = ip_header + tcp_header + user_data
    s.sendto(packet, (dest_ip, 0))
    data = s.recvfrom(2024)
    sys.stdout.write(data[0])
    ack, seq, rcv_data, flags, src_port = decode_packet(data)
    if rcv_data:
       ackn = seq + len(rcv_data)
    seqn = ack

    #### ACK packet 
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))

def communicate(s, ip_header, source_ip, dest_ip, source_port, dest_port, user_data):
    #### SYN packet

    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 1, 0, 0, 0, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))
    rcv_data = s.recvfrom(2024)
    ack, seq, rcv_data, flags, src_port = decode_packet(rcv_data)

    #### ACK packet
    ackn = seq + 1
    seqn = ack        
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))

    ##### PSH ACK packet
    user_data = user_data.decode('hex')
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 1, user_data)
    packet = ip_header + tcp_header + user_data
    pdb.set_trace()
    s.sendto(packet, (dest_ip, 0))

def tcp_stack(source_ip, dest_ip, dest_port): 
    ip_header = create_ip_header(source_ip, dest_ip)
    s = create_socket(source_ip, dest_ip)
    magicword1 = "4954640000005200000005a7a90fb36ecd3fa2ca7ec48ca36004acef63f77157ab2f53e3f768ecd9e18547b8c22e21d01bfb6b3de325a27b8fb3acef63f77157ab2f53e3f768ecd9e185b7330fb7c95782fc3d67e7c3a66728dad8b59848c7670c94b29b54d2379e2e7a"

    magicword2 = "495464000000520000007298c0389bc372a71a174bd1b514b3adacef63f77157ab2f53e3f768ecd9e18547b8c22e21d01bfb6b3de325a27b8fb3acef63f77157ab2f53e3f768ecd9e185b7330fb7c95782fc3d67e7c3a66728dad8b59848c7670c94b29b54d2379e2e7a"

    magicword3 = "4954640000005200000021e0c477c77394e85d66a98c2c922cc5acef63f77157ab2f53e3f768ecd9e18547b8c22e21d01bfb6b3de325a27b8fb3acef63f77157ab2f53e3f768ecd9e185b7330fb7c95782fc3d67e7c3a66728dad8b59848c7670c94b29b54d2379e2e7a"

    magicword4 = "495464000000580000009bf89049c926884d4f922b3b33ba7eceacef63f77157ab2f53e3f768ecd9e18547b8c22e21d01bfb6b3de325a27b8fb3acef63f77157ab2f53e3f768ecd9e185eb20be383aab05a8c2a71f2c906d93f72a85e7356effe1b8f5af097f9147f87e"

    #source_ports = [41776, 53856, 31342, 48913]
    source_ports = [41776, 53856, 31342]
    magic_words = [magicword1, magicword2, magicword3]
    index = 0
    for index in xrange(len(magic_words)):
       pre_communicate(s, ip_header, source_ip, dest_ip, source_ports[index], dest_port, magic_words[index])
       index += 1


    communicate(s, ip_header, source_ip, dest_ip, 48913, dest_port, magicword4)
    data = s.recvfrom(2024)
    while True:
       data = s.recvfrom(2024) # Here the program hangs
       ack, seq, rcv_data, flags, src_port = decode_packet(data)
       sys.stdout.write(data[0])
       ackn = seq + len(rcv_data)
       seqn = ack
       tcp_header = create_tcp_syn_header(source_ip, src_port, dest_ip, dest_port, 0, ackn, 1, seqn, 0, "")
       packet = ip_header + tcp_header
       s.sendto(packet, (dest_ip, 0))


source_ip = "172.16.87.84"
dest_ip = "172.16.10.1"
dest_port = 8888
tcp_stack(source_ip, dest_ip, dest_port)

这是Wireshark日志。程序成功建立与设备的通信并开始发送/接收数据包 enter image description here

然后它挂在recvfrom()上。

这是另一个Wireshark日志,它已被挂起。 enter image description here

怎么办?这个问题怎么解决?

1 个答案:

答案 0 :(得分:0)

根据您的Wireshark,您将最后一封ACK发送给设备,而且设备上没有数据了。由于你的套接字阻止了它,因为它会阻塞直到新数据到来为止。在这种情况下永远。

此外,设备未关闭连接,因此TCP有效。我不知道&#34;设备&#34;意思是但我认为它有一个有效的TCP堆栈。

设备刚刚停止接听。我建议你在设备方面寻找原因。