我想在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