상세 컨텐츠

본문 제목

Be1oxy (Quick Proxy Configuration Tool)

보안/이것저것-잡동사니

by Be1uga 2024. 3. 31. 01:26

본문


윈도우 환경에서 프록시 설정을 할때 간편하게 사용할 수 있습니다.

 

코드 내 

17 : self.auto_config_url = 'http://pac.com'
18 : self.proxy_server_addr1 = '127.0.0.1:8080'

 

해당 부분을 내부 환경에 맞게 수정 후 EXE 으로 만들어서 사용하시면 편합니다

 

import winreg
import binascii
import ctypes
import tkinter as tk
from tkinter import ttk
from typing import Any
import subprocess
import sys

class ProxyConfig:
    """프록시 설정을 담당하는 클래스입니다."""

    INTERNET_OPTION_REFRESH = 37
    INTERNET_OPTION_SETTINGS_CHANGED = 39

    def __init__(self):
        self.auto_config_url = 'http://pac.com'
        self.proxy_server_addr1 = '127.0.0.1:8080'
        self.internet_settings = self.open_key(winreg.HKEY_CURRENT_USER,
            r'Software\Microsoft\Windows\CurrentVersion\Internet Settings')
        self.connections = self.open_key(winreg.HKEY_CURRENT_USER,
            r'Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections')

    def __del__(self):
        """레지스트리 키를 닫습니다."""
        if hasattr(self, 'internet_settings'):
            winreg.CloseKey(self.internet_settings)
        if hasattr(self, 'connections'):
            winreg.CloseKey(self.connections)

    def open_key(self, key, sub_key) -> winreg.HKEYType:
        """레지스트리 키를 열고 핸들을 반환합니다."""
        try:
            handle = winreg.OpenKey(key, sub_key, 0, winreg.KEY_ALL_ACCESS)
            return handle
        except OSError as e:
            print(f"레지스트리 키 열기 실패: {e}")
            return None

    def set_key(self, key: winreg.HKEYType, subkey: str, value: Any) -> None:
        """레지스트리 키 값을 설정하는 함수입니다."""
        if key is None:
            return
        
        try:
            _, reg_type = winreg.QueryValueEx(key, subkey)
            winreg.SetValueEx(key, subkey, 0, reg_type, value)
        except FileNotFoundError as e:
            # [수정] 지정된 파일을 찾을 수 없는 경우 새로운 값을 생성합니다.
            print(f"레지스트리 키 값 생성: {subkey}")
            winreg.SetValueEx(key, subkey, 0, winreg.REG_SZ, value)
        except WindowsError as e:
            print(f"레지스트리 키 설정 중 오류 발생: {e}")

    def auto_config_enable(self) -> None:
        """자동 구성을 활성화하는 함수입니다."""
        if self.connections is None:
            return
        
        try:
            value, _ = winreg.QueryValueEx(self.connections, "DefaultConnectionSettings")
            auto_config = binascii.b2a_hex(value)
            auto_config = auto_config[:16] + b'09' + auto_config[18:]
            auto_config = binascii.a2b_hex(auto_config)
            self.set_key(self.connections, 'DefaultConnectionSettings', auto_config)
        except WindowsError as e:
            print(f"자동 구성 활성화 중 오류 발생: {e}")

    def auto_config_disable(self) -> None:
        """자동 구성을 비활성화하는 함수입니다."""
        if self.connections is None:
            return
        
        try:
            value, _ = winreg.QueryValueEx(self.connections, "DefaultConnectionSettings")
            auto_config = binascii.b2a_hex(value)
            auto_config = auto_config[:16] + b'01' + auto_config[18:]
            auto_config = binascii.a2b_hex(auto_config)
            self.set_key(self.connections, 'DefaultConnectionSettings', auto_config)
        except WindowsError as e:
            print(f"자동 구성 비활성화 중 오류 발생: {e}")

    def proxy_enable(self, proxy_addr: str) -> None:
        """프록시를 활성화하는 함수입니다."""
        if self.internet_settings is None:
            return
        
        self.set_key(self.internet_settings, 'ProxyEnable', 1)
        self.set_key(self.internet_settings, 'ProxyServer', proxy_addr)

    def proxy_disable(self, label: tk.Label) -> None:
        """프록시를 비활성화하는 함수입니다."""
        if self.internet_settings is None:
            return
        
        self.set_key(self.internet_settings, 'ProxyEnable', 0)
        self.set_key(self.internet_settings, 'AutoConfigURL', '')
        self.refresh()
        label.config(text="🚀 Proxy OFF 🚀")

    def refresh(self) -> None:
        """브라우저 설정을 새로고침하는 함수입니다."""
        internet_set_option = ctypes.windll.Wininet.InternetSetOptionW
        internet_set_option(0, self.INTERNET_OPTION_REFRESH, 0, 0)
        internet_set_option(0, self.INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)

    def set_pac(self, label: tk.Label) -> None:
        """PAC 설정을 하는 함수입니다."""
        if self.internet_settings is None:
            return
        
        self.proxy_disable(label)
        self.set_key(self.internet_settings, 'AutoConfigURL', self.auto_config_url)
        self.refresh()
        label.config(text="🚀 PAC URL 🚀")

    def set_proxy1(self, label: tk.Label) -> None:
        """Proxy1 설정을 하는 함수입니다."""
        if self.internet_settings is None:
            return
        
        self.proxy_enable(self.proxy_server_addr1)
        self.set_key(self.internet_settings, 'AutoConfigURL', '')
        self.refresh()
        label.config(text="🚀 127.0.0.1:8080 🚀")

    def get_exceptions(self) -> str:
        """ProxyOverride 키 값을 가져오는 함수입니다."""
        if self.internet_settings is None:
            return ""
        
        try:
            return winreg.QueryValueEx(self.internet_settings, 'ProxyOverride')[0]
        except WindowsError as e:
            print(f"ProxyOverride 값 가져오기 중 오류 발생: {e}")
            return ""

    def set_exceptions(self, value: str) -> None:
        """ProxyOverride 키 값을 설정하는 함수입니다."""
        if self.internet_settings is None:
            return
        
        self.set_key(self.internet_settings, 'ProxyOverride', value)

    def edit_hosts(self, label: tk.Label) -> None:
        """관리자 권한으로 hosts 파일을 편집하는 함수입니다."""
        try:
            if sys.platform.startswith('win'):
                command = 'Start-Process notepad -ArgumentList "$env:windir\System32\drivers\etc\hosts" -Verb RunAs'
                subprocess.run(["powershell", "-Command", command], check=True)
                label.config(text="🚀 Editing Hosts 🚀")
            else:
                print("이 기능은 Windows에서만 지원됩니다.")
        except subprocess.CalledProcessError:
            print("hosts 파일 편집을 위한 관리자 권한을 얻지 못했습니다.")
        except Exception as e:
            print(f"hosts 파일 편집 중 오류 발생: {e}")


