feat(main): 添加本地发送端口功能

- 在图形界面中添加本地发送端口输入框
- 在发送数据包时根据用户输入使用指定的本地端口
- 支持UDP、TCP、DNS和IP报文类型使用自定义本地端口
This commit is contained in:
fly6516 2025-01-08 14:30:11 +08:00
parent aa143115d5
commit 62df3394e5

16
main.py
View File

@ -257,6 +257,7 @@ def send_packet():
dest_host = dest_entry.get() dest_host = dest_entry.get()
dest_port = port_entry.get() dest_port = port_entry.get()
packet_type = var.get() packet_type = var.get()
local_port = local_port_entry.get() # 获取本地发送端口
# 验证目标地址 # 验证目标地址
if not validate_ip_or_domain(dest_host): if not validate_ip_or_domain(dest_host):
@ -266,9 +267,13 @@ def send_packet():
if not validate_port(dest_port): if not validate_port(dest_port):
raise ValueError("端口号无效必须是有效的正整数1-65535") raise ValueError("端口号无效必须是有效的正整数1-65535")
# 验证本地发送端口号
if local_port and not validate_port(local_port):
raise ValueError("本地发送端口号无效必须是有效的正整数1-65535")
# 解析目标IP地址 # 解析目标IP地址
dest_ip = socket.gethostbyname(dest_host) dest_ip = socket.gethostbyname(dest_host)
src_port = 12345 src_port = int(local_port) if local_port else 12345 # 使用用户输入的本地端口或默认端口
dest_port = int(dest_port) dest_port = int(dest_port)
# ICMP报文需要添加 RTT 计算 # ICMP报文需要添加 RTT 计算
@ -299,9 +304,11 @@ def send_packet():
# 对于其他报文类型UDP, TCP, DNS, IP # 对于其他报文类型UDP, TCP, DNS, IP
if packet_type == "UDP": if packet_type == "UDP":
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', src_port)) # 绑定本地发送端口
packet = construct_udp(src_port, dest_port) packet = construct_udp(src_port, dest_port)
elif packet_type == "TCP": elif packet_type == "TCP":
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', src_port)) # 绑定本地发送端口
sock.connect((dest_ip, dest_port)) sock.connect((dest_ip, dest_port))
packet = b"Hello, TCP!" # TCP 是面向连接的,这里发送简单的字符串 packet = b"Hello, TCP!" # TCP 是面向连接的,这里发送简单的字符串
sock.sendall(packet) sock.sendall(packet)
@ -312,6 +319,7 @@ def send_packet():
dns_server = '8.8.8.8' # Google Public DNS dns_server = '8.8.8.8' # Google Public DNS
port = 53 port = 53
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', src_port)) # 绑定本地发送端口
query_packet = build_dns_query(dest_host) query_packet = build_dns_query(dest_host)
sock.sendto(query_packet, (dns_server, port)) sock.sendto(query_packet, (dns_server, port))
response, _ = sock.recvfrom(512) response, _ = sock.recvfrom(512)
@ -331,6 +339,7 @@ def send_packet():
# 创建原始套接字 # 创建原始套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # 告诉内核IP头部已包含在数据包中 sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # 告诉内核IP头部已包含在数据包中
sock.bind(('', src_port)) # 绑定本地发送端口
# 发送IP报文 # 发送IP报文
sock.sendto(packet, (dest_ip, 0)) sock.sendto(packet, (dest_ip, 0))
@ -369,6 +378,11 @@ ip_combobox = ttk.Combobox(window, values=local_ips)
ip_combobox.grid(row=1, column=1) ip_combobox.grid(row=1, column=1)
ip_combobox.current(0) ip_combobox.current(0)
# 配置本地发送端口输入框
tk.Label(window, text="本地发送端口:").grid(row=1, column=2)
local_port_entry = tk.Entry(window)
local_port_entry.grid(row=1, column=3)
# 配置目标地址输入框 # 配置目标地址输入框
tk.Label(window, text="目标地址:").grid(row=2, column=0) tk.Label(window, text="目标地址:").grid(row=2, column=0)
dest_entry = tk.Entry(window) dest_entry = tk.Entry(window)