python - 将 PyQt5 WebEngine 请求转换为 IP 数据包,反之亦然
问题描述
使用 PyQt5,我已经成功设置了一个 QWebEngineUrlRequestInterceptor 子类,我可以修改 web 请求的 headers 和 data。我正在为类似 VPN 的应用程序构建它,其中请求被转换为数据包(使用 scapy 的IP()
对象或类似模块发送),加密并发送到另一个地址,该地址将解密并将数据包数据转换回 QWebEngine 请求. 我的问题是如何将使用 PyQt5 拦截的 Web 请求转换为 IP 数据包格式,反之亦然?
这是拦截器代码:
#Custom url interceptor for modifying headers
#and the url before sending it on
class UrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
def __init__(self,parent=None):
super(QWebEngineUrlRequestInterceptor,self).__init__(parent)
def interceptRequest(self,info):
#Modify the actual request here - todo: block the
#request here, packet simulate etc...
info.setHttpHeader(b"Accept-Language",InterClassVariables.languageCode.encode())
解决方案
问题是QWebEngineUrlRequestInterceptor
当您需要 IP 信息(第 3 层)时,它与 HTTP(第 7 层)交互。QWebEngineUrlRequestInfo没有任何 IP 属性(同样位于第 7 层)。
虽然可以使用 Qt 的QHostInfo,但使用普通 Python 更简单。在这里,我们使用netifaces。虽然它不在标准库中,但替代方案更复杂、依赖于平台或需要 Internet 连接。
import socket
from PyQt5.Qt import QUrl
from PyQt5.Qt import QWebEngineUrlRequestInterceptor
from PyQt5.Qt import QWebEngineUrlRequestInfo
import netifaces
from scapy.all import IP
#Custom url interceptor for modifying headers
#and the url before sending it on
class UrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
def __init__(self,parent=None):
super(QWebEngineUrlRequestInterceptor,self).__init__(parent)
self.info = None
def interceptRequest(self, info: QWebEngineUrlRequestInfo):
#Modify the actual request here - todo: block the
#request here, packet simulate etc...
self.info = info
self.info.setHttpHeader(b"Accept-Language",
InterClassVariables.languageCode.encode())
self.sendPacket()
def getDestIp(self):
qUrl = self.info.requestURL()
url = qUrl.toString()
dest_ip = socket.gethostbyname(url)
return dest_ip
def sendPacket()
src_ip = netifaces.gateways()['default'][netifaces.AF_INET][0]
dest_ip = get_dest_ip(self.info)
ip_layer = IP(src=src_ip, dst=dest_ip)
other_layers = OTHER_PROTOCOLS() # FIXME
pkt = ip_layer/other_layers
send(pkt) # Choose whichever send function is most appropriate here
如果我们打印数据包(没有其他层),我们应该得到类似这样的东西:
$ python project.py -show-packet # Pseudo cli
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = ip
chksum = None
src = 172.31.98.1
dst = 151.101.65.69
\options \
推荐阅读
- simplex - 单纯形算法 - 最坏情况
- python-3.x - 如何使用 2 个列表并将值合并到一个字典中
- python-3.x - 如何从 OrangeML 模型中获取 Scikit-learn 模型输出?
- javascript - 如何使用猫鼬打开和关闭 TTL 索引?
- xamarin - 以 Xamarin 形式播放视频 - 无法播放视频
- django - 带有反应的Django csv输出
- java - 如何在 Retrofit 上上传没有标题和容器的文件
- android-studio - 更新插件后的警告
- sql - 选择具有特定值的列(虚拟表)
- c# - 从 HelixViewport3D 创建图像