import socket
import struct
import time
import random
import array
def syn_scan_port(target_ip, port):
"""SYN 扫描单个端口"""
try:
# 创建 Raw Socket
raw_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
raw_socket.settimeout(2)
# 构造 IP 头部
ip_header = struct.pack('!BBHHHBBHLL', 0x45, 0, 20+20, random.randint(1, 65535), 0, 64, socket.IPPROTO_TCP, 0, socket.inet_aton('192.168.1.102'), socket.inet_aton(target_ip))
# 构造 TCP 头部
tcp_header = struct.pack('!HHLLBBHHH', random.randint(1024, 65535), port, 0, 0, 5 << 4 | 0, 0, 0, 0, 0)
tcp_syn_flags = 0x02
tcp_header_list = list(struct.unpack('!HHLLBBHHH', tcp_header))
tcp_header_list[4] = (tcp_header_list[4] | tcp_syn_flags)
tcp_header = struct.pack('!HHLLBBHHH', *tcp_header_list)
# 计算校验和
ip_checksum = calculate_checksum(ip_header)
ip_header = ip_header[:10] + struct.pack('!H', ip_checksum) + ip_header[12:]
pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton('192.168.1.102'), socket.inet_aton(target_ip), 0, socket.IPPROTO_TCP, len(tcp_header))
tcp_checksum = calculate_checksum(pseudo_header + tcp_header)
tcp_header = tcp_header[:16] + struct.pack('!H', tcp_checksum) + tcp_header[18:]
# 发送 SYN 数据包
packet = ip_header + tcp_header
raw_socket.sendto(packet, (target_ip, port))
# 接收响应
recv_packet = raw_socket.recvfrom(65535)
ip_header_reply = recv_packet[0][0:20]
ip_header_unpack = struct.unpack('!BBHHHBBHLL', ip_header_reply)
ip_protocol_reply = ip_header_unpack[6]
tcp_header_reply = recv_packet[0][ip_header_unpack[2]:ip_header_unpack[2]+20]
tcp_header_unpack_reply = struct.unpack('!HHLLBBHHH', tcp_header_reply)
tcp_flags_reply = tcp_header_unpack_reply[5]
# 判断端口状态
if tcp_flags_reply & 0x12 == 0x12:
return "open"
elif tcp_flags_reply & 0x14 == 0x14:
return "closed"
else:
return "filtered"
except socket.timeout:
return "filtered"
except socket.error:
return "error"
finally:
if 'raw_socket' in locals():
raw_socket.close()
def calculate_checksum(packet):
"""计算 IP/TCP 头部校验和"""
if len(packet) % 2 != 0:
packet += b'\0'
res = sum(array.unpack("!H", packet[i:i+2])[0] for i in range(0, len(packet), 2))
res = (res >> 16) + (res & 0xffff)
res += res >> 16
return (~res) & 0xffff