class ProxyGUI:
    def __init__(self, proxy_config: ProxyConfig):
        self.proxy_config = proxy_config
        self.root = tk.Tk()
        self.setup_gui()

    def setup_gui(self) -> None:
        self.root.title("Be1oxy")
        self.root.geometry("207x230")
        self.root.resizable(False, False)
        self.root.config(bg='#F0F0F0')  # Light gray background

        self.current_label = tk.Label(self.root, text="www.1231.me", font=("Arial", 12, "bold"), fg='#333333', bg='#F0F0F0')
        self.current_label.pack()

        self.exceptions_frame = tk.Frame(self.root, height=40)
        self.exceptions_frame.pack_propagate(0)
        self.exceptions_frame.pack(fill=tk.BOTH, expand=True)

        self.exceptions_text = tk.Text(self.exceptions_frame, height=2, font=("Arial", 11), wrap=tk.WORD, bg='#FFFFFF', fg='#333333')
        self.exceptions_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        self.exceptions_scrollbar = tk.Scrollbar(self.exceptions_frame, command=self.exceptions_text.yview)
        self.exceptions_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.exceptions_text.config(yscrollcommand=self.exceptions_scrollbar.set)

        self.exceptions_text.insert("1.0", self.proxy_config.get_exceptions().replace(';', '\n'))

        button_style = {"font": ("Arial", 12, "bold"), "borderwidth": 0, "relief": tk.FLAT, "fg": "#FFFFFF"}

        update_button = tk.Button(self.root, text="URL Bypass", command=self.update_exceptions, bg='#6C757D', **button_style)
        update_button.pack(fill=tk.X)

        edit_hosts_button = tk.Button(self.root, text="Edit Hosts", command=lambda: self.proxy_config.edit_hosts(self.current_label), bg='#FFC107', **button_style)
        edit_hosts_button.pack(fill=tk.X)

        pac_button = tk.Button(self.root, text="Auto-Configuration", command=lambda: self.proxy_config.set_pac(self.current_label), bg='#8BC34A', **button_style)
        pac_button.pack(fill=tk.X)

        proxy1_button = tk.Button(self.root, text="127.0.0.1:8080", command=lambda: self.proxy_config.set_proxy1(self.current_label), bg='#2196F3', **button_style)
        proxy1_button.pack(fill=tk.X)

        proxy_off_button = tk.Button(self.root, text="Proxy OFF", command=lambda: self.proxy_config.proxy_disable(self.current_label), bg='#F44336', **button_style)
        proxy_off_button.pack(fill=tk.X)

        self.is_topmost = tk.BooleanVar()
        topmost_checkbutton = tk.Checkbutton(self.root, text="Always on Top", variable=self.is_topmost, command=self.toggle_topmost, bg='#F0F0F0', font=("Arial", 9), fg="#333333")
        topmost_checkbutton.pack(pady=(3))

    def update_exceptions(self) -> None:
        """예외 주소를 업데이트하는 함수입니다."""
        exceptions = self.exceptions_text.get("1.0", tk.END).replace('\n', ';')
        self.proxy_config.set_exceptions(exceptions)
        self.exceptions_text.delete("1.0", tk.END)
        self.exceptions_text.insert("1.0", self.proxy_config.get_exceptions().replace(';', '\n'))

    def toggle_topmost(self) -> None:
        self.root.attributes('-topmost', self.is_topmost.get())

    def run(self) -> None:
        self.root.mainloop()


def main():
    proxy_config = ProxyConfig()
    gui = ProxyGUI(proxy_config)
    gui.run()

if __name__ == "__main__":
    main()