我想在python上编写简单的udp端口扫描程序,但我遇到了一些问题 .

首先,我理解正确,有3个选项:

  • 发送UDP - 什么都没有 - >端口被过滤|打开

  • 发送UDP - 获取icmp端口不可达 - >端口关闭

  • 发送UDP - 获取UDP - 端口打开

我创建原始套接字,创建IP标头和udp标头 . 在udp头中写入dest端口并添加一些数据 . 然后我将它发送到服务器并使用 select 等待回复 . 但在开放的港口和封闭的港口都没有 . 只有超时 .

是否可以发送虚拟数据但不能正确发送下一级别的数据包?

[更新1]添加了更多要在udp数据包中发送的数据 . 现在我从( 194.226.244.126 ,53)获得udp数据包,但我的主机发送回icmp类型3到 194.226.244.126 ,然后才能读取任何收到的数据 . 但仍然没有8.8.8.8的回应

[更新2]发现8.8.8.8只回复正确的dns数据包 . 但仍然无法读取带有原始套接字的udp数据包 .

import socket
import time
import select
import sys
from packets_headers import iphdr, udphdr
from get_ip import Getip

timeout = 3
host = "8.8.8.8"
port = 53
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW)
udp_header = udphdr(b"00000000000000000", port, 4242)
udp_packet = udp_header.assemble()
g = Getip()
ip_packet_header = iphdr(socket.IPPROTO_UDP, g.get_lan_ip(), host)
ip_packet_header.data = udp_packet
ip_packet = ip_packet_header.assemble()
my_socket.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
full_packet = ip_packet
while full_packet:
    sent = my_socket.sendto(full_packet, (host, port))
    full_packet = full_packet[sent:]

ready = select.select([my_socket], [], [], timeout)
if ready[0] == []:  # Timeout
    print("Timeout")
    sys.exit()
rec_packet, addr = my_socket.recvfrom(1024)
print(rec_packet, addr)

packets_header.py

import socket
import struct
import random


class iphdr(object):

    """
    This represents an IP packet header.
    @assemble packages the packet
    @disassemble disassembles the packet
    """

    def __init__(self, proto=socket.IPPROTO_ICMP, src="0.0.0.0", dst=None):
        self.version = 4
        self.hlen = 5
        self.tos = 0
        self.length = 20
        self.id = random.randint(2 ** 10, 2 ** 16)
        self.frag = 0
        self.ttl = 255
        self.proto = proto
        self.cksum = 0
        self.src = src
        self.saddr = socket.inet_aton(src)
        self.dst = dst or "0.0.0.0"
        self.daddr = socket.inet_aton(self.dst)
        self.data = ""

    def assemble(self):
        header = struct.pack('BBHHHBB',
                             (self.version & 0x0f) << 4 | (self.hlen & 0x0f),
                             self.tos, self.length + len(self.data),
                             socket.htons(self.id), self.frag,
                             self.ttl, self.proto)
        self._raw = header + b"\x00\x00" + self.saddr + self.daddr + self.data
        return self._raw

    @classmethod
    def disassemble(self, data):
        self._raw = data
        ip = iphdr()
        pkt = struct.unpack('!BBHHHBBH', data[:12])
        ip.version = (pkt[0] >> 4 & 0x0f)
        ip.hlen = (pkt[0] & 0x0f)
        ip.tos, ip.length, ip.id, ip.frag, ip.ttl, ip.proto, ip.cksum = pkt[1:]
        ip.saddr = data[12:16]
        ip.daddr = data[16:20]
        ip.src = socket.inet_ntoa(ip.saddr)
        ip.dst = socket.inet_ntoa(ip.daddr)
        return ip

    def __repr__(self):
        return "IP (tos %s, ttl %s, id %s, frag %s, proto %s, length %s) " \
               "%s -> %s" % \
               (self.tos, self.ttl, self.id, self.frag, self.proto,
                self.length, self.src, self.dst)


class udphdr(object):

    def __init__(self, data="", dport=4242, sport=4242):
        self.dport = dport
        self.sport = sport
        self.cksum = 0
        self.length = 0
        self.data = data

    def assemble(self):
        self.length = len(self.data) + 8
        part1 = struct.pack("!HHH", self.sport, self.dport, self.length)
        cksum = self.checksum(self.data)
        cksum = struct.pack("!H", cksum)

        self._raw = part1 + cksum + self.data
        return self._raw

    @classmethod
    def checksum(self, data):
        # XXX implement proper checksum
        cksum = 0
        return cksum

    def disassemble(self, data):
        self._raw = data
        udp = udphdr()
        pkt = struct.unpack("!HHHH", data)
        udp.src_port, udp.dst_port, udp.length, udp.cksum = pkt
        return udp