2016-04-23 87 views
0

我試圖調試HTTPS連接使用mitmproxy和Python 3.這個想法如下:代理運行本地,並告訴Python使用它的HTTPS連接; Python必須接受由mitmproxy創建的自簽名證書才能正常工作,如果一切順利,mitmproxy的控制檯會向我顯示已解碼的請求/響應對。麻煩通過mitmproxy HTTPS通信

我能夠用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變量的代碼失敗,「拒絕連接」(如預期),並使用ssl_ctx作品代碼好 - 這表明我假設代理根本沒有被使用。

+0

所以我猜這是不可能的默認情況下,注意'目前urllib.request不支持通過代理獲取https位置。但是,這可以通過擴展urllib.request來啓用,如配方[6]所示。'在https://docs.python.org/3/howto/urllib2.html#id13中是這樣說的。它導致的配方是針對Python 2,其中一個註釋鏈接到Python 3版本,該版本與'TypeError:do_open()失敗,在urllib代碼深處有一個意外的關鍵字參數'context'。我不會試圖讓它繼續工作,沒有意義。 – wujek

回答

1

感謝您詢問併發布您嘗試的代碼。我不確定爲什麼文檔聲稱不支持通過代理獲取HTTPS,因爲它確實有效。

除了明確地傳遞SSL上下文之外,我還創建並安裝了ProxyHandler以外的HTTPSHandler。這個工作對我(的Python 3.5 + mitmproxy):

import urllib.request 
import ssl 

ssl_ctx = ssl.create_default_context() 
ssl_ctx.check_hostname = False 
ssl_ctx.verify_mode = ssl.CERT_NONE 

ssl_handler = urllib.request.HTTPSHandler(context=ssl_ctx) 
proxy_handler = urllib.request.ProxyHandler({'https': 'localhost:8080'}) 

opener = urllib.request.build_opener(ssl_handler, proxy_handler) 
urllib.request.install_opener(opener) 


if __name__ == '__main__': 
    req = urllib.request.Request('https://...') 

    with urllib.request.urlopen(req) as res: 
     print(res.read().decode('utf8')) 

一旦安裝了這個揭幕戰中,它被用來作爲默認使用的urllib,即使是在第三方庫的所有請求 - 這正是我需要的。

但我不確定,爲什麼你的註釋行不起作用。也許在urlopen中傳遞上下文會安裝一個覆蓋自定義代碼的新開啓器。