2017-04-12 12 views
1

ハンドシェイク機能を実装しようとしています。私はSYNパケットを送信しており、サーバはACKパケットで応答します。サーバーの応答を取得するために、私はハングしている関数recvfromを使用しています。ここに私のコードです。rawソケット経由のTCPハンドシェイク、なぜrecvfromがハングするのですか?

import socket, sys 
from struct import * 
import codecs 

def checksum(msg): 
    s = 0 
    for i in range(0, len(msg), 2): 
     w = ord(msg[i]) + (ord(msg[i+1]) << 8) 
     s = s + w 
    s = (s>>16) + (s & 0xffff); 
    s = s + (s >> 16); 
    s = ~s & 0xffff 
    return s 

try: 
    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) 
    s.bind(("", "63798")) 
except socket.error , msg: 
    print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] 
    sys.exit() 

packet = ''; 
source_ip = '172.16.87.84' 
dest_ip = '172.16.10.1' 

# ip header fields 
ip_ihl = 5 
ip_ver = 4 
ip_tos = 0 
ip_tot_len = 0 
ip_id = 54321 
ip_frag_off = 0 
ip_ttl = 255 
ip_proto = socket.IPPROTO_TCP 
ip_check = 0 
ip_saddr = socket.inet_aton (source_ip) 
ip_daddr = socket.inet_aton (dest_ip) 
ip_ihl_ver = (ip_ver << 4) + ip_ihl 

ip_header = pack('!BBHHHBBH4s4s' , ip_ihl_ver, ip_tos, ip_tot_len, ip_id, ip_frag_off, ip_ttl, ip_proto, ip_check, ip_saddr, ip_daddr) 

# tcp header fields 
tcp_source = 63798 # source port 
tcp_dest = 8888 # destination port 
tcp_seq = 104 
tcp_ack_seq = 0 
tcp_doff = 5 #4 bit size of tcp header, 5 * 4 = 20 bytes 
#tcp flags 
tcp_fin = 0 
tcp_syn = 1 
tcp_rst = 0 
tcp_psh = 0 
tcp_ack = 0 
tcp_urg = 0 
tcp_window = socket.htons (5840) 
tcp_check = 0 
tcp_urg_ptr = 0 

tcp_offset_res = (tcp_doff << 4) + 0 
tcp_flags = tcp_fin + (tcp_syn << 1) + (tcp_rst << 2) + (tcp_psh <<3) + (tcp_ack << 4) + (tcp_urg << 5) 

tcp_header = pack('!HHLLBBHHH' , tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags, tcp_window, tcp_check, tcp_urg_ptr) 

source_address = socket.inet_aton(source_ip) 
dest_address = socket.inet_aton(dest_ip) 
placeholder = 0 
protocol = socket.IPPROTO_TCP 
tcp_length = len(tcp_header) 

psh = pack('!4s4sBBH' , source_address , dest_address , placeholder , protocol , tcp_length); 
psh = psh + tcp_header; 

tcp_check = checksum(psh) 

tcp_header = pack('!HHLLBBH' , tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags, tcp_window) + pack('H' , tcp_check) + pack('!H' , tcp_urg_ptr) 

packet = ip_header + tcp_header 
s.sendto(packet, (dest_ip , 8888)) 
s.recvfrom(1024) # Here is recevfrom hangs 

プログラムはrecvfrom()でハングします。何をすべきか、この問題の理由は何ですか? 実際にサーバーはACKパケットを送信します。それはここでwiresharkの で見ることができるWiresharkのは enter image description here

答えて

0

問題がここに産むログです:s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)を、raw(7) man pageは言う:

をIPPROTO_RAWのプロトコルが有効になってIP_HDRINCLを意味し、 することができる任意のIPプロトコルを送信渡されたヘッダーで指定されています。
IPPROTO_RAWによるすべてのIPプロトコルの受信は、生の ソケットを使用して行うことはできません。パケットが受信されると、他のプロトコルハンドラ (例えば、カーネルプロトコルモジュール)に渡される前に、そのプロトコルにバインドされた を有する任意の生ソケットにパケットが渡される。
IPPROTO_RAWソケットは送信のみです。

使用s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP) 代わりに、自分のIPヘッダーに使用するIP_HDRINCLソケットオプションを有効にします。 s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

+0

おかげで男を。コードが動作し始めた –

関連する問題