2017-04-23 29 views
0

私はこのコードを実装して、PCから自分のデバイスと通信しています。それはいくつかのパケットを取得し、whileループでrecvfrom()でハングアップしますか?recvfromでtcp rawソケットがハングアップするのはなぜですか?

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でハング()。

もう1つのWiresharkログが既にハングしています。 enter image description here

どうすればよいですか?どのようにしてこの問題を解決できますか?

+1

申し訳ありませんが、なぜあなたはtcpを再実装しようとしていますか?ここで書いたものよりずっと複雑です。窓、再送信、ナグルのアルゴリズムe.t.cがあります。あなたのデバイスはTCP接続を期待しているので、単にTCPスタックを使用すると思います。 – norekhov

+0

もっと深いTCP /ソケット機構を理解するためです。タスクはすでに単純なソケットを介して解決されています。 –

答えて

0

あなたのWiresharkによれば、最後のACKをデバイスに送信し、デバイスからのデータはもうありません。あなたのソケットはブロックされているので、新しいデータが到着するまでブロックされます。この場合永遠に。

また、接続がデバイスによって閉じられていないため、TCPが有効でした。私は "デバイス"が何を意味するかわかりませんが、有効なTCPスタックを持っていると思います。

デバイスが応答を停止しました。私はあなたがデバイス側で理由を追求することをお勧めします。

関連する問題