1. 程式人生 > >BaseProxy:異步http/https中間人

BaseProxy:異步http/https中間人

response 默認 chrom version 下載 安裝ca證書 image www. 參考

BaseProxy

異步http/https代理,可攔截並修改報文,可以作為中間人工具.僅支持py3.5+.項目地址:BaseProxy。

意義

BaseProxy項目的本意是為了使HTTP/HTTPS攔截更加純粹,更加易操作,學習成本更低。

在Python領域,中間人工具非常強大和成功的是MitmProxy,但是有些地方不是很喜歡。

  • Windows上安裝比較費時費力
  • 功能太多了,可惜我用不到這麽多(似乎不是它的錯,哈哈)
  • 隨著版本升級,采用插件化框架,需要定制功能,需要寫個插件成為它的一部分(我只是想集成它而已).

因此BaseProxy就誕生了,不僅支持HTTPS透明傳輸,還支持HTTP/HTTPS攔截,簡單易用,可以很好地集成到你們的項目中。

安裝

安裝非常簡單,本項目已經發布到PyPI中...

pip3 install baseproxy

使用配置

啟動baseproxy

在test文件夾下,有很多測試用例。以startserver.py為例。

from baseproxy.proxy import AsyncMitmProxy

baseproxy = AsyncMitmProxy(https=True)

baseproxy.serve_forever()

使用上述代碼,就可以將HTTPServer運行起來了.對代碼的解釋如下:

  • https=True是對https進行解密;https=False是對於https實行透傳
  • baseproxy默認運行在8788端口,如果想改變端口的話,修改為AsyncMitmProxy(server_addr=(‘‘,port),https=True)
    .

運行結果如下:

[2018-06-22 18:46:32] INFO HTTPServer is running at address(  , 8788 )......

安裝CA證書

1.將chrome瀏覽器代理服務器設置為127.0.0.1:8788,推薦使用SwitchyOmega插件.

技術分享圖片

2.設置好代理,並將baseproxy運行後,訪問www.baidu.com.

技術分享圖片

3.這時候訪問被拒絕,需要安裝證書.在當前網頁訪問 baseproxy.ca,下載證書.

技術分享圖片

4.雙擊下載的證書,並安裝到合法機構中.

技術分享圖片

技術分享圖片
技術分享圖片
5.接著訪問百度就可以了.

技術分享圖片

註意:只有https=True時,才需要安裝CA證書。

開發

經過上一步的使用配置,baseproxy已經可以正常運行了,但是這樣是遠遠不夠的.baseproxy還提供了接口,方便開發者對http請求和響應進行修改.

接口

baseproxy提供了兩個接口,一個是修改請求,一個是修改響應.

攔截請求

class ReqIntercept(InterceptPlug):

    def deal_request(self,request):
        pass

對於請求的攔截,需要繼承ReqIntercept類,並重寫其中的deal_request函數.在deal_request函數的最後,需要將修改後的request參數返回出去.
如果想拋棄這個請求,直接返回None.

request參數

deal_request函數中的request參數類型為Request類

成員變量

Name 類型 含義
hostname str 域名
port int 端口
command str 請求類型
path str 請求路徑
request_version str HTTP協議版本

成員函數


    def set_headers(self,headers)
     - headers:類型為dict
     - 用於設置頭部
    def get_header(self,key):
    - key:類型為str
    - 用於獲取指定頭部,返回str
    def get_headers(self):
    - 用於獲取整個頭部,返回為dict
    def set_header(self,key,value):
    - 頭部 key,類型str
    - 頭部 value,類型str
    - 用於設置頭信息
    def get_body_data(self):
    - 獲取請求體內容,返回類型為bytes
    def set_body_data(self,body):
    - 設置請求體內容,body類型為bytes

攔截響應

class RspIntercept(InterceptPlug):

    def deal_response(self,response):
        pass

對於響應的攔截,需要繼承RspIntercept類,並重寫其中的deal_response函數.在deal_response函數的最後,需要將修改後的response參數返回出去.
如果想拋棄這個響應,直接返回None.

response參數

deal_response函數中的response參數類型為Response類

成員變量

Name 類型 含義
hostname str 域名
port int 端口
status int 狀態碼
reason str 狀態描述
response_version str HTTP協議版本
request Request 響應對應的請求實例

成員函數


    def set_headers(self,headers)
     - headers:類型為dict
     - 用於設置頭部
    def get_header(self,key):
    - key:類型為str
    - 用於獲取指定頭部,返回str
    def get_headers(self):
    - 用於獲取整個頭部,返回為dict
    def set_header(self,key,value):
    - 頭部 key,類型str
    - 頭部 value,類型str
    - 用於設置頭信息
    def get_body_data(self):
    - 獲取響應體內容,返回類型為bytes
    def set_body_data(self,body):
    - 設置響應體內容,body類型為bytes
    def get_body_str(self,decoding=None):
    - decoding:編碼,默認為None,內部采用chardet探測
    - 返回響應體,類型為str.如果無法解碼,返回None
    def set_body_str(self,body_str,encoding=None):
    - encoding:編碼,默認為None,內部采用chardet探測
    - 設置響應體,body_str類型為str

註冊攔截插件

將攔截類完成後,需要註冊到baseproxy中,需要調用AsyncMitmProxy的register函數.示例如下:

from baseproxy.proxy import ReqIntercept, RspIntercept, AsyncMitmProxy
__author__ = ‘qiye‘
__date__ = ‘2018/6/21 23:35‘

class DebugInterceptor(ReqIntercept, RspIntercept):
    def deal_request(self, request):
        return request

    def deal_response(self, response):
        return response

if __name__=="__main__":

    baseproxy = AsyncMitmProxy(https=False)
    baseproxy.register(DebugInterceptor)
    baseproxy.serve_forever()

小例子

將淘寶中的所有產品圖片換成我公眾號的二維碼.代碼在test文件夾的replace_image.py中,內容如下:

from baseproxy.proxy import RspIntercept, AsyncMitmProxy



class ImageInterceptor( RspIntercept):

    def deal_response(self, response):
        if response.get_header("Content-Type") and ‘image‘ in response.get_header("Content-Type"):
            with open("../img/qiye2.jpg",‘rb‘) as f:
                response.set_body_data(f.read())
        return response


if __name__ == "__main__":
    baseproxy = AsyncMitmProxy(https=True)
    baseproxy.register(ImageInterceptor)
    baseproxy.serve_forever()

效果如下:

技術分享圖片

參考項目

MitmProxy
proxy2

福利大放送

關註公眾號:七夜安全博客

技術分享圖片

  • 回復【1】:領取 Python數據分析 教程大禮包
  • 回復【2】:領取 Python Flask 全套教程
  • 回復【3】:領取 某學院 機器學習 教程
  • 回復【4】:領取 爬蟲 教程

知識星球已經50人了,隨著人數的增多,價格之後會上漲,越早關註越多優惠。星球的福利有很多:

  • 比如上面的教程,已經提前在知識星球中分享
  • 可以發表一些問題,大家一塊解決
  • 我之後寫的電子書,錄制的教學視頻,對於知識星球的朋友都是優惠的(基本上免費)
  • 一些節假日會給大家發個紅包或者贈書

技術分享圖片

BaseProxy:異步http/https中間人