将 PyQt5 WebEngine 请求转换为 IP 数据包,反之亦然
Convert PyQt5 WebEngine request into IP packet and vice-versa
使用PyQt5,我已经成功建立了一个QWebEngineUrlRequestInterceptor子类,我可以修改web请求的头部和数据。我正在为类似 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())
问题是当您需要 IP 信息(第 3 层)时,QWebEngineUrlRequestInterceptor
与 HTTP(第 7 层)交互。 QWebEngineUrlRequestInfo 没有任何 IP 属性(同样位于第 7 层)。
虽然可以使用 Qt,但 QHostInfo, it's simpler to use vanilla Python. Here, we are using netifaces. While it's not in the standard library, alternatives 更复杂、依赖于平台或需要互联网连接。
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 \
使用PyQt5,我已经成功建立了一个QWebEngineUrlRequestInterceptor子类,我可以修改web请求的头部和数据。我正在为类似 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())
问题是当您需要 IP 信息(第 3 层)时,QWebEngineUrlRequestInterceptor
与 HTTP(第 7 层)交互。 QWebEngineUrlRequestInfo 没有任何 IP 属性(同样位于第 7 层)。
虽然可以使用 Qt,但 QHostInfo, it's simpler to use vanilla Python. Here, we are using netifaces. While it's not in the standard library, alternatives 更复杂、依赖于平台或需要互联网连接。
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 \