通过原始套接字进行TCP握手,为什么recvfrom挂起?

2024-06-07 21:28:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试实现握手功能。我正在发送SYN包,服务器通过ACK包响应。为了获得服务器响应,我使用了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


Tags: ipsourcelencheckmsgsocketseqpack
1条回答
网友
1楼 · 发布于 2024-06-07 21:28:13

问题就在这里:s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)raw(7) man page说:

A protocol of IPPROTO_RAW implies enabled IP_HDRINCL and is able to send any IP protocol that is specified in the passed header.
Receiving of all IP protocols via IPPROTO_RAW is not possible using raw sockets. When a packet is received, it is passed to any raw sockets which have been bound to its protocol before it is passed to other protocol handlers (e.g., kernel protocol modules).
An IPPROTO_RAW socket is send only.

请改用s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP) ,并启用IP_HDRINCL套接字选项来使用您自己的ip标头: s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

相关问题 更多 >

    热门问题