首页 > 解决方案 > 只有当协议是 TCP 时,Wireshark 才能捕获原始套接字

问题描述

我正在尝试发送一个原始套接字数据包,编写我自己的 IP 标头和 TCP 标头,当 IP 标头中的 ip_protocol 设置为除 6 之外的任何数字(即 TCP)时,wireshark 可以捕获数据包

我正在使用 Windows 10 和 python 3.6.8。我的源 IP 和目标 IP 都是 localhost。我也试过关闭防火墙,但没有帮助。任何 IP 协议不是 6 的数据包都可以正常捕获。只有当我设置 ip_protocol = 6 时,Wireshark 才能捕获数据包。

def carry_around_add(a, b):
    c = a + b
    return (c & 0xffff) + (c >> 16)

def CalculateChecksum(msg):
    s = 0
    for i in range(0, len(msg), 2):
        temp = msg[i] << 8 + msg[i+1]
        s = carry_around_add(s, temp)
    return ~s & 0xffff
def GenerateIPHeader(ip_source, ip_dest):
    ip_ver = 4              # ipv4
    ip_ihl = 5              # Header Length = 5, no option
    ip_dscp = 0             # dscp (type of service)
    ip_total_len = 0        # left for kernel to fill
    ip_id = 0               # fragment
    ip_frag_offset = 0      # fragment
    ip_ttl = 255            # Time to live
    ip_protocol = 6         # TCP = 6
    ip_checksum = 0         # left for kernel to fill
    ip_saddr = socket.inet_aton(ip_source)
    ip_daddr = socket.inet_aton(ip_dest)
    ip_ver_ihl = (ip_ver << 4) + ip_ihl 
    ip_header = struct.pack('!BBHHHBBH4s4s' , ip_ver_ihl, ip_dscp, ip_total_len, ip_id, ip_frag_offset, ip_ttl, ip_protocol, ip_checksum, ip_saddr, ip_daddr)
    return ip_header
def GenerateTCPHeader(SrcPort, DestPort, Checksum = 0, Flags = (0, 0, 0, 0, 1, 0)):
    tcp_sport = SrcPort 
    tcp_dport = DestPort
    global SequenceNumber
    tcp_seq = SequenceNumber    
    tcp_ack_seq = 0     
    tcp_data_offset = 5     # No option

    # Flags
    tcp_flag_urg = Flags[0] 
    tcp_flag_ack = Flags[1]
    tcp_flag_psh = Flags[2]
    tcp_flag_rst = Flags[3]
    tcp_flag_syn = Flags[4]
    tcp_flag_fin = Flags[5]

    tcp_window_size = 3000  
    tcp_checksum = Checksum
    tcp_urgent_ptr = 0

    tcp_offset_reserv = (tcp_data_offset << 4)
    tcp_flags = tcp_flag_fin + (tcp_flag_syn << 1) + (tcp_flag_rst << 2) + (tcp_flag_psh <<3) + (tcp_flag_ack << 4) + (tcp_flag_urg << 5)

    # print(tcp_sport, tcp_dport, tcp_seq, tcp_ack_seq, tcp_offset_reserv, tcp_flags, tcp_window_size, tcp_checksum, tcp_urgent_ptr)
    tcp_header = struct.pack('!HHLLBBHHH' , tcp_sport, tcp_dport, tcp_seq, tcp_ack_seq, tcp_offset_reserv, tcp_flags, tcp_window_size, tcp_checksum, tcp_urgent_ptr)
    return tcp_header
def GeneratePacket(SrcAddr, SrcPort, DestAddr, DestPort, payload = ''):
    if len(payload) % 2 == 1:
        payload += " "
    IPHeader = GenerateIPHeader(SrcAddr, DestAddr)
    TCPHeader = GenerateTCPHeader(SrcPort, DestPort)
    PseudoIPHEader = GeneratePseudoIPHeader(SrcAddr, DestAddr, TCPHeader, payload)
    Checksum = b"".join([PseudoIPHEader, TCPHeader, payload.encode()])
    TCPChecksum = CalculateChecksum(Checksum)
    TCPHeader = GenerateTCPHeader(SrcPort, DestPort, TCPChecksum)
    TCPPacket = b"".join([TCPHeader, payload.encode()])
    packet = b"".join([IPHeader, TCPPacket])
    return packet
def GeneratePseudoIPHeader(ip_source, ip_dest, tcp_header, payload_data):
    psh_saddr = socket.inet_pton(socket.AF_INET, ip_source)
    psh_daddr = socket.inet_pton(socket.AF_INET, ip_dest)
    psh_reserved = 0
    psh_protocol = socket.IPPROTO_TCP
    psh_tcp_len = len(tcp_header) + len(payload_data)
    psh = struct.pack('!4s4sBBH', psh_saddr, psh_daddr, psh_reserved, psh_protocol, psh_tcp_len)
    return psh
def StartClient(SrcAddr, SrcPort, DestAddr, DestPort):
    try:
        Client = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
    except socket.error as msg:
        print('Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
        sys.exit()
    Client.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)  #Set it to include the header
    Client.bind((SrcAddr, SrcPort))

    Packet = GeneratePacket(SrcAddr, SrcPort, DestAddr, DestPort, 'Hello!')

    print(Packet)
    Client.sendto(Packet, (DestAddr, DestPort))

标签: socketstcppython-3.6raw-sockets

解决方案


推荐阅读