https 攔截器

說明

先安裝依賴,腳本運行后訪問 http://mitm.it 安裝證書。

pip install mitmproxy pywin32

腳本

import atexit
import sys
import winreg
import subprocess
import asyncio
import os
from datetime import datetime
from mitmproxy import http, options
from mitmproxy.tools.dump import DumpMaster

# 配置參數(shù)
PROXY_PORT = 28181
RESPONSE_CONFIG = {
    "url1": '{"status":"0"}'.encode('utf-8'),
    "url2": '{"code":1}'.encode('utf-8'),
}
PROXY_BYPASS = '<local>;localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*'

class Logger:
    @staticmethod
    def log(action: str, details: str = ""):
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] {action}: {details}\n"
        with open("proxy.log", "a", encoding="utf-8") as f:
            f.write(log_entry)
        print(log_entry.strip())

class WindowsProxyManager:
    def __init__(self):
        self.original_settings = {}
        self.reg_path = r"Software\Microsoft\Windows\CurrentVersion\Internet Settings"

    def set_proxy(self, enable: bool):
        try:
            with winreg.OpenKey(winreg.HKEY_CURRENT_USER, self.reg_path, 0, winreg.KEY_ALL_ACCESS) as key:
                if enable:
                    self._backup_settings(key)
                    self._apply_proxy(key)
                else:
                    self._restore_settings(key)  # 確保方法存在
        except PermissionError:
            Logger.log("錯誤", "需要管理員權限")
            sys.exit(1)
        except Exception as e:
            Logger.log("代理錯誤", str(e))
            sys.exit(1)
        self._set_winhttp_proxy(enable)

    def _backup_settings(self, key):
        """備份原始注冊表設置"""
        self.original_settings = {
            "ProxyServer": "",
            "ProxyEnable": 0,
            "ProxyOverride": ""
        }
        # try:
        #     self.original_settings = {
        #         "ProxyServer": winreg.QueryValueEx(key, "ProxyServer")[0],
        #         "ProxyEnable": winreg.QueryValueEx(key, "ProxyEnable")[0],
        #         "ProxyOverride": winreg.QueryValueEx(key, "ProxyOverride")[0]
        #     }
        #     Logger.log("系統(tǒng)代理", "備份成功")
        # except FileNotFoundError:
        #     Logger.log("警告", "初始代理設置不存在")
        #     self.original_settings = {
        #         "ProxyServer": "",
        #         "ProxyEnable": 0,
        #         "ProxyOverride": ""
        #     }

    def _apply_proxy(self, key):
        """應用新代理設置"""
        winreg.SetValueEx(key, "ProxyServer", 0, winreg.REG_SZ, f"127.0.0.1:{PROXY_PORT}")
        winreg.SetValueEx(key, "ProxyEnable", 0, winreg.REG_DWORD, 1)
        winreg.SetValueEx(key, "ProxyOverride", 0, winreg.REG_SZ, PROXY_BYPASS)
        self._refresh_system_settings()
        Logger.log("系統(tǒng)代理", "已啟用新配置")

    def _restore_settings(self, key):
        """恢復原始設置(新增此方法)"""
        winreg.SetValueEx(
            key, 
            "ProxyServer", 
            0, 
            winreg.REG_SZ, 
            self.original_settings.get("ProxyServer", "")
        )
        winreg.SetValueEx(
            key, 
            "ProxyEnable", 
            0, 
            winreg.REG_DWORD, 
            self.original_settings.get("ProxyEnable", 0)
        )
        winreg.SetValueEx(
            key, 
            "ProxyOverride", 
            0, 
            winreg.REG_SZ, 
            self.original_settings.get("ProxyOverride", "")
        )
        self._refresh_system_settings()
        Logger.log("系統(tǒng)代理", "已恢復原始配置")

    def _refresh_system_settings(self):
        """刷新系統(tǒng)設置(修復here-string格式)"""
        try:
            # 使用精確格式化的 PowerShell 命令
            Logger.log("當前的 系統(tǒng) 代理服務器設置")
            ps_command = r'''
Add-Type -TypeDefinition @" 
using System.Runtime.InteropServices;
public class WinInet {
    [DllImport("wininet.dll")]
    public static extern bool InternetSetOption(int hInternet, int dwOption, int lpBuffer, int dwBufferLength);
}
"@
[WinInet]::InternetSetOption(0, 39, 0, 0) >$null
[WinInet]::InternetSetOption(0, 37, 0, 0) >$null
Get-ItemProperty -Path "HKCU:\\Software\\Microsoft\Windows\\CurrentVersion\\Internet Settings" | Select-Object ProxyServer, ProxyEnable, ProxyOverride
'''
            subprocess.run(
                ["powershell", "-Command", ps_command.strip()],
                check=True,
                timeout=10
            )
            Logger.log("系統(tǒng)刷新", "成功通知系統(tǒng)更新代理設置")
        except subprocess.CalledProcessError as e:
            Logger.log("刷新失敗", f"錯誤代碼: {e.returncode}")
        except subprocess.TimeoutExpired:
            Logger.log("刷新超時", "系統(tǒng)未及時響應")

    def _set_winhttp_proxy(self, enable: bool):
        """配置系統(tǒng)級代理"""
        try:
            cmd = (f'netsh winhttp set proxy 127.0.0.1:{PROXY_PORT} bypass-list="{PROXY_BYPASS}"' 
                   if enable else 'netsh winhttp reset proxy')
            
            result = subprocess.run(
                cmd,
                shell=True,
                check=True,
                capture_output=True,
                text=True
            )
            Logger.log(result.stdout.strip())
        except subprocess.CalledProcessError as e:
            Logger.log("WinHTTP錯誤", e.stderr.strip())

