【发布时间】:2016-04-23 18:47:01
【问题描述】:
我正在尝试使用mitmproxy 和 Python 3 调试 HTTPS 连接。想法如下:代理在本地运行,我告诉 Python 将其用于 HTTPS 连接; Python 必须接受mitmproxy 创建的自签名证书才能正常工作,如果一切顺利,mitmproxy 的控制台将显示解码后的请求/响应对。
我可以用 Python 3 和requests 做我想做的事,但是我必须使用标准的urllib 来做,唉,我失败了。代码如下:
#!/usr/bin/env python3
import urllib.request
import ssl
proxy = urllib.request.ProxyHandler({'https': 'localhost:8080'})
opener = urllib.request.build_opener(proxy)
urllib.request.install_opener(opener)
ssl_ctx = ssl.create_default_context()
ssl_ctx.check_hostname = False
ssl_ctx.verify_mode = ssl.CERT_NONE
#ssl_ctx = ssl._create_unverified_context()
req = urllib.request.Request('https://github.com')
with urllib.request.urlopen(req) as res:
#with urllib.request.urlopen(req, context=ssl_ctx) as res:
print(res.read().decode('utf8'))
执行上述代码时,我得到一个 ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败 (_ssl.c:645) 错误,这意味着使用了代理,但其证书未验证。这正是我期望在这一点上发生的事情。
当我使用注释掉的行来使用ssl_context(以任何方式创建)时,我得到了我请求的页面的内容,但代理控制台从不显示解码的请求信息,它保持空白。就好像使用 ssl_context 完全绕过了代理。
有人可以帮助我并告诉我我做错了什么吗?
编辑:为了确保,我将代理端口更改为 8081,现在使用 ssl_ctx 变量的代码 not 失败并显示“连接被拒绝”(正如预期的那样),并且使用 ssl_ctx 的代码工作正常 - 这表明我的假设是根本没有使用代理。
【问题讨论】:
-
所以我猜默认情况下这是不可能的,注释'当前 urllib.request 不支持通过代理获取 https 位置。但是,这可以通过扩展 urllib.request 来启用,如配方 [6] 中所示。在docs.python.org/3/howto/urllib2.html#id13 中是这样说的。它导致的配方适用于 Python 2,其中一个 cmets 链接到 Python 3 版本,该版本因 'TypeError: do_open() got an unexpected keyword argument 'context'' 在 urllib 代码深处的某处而失败。我不会再让它工作了,没有意义。
标签: python-3.x https proxy