gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 02:53:43 25 4
gpt4 key购买 nike

我正在尝试实现握手功能。我正在发送 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

最佳答案

问题就在这里: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 header :s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

关于python - 通过原始套接字进行 TCP 握手,为什么 recvfrom 挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43380226/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com