class RequestInterceptor:
    async def request(self, flow: http.HTTPFlow):
        # 遍歷所有配置的URL
        for url in RESPONSE_CONFIG:
            if url in flow.request.pretty_url:
                Logger.log("攔截請求", f"{flow.request.url} -> 返回預設響應")
                flow.response = http.Response.make(
                    200,
                    RESPONSE_CONFIG[url],
                    {"Content-Type": "application/json; charset=utf-8"}
                )
                return  # 匹配到第一個符合的URL即返回

async def proxy_main():
    """修復后的異步主函數(shù)"""
    proxy_mgr = WindowsProxyManager()
    
    # if input("是否自動配置系統(tǒng)代理?(y/n) ").lower() != 'y':
    #     print("請手動設置代理: 127.0.0.1:28181")
    #     return

    proxy_mgr.set_proxy(True)
    atexit.register(proxy_mgr.set_proxy, False)

    # 初始化 mitmproxy 實例
    opts = options.Options(
        listen_port=PROXY_PORT,
        ssl_insecure=True,
        http2=True
    )
    master = DumpMaster(opts)
    master.addons.add(RequestInterceptor())

    try:
        print(f"\n{' MITM代理已啟動 ':=^40}")
        print(f"| 監(jiān)聽端口: {PROXY_PORT:^24} |")
        print(f"{'':=^40}\n")
        
        # 使用官方推薦的運行方式
        await master.run()
    except asyncio.CancelledError:
        Logger.log("狀態(tài)", "正在關閉代理服務...")
    finally:
        # 正確關閉資源
        if hasattr(master, "server"):
            master.server.close()
            Logger.log("狀態(tài)", "網(wǎng)絡端口已釋放")

def main():
    """主入口函數(shù)"""
    if os.name == 'nt':
        from ctypes import windll
        if not windll.shell32.IsUserAnAdmin():
            windll.shell32.ShellExecuteW(
                None, "runas", sys.executable, " ".join(sys.argv), None, 1
            )
            return

    Logger.log("啟動", f"進程ID: {os.getpid()}")
    
    try:
        asyncio.run(proxy_main())
    except KeyboardInterrupt:
        Logger.log("狀態(tài)", "用戶主動終止操作")
    finally:
        Logger.log("關閉", "服務已停止")

if __name__ == "__main__":
    main()
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容