Windsurf
Windsurf 是由 Codeium 公司开发的,旨在提供一种简单、高效的方式来创建单页应用程序(SPA)。
在codeium.com/windsurf 下载,目前还是免费
对话是交流
- 拦截本电脑发出的所有请求信息
我将创建一个Python脚本来监控本机的网络请求。我们将使用`scapy`库来捕获和分析网络数据包。
Created packet_sniffer.py +136-0 0
这个脚本需要使用sudo权限来运行,因为网络数据包捕获需要系统级权限。使用方法:
sudo python3 packet_sniffer.py
脚本功能:
1. 捕获所有经过本机网卡的网络数据包
1. 识别常见协议:TCP、UDP、HTTP、HTTPS、DNS等
1. 显示每个请求的详细信息:
- 时间戳
- 协议类型
- 源IP和端口
- 目标IP和端口
- 数据包大小
- 特殊信息(如DNS查询内容)
1. 自动将捕获的数据保存为JSON文件
1. 按Ctrl+C可以优雅地停止捕获
注意事项:
1. 需要root/管理员权限运行
1. 会显示所有网络请求,包括系统和应用程序的请求
1. 对于HTTPS请求,由于加密原因,只能看到基本连接信息,无法查看具体内容
1. 保存的JSON文件可以后续用于分析或处理
```js
```python
#!/usr/bin/env python3
from scapy.all import *
from datetime import datetime
import threading
import queue
import signal
import sys
import socket
class PacketSniffer:
def __init__(self):
self.packet_queue = queue.Queue()
self.is_running = False
self.dns_cache = {}
self.service_names = {
21: 'FTP',
22: 'SSH',
23: 'Telnet',
25: 'SMTP',
53: 'DNS',
80: 'HTTP',
110: 'POP3',
143: 'IMAP',
443: 'HTTPS',
465: 'SMTPS',
587: 'SMTP(SSL)',
993: 'IMAPS',
995: 'POP3S',
1080: 'SOCKS',
1433: 'MSSQL',
1521: 'Oracle',
3306: 'MySQL',
3389: 'RDP',
5432: 'PostgreSQL',
6379: 'Redis',
8080: 'HTTP-Proxy',
8443: 'HTTPS-Alt',
27017: 'MongoDB'
}
def get_hostname(self, ip):
"""获取IP地址对应的域名"""
if ip in self.dns_cache:
return self.dns_cache[ip]
try:
hostname = socket.gethostbyaddr(ip)[0]
self.dns_cache[ip] = hostname
return hostname
except (socket.herror, socket.gaierror):
self.dns_cache[ip] = ip
return ip
def get_service_name(self, port):
"""获取端口对应的服务名称"""
return self.service_names.get(port, str(port))
def packet_callback(self, packet):
"""回调函数,处理每个捕获的数据包"""
self.packet_queue.put(packet)
def process_packet(self, packet):
"""处理数据包并提取详细信息"""
packet_info = {
'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'),
'protocol': None,
'src_ip': None,
'src_host': None,
'dst_ip': None,
'dst_host': None,
'src_port': None,
'src_service': None,
'dst_port': None,
'dst_service': None,
'length': len(packet),
'info': '',
'payload': '',
'payload_hex': '',
'payload_ascii': '',
'flags': [],
'headers': {},
'raw_layers': []
}
# 以太网层处理
if Ether in packet:
ether = packet[Ether]
packet_info['mac_src'] = ether.src
packet_info['mac_dst'] = ether.dst
packet_info['raw_layers'].append({
'layer': 'Ethernet',
'type': hex(ether.type),
'src': ether.src,
'dst': ether.dst
})
# IP层处理
if IP in packet:
ip = packet[IP]
# 解析IP和主机名
src_ip = ip.src
dst_ip = ip.dst
packet_info.update({
'src_ip': src_ip,
'dst_ip': dst_ip,
'src_host': self.get_hostname(src_ip),
'dst_host': self.get_hostname(dst_ip),
'ttl': ip.ttl,
'ip_version': ip.version,
'ip_ihl': ip.ihl,
'ip_tos': ip.tos,
'ip_len': ip.len,
'ip_id': ip.id,
'ip_flags': ip.flags,
'ip_frag': ip.frag
})
packet_info['raw_layers'].append({
'layer': 'IP',
'version': ip.version,
'ihl': ip.ihl,
'tos': ip.tos,
'len': ip.len,
'id': ip.id,
'flags': str(ip.flags),
'frag': ip.frag,
'ttl': ip.ttl,
'proto': ip.proto,
'src': ip.src,
'dst': ip.dst
})
# TCP协议处理
if TCP in packet:
tcp = packet[TCP]
packet_info['protocol'] = 'TCP'
src_port = tcp.sport
dst_port = tcp.dport
packet_info.update({
'src_port': src_port,
'dst_port': dst_port,
'src_service': self.get_service_name(src_port),
'dst_service': self.get_service_name(dst_port),
'seq': tcp.seq,
'ack': tcp.ack,
'window': tcp.window
})
# TCP标志位
flags = []
if tcp.flags.F: flags.append('FIN')
if tcp.flags.S: flags.append('SYN')
if tcp.flags.R: flags.append('RST')
if tcp.flags.P: flags.append('PSH')
if tcp.flags.A: flags.append('ACK')
if tcp.flags.U: flags.append('URG')
packet_info['flags'] = flags
# 应用层协议检测和处理
# HTTP
if tcp.dport == 80 or tcp.sport == 80:
packet_info['protocol'] = 'HTTP'
try:
if Raw in packet:
raw_data = packet[Raw].load
packet_info['payload'] = raw_data
try:
# 尝试解码为UTF-8文本
payload = raw_data.decode('utf-8', errors='ignore')
# 解析HTTP请求/响应
if payload.startswith(('GET', 'POST', 'PUT', 'DELETE', 'HTTP/')):
lines = payload.split('\r\n')
packet_info['info'] = lines[0] # HTTP请求/响应行
# 提取URL或文件名
if ' ' in lines[0]:
parts = lines[0].split(' ')
if len(parts) > 1:
path = parts[1]
if '?' in path:
path = path.split('?')[0]
if '/' in path:
packet_info['filename'] = path.split('/')[-1] or '/'
# 解析HTTP头
for line in lines[1:]:
if ': ' in line:
key, value = line.split(': ', 1)
packet_info['headers'][key] = value
# 从Content-Disposition提取文件名
if key.lower() == 'content-disposition':
if 'filename=' in value:
filename = value.split('filename=')[-1].strip('"')
packet_info['filename'] = filename
# 查找可能的文件名模式
import re
# 常见文件扩展名模式
file_pattern = r'[\w\-. ]+\.(jpg|jpeg|png|gif|pdf|doc|docx|xls|xlsx|zip|rar|txt|html|xml|json)'
found_files = re.findall(file_pattern, payload, re.IGNORECASE)
if found_files:
packet_info['found_files'] = found_files
# 查找URL模式
url_pattern = r'https?://[\w\-\.]+\.[a-zA-Z]{2,}[\w\-\./\?\=\&\%]*'
found_urls = re.findall(url_pattern, payload)
if found_urls:
packet_info['found_urls'] = found_urls
except UnicodeDecodeError:
# 如果不是文本数据,检查是否是二进制文件格式
if raw_data.startswith(b'PK\x03\x04'): # ZIP文件头
packet_info['file_type'] = 'ZIP Archive'
elif raw_data.startswith(b'%PDF'): # PDF文件头
packet_info['file_type'] = 'PDF Document'
elif raw_data.startswith(b'\xff\xd8\xff'): # JPEG文件头
packet_info['file_type'] = 'JPEG Image'
elif raw_data.startswith(b'\x89PNG\r\n'): # PNG文件头
packet_info['file_type'] = 'PNG Image'
elif raw_data.startswith(b'GIF87a') or raw_data.startswith(b'GIF89a'): # GIF文件头
packet_info['file_type'] = 'GIF Image'
except Exception as e:
packet_info['parse_error'] = str(e)
# HTTPS/TLS
elif tcp.dport == 443 or tcp.sport == 443:
packet_info['protocol'] = 'HTTPS'
if Raw in packet:
try:
# 尝试检测TLS握手
if packet[Raw].load[0] == 0x16: # TLS Handshake
packet_info['info'] = 'TLS Handshake'
elif packet[Raw].load[0] == 0x17: # TLS Application Data
packet_info['info'] = 'TLS Application Data'
else:
packet_info['info'] = 'HTTPS Communication'
except:
packet_info['info'] = 'HTTPS Communication'
# UDP协议处理
elif UDP in packet:
udp = packet[UDP]
src_port = udp.sport
dst_port = udp.dport
packet_info.update({
'protocol': 'UDP',
'src_port': src_port,
'dst_port': dst_port,
'src_service': self.get_service_name(src_port),
'dst_service': self.get_service_name(dst_port),
'udp_len': udp.len
})
# DNS请求检测
if udp.dport == 53 or udp.sport == 53:
packet_info['protocol'] = 'DNS'
if packet.haslayer(DNS):
dns = packet[DNS]
packet_info['dns_id'] = dns.id
if dns.qr == 0: # DNS查询
packet_info['info'] = f"DNS Query: {dns.qd.qname.decode()}"
packet_info['dns_type'] = 'query'
packet_info['dns_qtype'] = dns.qd.qtype
else: # DNS响应
packet_info['info'] = "DNS Response"
packet_info['dns_type'] = 'response'
packet_info['dns_rcode'] = dns.rcode
# 解析DNS应答
answers = []
for i in range(dns.ancount):
rr = dns.an[i]
if hasattr(rr, 'rdata'):
answers.append({
'name': rr.rrname.decode(),
'type': rr.type,
'data': str(rr.rdata)
})
packet_info['dns_answers'] = answers
# ICMP协议处理
elif ICMP in packet:
icmp = packet[ICMP]
packet_info.update({
'protocol': 'ICMP',
'icmp_type': icmp.type,
'icmp_code': icmp.code
})
if icmp.type == 8:
packet_info['info'] = 'ICMP Echo Request (Ping)'
elif icmp.type == 0:
packet_info['info'] = 'ICMP Echo Reply (Ping)'
return packet_info
def print_packet_info(self, packet_info):
"""打印数据包详细信息"""
print("\n" + "="*80)
print(f"时间: {packet_info['time']}")
print(f"协议: {packet_info['protocol']}")
# 显示文件名或URL信息
if 'filename' in packet_info:
print(f"\n检测到文件名: {packet_info['filename']}")
if 'file_type' in packet_info:
print(f"文件类型: {packet_info['file_type']}")
if 'found_files' in packet_info:
print("\n检测到的文件:")
for file in packet_info['found_files']:
print(f" - {file}")
if 'found_urls' in packet_info:
print("\n检测到的URL:")
for url in packet_info['found_urls']:
print(f" - {url}")
# 网络层信息
if 'mac_src' in packet_info:
print(f"MAC地址: {packet_info['mac_src']} -> {packet_info['mac_dst']}")
print(f"源地址: {packet_info['src_ip']} ({packet_info['src_host']}):{packet_info['src_port']} ({packet_info['src_service']})")
print(f"目标地址: {packet_info['dst_ip']} ({packet_info['dst_host']}):{packet_info['dst_port']} ({packet_info['dst_service']})")
# 分层协议详细信息
print("\n分层协议信息:")
for layer in packet_info['raw_layers']:
print(f"\n {layer['layer']} 层:")
for key, value in layer.items():
if key != 'layer':
print(f" {key}: {value}")
# 传输层信息
if packet_info['protocol'] == 'TCP':
print("\nTCP详细信息:")
print(f" 序列号: {packet_info.get('seq', 'N/A')}")
print(f" 确认号: {packet_info.get('ack', 'N/A')}")
if packet_info['flags']:
print(f" TCP标志: {', '.join(packet_info['flags'])}")
# 应用层信息
print(f"\n数据包大小: {packet_info['length']} bytes")
if packet_info['info']:
print(f"协议信息: {packet_info['info']}")
# HTTP头信息
if packet_info['headers']:
print("\nHTTP头信息:")
for key, value in packet_info['headers'].items():
print(f" {key}: {value}")
# DNS详细信息
if packet_info['protocol'] == 'DNS':
print("\nDNS详细信息:")
print(f" 类型: {packet_info.get('dns_type', 'N/A')}")
if 'dns_answers' in packet_info:
print(" 解析结果:")
for answer in packet_info['dns_answers']:
print(f" {answer['name']} -> {answer['data']}")
# 显示原始负载
if packet_info['payload'] and len(packet_info['payload']) > 0:
print("\n负载内容:")
try:
# 尝试解码为UTF-8文本并美化显示
text_content = packet_info['payload'].decode('utf-8', errors='ignore')
if any(text_content.startswith(prefix) for prefix in ['GET ', 'POST ', 'PUT ', 'DELETE ', 'HTTP/', '{', '[']):
# 如果是HTTP请求/响应或JSON数据,保持原格式
print(" 文本内容:")
for line in text_content.split('\n')[:20]: # 限制显示前20行
print(f" {line.strip()}")
if len(text_content.split('\n')) > 20:
print(" ...")
else:
# 其他文本内容
print(" 文本内容:")
preview = text_content[:200]
print(f" {preview}" + ('...' if len(text_content) > 200 else ''))
except UnicodeDecodeError:
# 如果不是文本,显示十六进制格式
print(" 二进制内容 (HEX):")
hex_payload = ' '.join(f'{b:02x}' for b in packet_info['payload'])
print(f" {hex_payload[:200]}" + ('...' if len(hex_payload) > 200 else ''))
print("="*80)
def packet_processor(self):
"""处理数据包队列的线程函数"""
while self.is_running or not self.packet_queue.empty():
try:
packet = self.packet_queue.get(timeout=1)
packet_info = self.process_packet(packet)
if packet_info['protocol']: # 只打印有效的数据包
self.print_packet_info(packet_info)
except queue.Empty:
continue
def start_sniffing(self):
"""开始捕获数据包"""
self.is_running = True
# 启动数据包处理线程
processor_thread = threading.Thread(target=self.packet_processor)
processor_thread.start()
print("开始捕获网络请求...")
print("按 Ctrl+C 停止捕获")
# 开始捕获数据包
try:
sniff(prn=self.packet_callback, store=0)
except Exception as e:
print(f"捕获错误: {e}")
finally:
self.stop_sniffing()
processor_thread.join()
def stop_sniffing(self):
"""停止捕获数据包"""
self.is_running = False
print("\n停止捕获...")
def main():
sniffer = PacketSniffer()
def signal_handler(sig, frame):
print("\n正在优雅地停止...")
sniffer.stop_sniffing()
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
sniffer.start_sniffing()
if __name__ == "__main__":
main()
==========================================
时间: 2025-03-26 10:37:54.991109
协议: HTTPS
MAC地址: xxxx -> xxx
源地址: xxx:52375 (52375)
目标地址: xxxx:443 (HTTPS)
分层协议信息:
Ethernet 层:
type: 0x800 src: xxxx dst: xxx
IP 层:
version: 4 ihl: 5 tos: 0 len: 52 id: 0 flags: DF frag: 0 ttl: 64 proto: 6 src: xxx dst: xxx
数据包大小: 66 bytes
=======================================