Masscan 是一个高性能的端口扫描工具,它通过发送 TCP SYN 包来检测目标主机的端口状态。具体来说,Masscan 的工作原理如下:
发送 TCP SYN 包:Masscan 向目标主机的指定端口发送 TCP SYN 包。这是 TCP 三次握手的第一步。接收响应:如果目标主机的端口是开放的,它会回复一个 TCP SYN-ACK 包。如果端口是关闭的,它会回复一个 TCP RST 包。分析响应:Masscan 根据接收到的响应包来判断端口的状态。如果收到 SYN-ACK 包,说明端口是开放的;如果收到 RST 包,说明端口是关闭的。2. 为什么 Masscan 这么快Masscan 能够实现高速扫描的原因有以下几点:
2.1 并发扫描多线程/多进程:Masscan 使用多线程或多进程并发发送和接收数据包,大大提高了扫描速度。异步 I/O:Masscan 使用异步 I/O 模型,可以在等待响应的同时继续发送新的请求,进一步提高效率。2.2 高效的网络编程自定义网络栈:Masscan 使用自定义的网络栈,绕过了操作系统的网络协议栈,减少了系统调用的开销。直接操作网络接口:Masscan 直接操作网络接口卡(NIC),通过 raw socket 发送和接收数据包,避免了操作系统内核的处理延迟。2.3 优化的算法随机化扫描:Masscan 可以随机化扫描顺序,减少被目标主机防火墙或入侵检测系统(IDS)检测到的风险。批量发送:Masscan 可以批量发送多个数据包,减少每次发送的开销。2.4 硬件加速利用硬件特性:Masscan 可以利用现代网络硬件的特性,如多核处理器、高速网络接口等,进一步提升性能。3. 示例代码以下是一个简化的 Masscan 工作流程的伪代码,展示了如何发送 TCP SYN 包并接收响应:
代码语言:python代码运行次数:0运行复制import socket
import struct
import random
def send_syn_packet(ip, port):
# 创建原始套接字
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
# 构建 IP 头
ip_header = build_ip_header(ip)
# 构建 TCP 头
tcp_header = build_tcp_header(port)
# 构建完整的数据包
packet = ip_header + tcp_header
# 发送数据包
s.sendto(packet, (ip, 0))
def build_ip_header(ip):
# IP 头结构
ip_header = struct.pack('!BBHHHBBH4s4s',
69, 0, 0, 0, 0, 64, 6, 0,
socket.inet_aton('0.0.0.0'), socket.inet_aton(ip))
return ip_header
def build_tcp_header(port):
# TCP 头结构
source_port = random.randint(1024, 65535)
dest_port = port
seq = 0
ack_seq = 0
doff = 5
flags = 0x02 # SYN 标志
window = socket.htons(5840)
checksum = 0
urg_ptr = 0
tcp_header = struct.pack('!HHLLBBHHH',
source_port, dest_port, seq, ack_seq,
(doff << 4) + 0, flags, window, checksum, urg_ptr)
return tcp_header
def receive_response(s):
# 接收响应
while True:
packet = s.recvfrom(65565)
ip_header = packet[0][0:20]
iph = struct.unpack('!BBHHHBBH4s4s', ip_header)
version_ihl = iph[0]
version = version_ihl >> 4
ihl = version_ihl & 0xF
iph_length = ihl * 4
tcp_header = packet[0][iph_length:iph_length+20]
tcph = struct.unpack('!HHLLBBHHH', tcp_header)
source_port = tcph[0]
dest_port = tcph[1]
sequence = tcph[2]
acknowledgement = tcph[3]
doff_reserved = tcph[4]
tcph_length = doff_reserved >> 4
flags = tcph[5]
if flags & 0x12 == 0x12: # SYN-ACK
print(f"Port {dest_port} is open")
elif flags & 0x14 == 0x14: # RST-ACK
print(f"Port {dest_port} is closed")
# 示例使用
send_syn_packet('192.168.1.1', 80)