From 688bdce0871daf640a1776a6370f9f33c2a8f676 Mon Sep 17 00:00:00 2001 From: RRRosmontis Date: Tue, 18 Aug 2026 08:13:40 +0000 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=E3=80=8Cfull=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- full/Royirin Rosmontis Private Proxy.lnk | Bin 0 -> 943 bytes full/build.bat | 6 + full/ico.ico | Bin 0 -> 123912 bytes full/jp_client.conf | 11 + full/proxy.py | 2111 ++++++++++++++++++++++ 5 files changed, 2128 insertions(+) create mode 100644 full/Royirin Rosmontis Private Proxy.lnk create mode 100644 full/build.bat create mode 100644 full/ico.ico create mode 100644 full/jp_client.conf create mode 100644 full/proxy.py diff --git a/full/Royirin Rosmontis Private Proxy.lnk b/full/Royirin Rosmontis Private Proxy.lnk new file mode 100644 index 0000000000000000000000000000000000000000..621dc3a63770209b3976ad6cd0fdbc2ea65d7bec GIT binary patch literal 943 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
  • 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 wBF@XN`F45k>f=&4pmZ(x@2l2Zd EXE 解压出的临时目录(_MEIPASS) +# PERSIST_DIR -> EXE 所在目录,服务安装等需要持久化的操作都放这里 +if getattr(sys, 'frozen', False): + BASE_DIR = Path(sys._MEIPASS) + PERSIST_DIR = Path(sys.executable).resolve().parent +else: + BASE_DIR = Path(__file__).resolve().parent + PERSIST_DIR = BASE_DIR + +WG_DIR = BASE_DIR / "wg" +WG_EXE = WG_DIR / "wireguard.exe" +WG_CLI = WG_DIR / "wg.exe" +WG_CONF = BASE_DIR / "jp_client.conf" +WG_SERVICE = "WireGuardTunnel$jp_client" + +# WireGuard 服务安装必须使用 PERSIST_DIR,不能依赖会被清理的 temp 目录 +_PERSIST_WG_EXE = PERSIST_DIR / "wg" / "wireguard.exe" +_PERSIST_WG_CONF = PERSIST_DIR / "jp_client.conf" + +def _endpoint_domain(): + """从 jp_client.conf 的 Endpoint 行解析服务器域名。""" + try: + for line in WG_CONF.read_text(encoding="utf-8").splitlines(): + line = line.strip() + if line.startswith("Endpoint "): + addr = line.split("=", 1)[1].strip() + return addr.rsplit(":", 1)[0] + except Exception: + pass + return "???" + +def _endpoint_port(default=52810): + """从 jp_client.conf 的 Endpoint 行解析服务器端口。""" + try: + for line in WG_CONF.read_text(encoding="utf-8").splitlines(): + line = line.strip() + if line.startswith("Endpoint "): + addr = line.split("=", 1)[1].strip() + return int(addr.rsplit(":", 1)[1]) + except Exception: + pass + return default + +def _listen_port(default=52810): + """从 jp_client.conf 的 ListenPort 行解析本地监听端口。""" + try: + for line in WG_CONF.read_text(encoding="utf-8").splitlines(): + line = line.strip() + if line.startswith("ListenPort "): + return int(line.split("=", 1)[1].strip()) + except Exception: + pass + return default + +def _server_ip(): + """把 endpoint 域名解析为 IPv4 地址,仅用于界面显示。""" + try: + import socket + return socket.getaddrinfo(_endpoint_domain(), 443, socket.AF_INET, socket.SOCK_STREAM)[0][4][0] + except Exception: + return "???" + +def _tcp_endpoint_reachable(port=80, timeout=5): + """测试能否通过 TCP 连到服务器,用于区分"TCP 通但 UDP 被拦截"的场景。""" + try: + import socket + ip = socket.getaddrinfo(_endpoint_domain(), port, socket.AF_INET, socket.SOCK_STREAM)[0][4][0] + with socket.create_connection((ip, port), timeout=timeout): + return True + except Exception: + return False + +# ── 本地认证转发器(直连 / WG 模式均使用) ───────────── +# 本地 127.0.0.1:1080 作为透明 TCP 转发器, +# 直连模式通过 TLS 转发到远端服务器,WG 模式直接转发到 WG 网关。 +# 转发前会在首条 HTTP 请求中自动注入 Proxy-Authorization, +# 使 Windows 应用无需感知 nginx 正向代理的 Basic 认证。 +_TLS_LOCAL_PORT = 1080 +_tls_forwarder = None + +# 系统代理注册表路径,以及当前生效的代理地址 +PROXY_HOST = "127.0.0.1" +PROXY_PORT = _TLS_LOCAL_PORT +PROXY_REG = r"HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" + +# ── PAC 内存服务 ────────────────────────────────────── +# Windows 无法跳过 HTTPS 证书校验下载远程 PAC,因此在本地 127.0.0.1 +# 启动一个极简 HTTP 服务,把 PAC 内容放在内存里供系统读取。 +_pac_server = None # {"server": TCPServer, "port": int} + +# 服务器 PAC 拉取失败时的回退:直接内置服务器上的完整 PAC(直连版本) +# 内容来源: https://tunnel.rrrosmontis.icu/proxy.pac +# 实际使用时根据当前模式替换其中的代理地址 +_BUILT_IN_PAC_DIRECT = r'''function FindProxyForURL(url, host) { + // RRPP 规则代理列表 — 仅以下域名走加密隧道 + var proxy = "PROXY 127.0.0.1:1080"; + // Google 全系 + Gemini + CDN + if (shExpMatch(host, "google.com") || + shExpMatch(host, "*.google.com") || + shExpMatch(host, "google.com.hk") || + shExpMatch(host, "*.google.com.hk") || + shExpMatch(host, "google.co.jp") || + shExpMatch(host, "*.google.co.jp") || + shExpMatch(host, "googleapis.com") || + shExpMatch(host, "*.googleapis.com") || + shExpMatch(host, "googleusercontent.com") || + shExpMatch(host, "*.googleusercontent.com") || + shExpMatch(host, "googletagmanager.com") || + shExpMatch(host, "*.googletagmanager.com") || + shExpMatch(host, "google-analytics.com") || + shExpMatch(host, "*.google-analytics.com") || + shExpMatch(host, "gstatic.com") || + shExpMatch(host, "*.gstatic.com") || + shExpMatch(host, "ggpht.com") || + shExpMatch(host, "*.ggpht.com") || + shExpMatch(host, "googlehosted.com") || + shExpMatch(host, "*.googlehosted.com") || + shExpMatch(host, "1e100.net") || + shExpMatch(host, "*.1e100.net") || + shExpMatch(host, "youtube.com") || + shExpMatch(host, "*.youtube.com") || + shExpMatch(host, "ytimg.com") || + shExpMatch(host, "*.ytimg.com") || + shExpMatch(host, "googlevideo.com") || + shExpMatch(host, "*.googlevideo.com") || + shExpMatch(host, "gemini.google.com") || + shExpMatch(host, "*.gemini.google.com") || + shExpMatch(host, "generativeai.googleapis.com") || + shExpMatch(host, "*.generativeai.googleapis.com") || + shExpMatch(host, "aistudio.google.com") || + shExpMatch(host, "*.aistudio.google.com") || + shExpMatch(host, "deepmind.google.com") || + shExpMatch(host, "*.deepmind.google.com") || + shExpMatch(host, "deepmind.com") || + shExpMatch(host, "*.deepmind.com")) { + return proxy; + } + + // OpenAI / ChatGPT 全系 + CDN + if (shExpMatch(host, "openai.com") || + shExpMatch(host, "*.openai.com") || + shExpMatch(host, "chatgpt.com") || + shExpMatch(host, "*.chatgpt.com") || + shExpMatch(host, "oaistatic.com") || + shExpMatch(host, "*.oaistatic.com") || + shExpMatch(host, "oaiusercontent.com") || + shExpMatch(host, "*.oaiusercontent.com") || + shExpMatch(host, "openaiusercontent.com") || + shExpMatch(host, "*.openaiusercontent.com")) { + return proxy; + } + + // Grok / xAI 全系 + CDN + if (shExpMatch(host, "grok.com") || + shExpMatch(host, "*.grok.com") || + shExpMatch(host, "x.com") || + shExpMatch(host, "*.x.com") || + shExpMatch(host, "twitter.com") || + shExpMatch(host, "*.twitter.com") || + shExpMatch(host, "twimg.com") || + shExpMatch(host, "*.twimg.com") || + shExpMatch(host, "x.ai") || + shExpMatch(host, "*.x.ai") || + shExpMatch(host, "xai.com") || + shExpMatch(host, "*.xai.com")) { + return proxy; + } + + // Meta 全系 + CDN + if (shExpMatch(host, "meta.com") || + shExpMatch(host, "*.meta.com") || + shExpMatch(host, "meta.ai") || + shExpMatch(host, "*.meta.ai") || + shExpMatch(host, "facebook.com") || + shExpMatch(host, "*.facebook.com") || + shExpMatch(host, "fb.com") || + shExpMatch(host, "*.fb.com") || + shExpMatch(host, "fbcdn.net") || + shExpMatch(host, "*.fbcdn.net") || + shExpMatch(host, "fbsbx.com") || + shExpMatch(host, "*.fbsbx.com") || + shExpMatch(host, "instagram.com") || + shExpMatch(host, "*.instagram.com") || + shExpMatch(host, "cdninstagram.com") || + shExpMatch(host, "*.cdninstagram.com") || + shExpMatch(host, "threads.net") || + shExpMatch(host, "*.threads.net") || + shExpMatch(host, "whatsapp.com") || + shExpMatch(host, "*.whatsapp.com") || + shExpMatch(host, "whatsapp.net") || + shExpMatch(host, "*.whatsapp.net") || + shExpMatch(host, "messenger.com") || + shExpMatch(host, "*.messenger.com")) { + return proxy; + } + + // Claude / Anthropic 全系 + CDN + if (shExpMatch(host, "anthropic.com") || + shExpMatch(host, "*.anthropic.com") || + shExpMatch(host, "claude.ai") || + shExpMatch(host, "*.claude.ai") || + shExpMatch(host, "claudeusercontent.com") || + shExpMatch(host, "*.claudeusercontent.com")) { + return proxy; + } + + // Cloudflare 全系 + if (shExpMatch(host, "cloudflare.com") || + shExpMatch(host, "*.cloudflare.com") || + shExpMatch(host, "cloudflare.net") || + shExpMatch(host, "*.cloudflare.net") || + shExpMatch(host, "cloudflareinsights.com") || + shExpMatch(host, "*.cloudflareinsights.com") || + shExpMatch(host, "cloudflarestatus.com") || + shExpMatch(host, "*.cloudflarestatus.com") || + shExpMatch(host, "cloudflarecdn.com") || + shExpMatch(host, "*.cloudflarecdn.com") || + shExpMatch(host, "cf-cdn.com") || + shExpMatch(host, "*.cf-cdn.com") || + shExpMatch(host, "workers.dev") || + shExpMatch(host, "*.workers.dev") || + shExpMatch(host, "pages.dev") || + shExpMatch(host, "*.pages.dev")) { + return proxy; + } + + // GitHub 全系 + if (shExpMatch(host, "github.com") || + shExpMatch(host, "*.github.com") || + shExpMatch(host, "githubusercontent.com") || + shExpMatch(host, "*.githubusercontent.com") || + shExpMatch(host, "githubassets.com") || + shExpMatch(host, "*.githubassets.com") || + shExpMatch(host, "github.io") || + shExpMatch(host, "*.github.io") || + shExpMatch(host, "githubcopilot.com") || + shExpMatch(host, "*.githubcopilot.com") || + shExpMatch(host, "ghcr.io") || + shExpMatch(host, "*.ghcr.io")) { + return proxy; + } + + // Hugging Face 全系 + CDN + if (shExpMatch(host, "huggingface.co") || + shExpMatch(host, "*.huggingface.co") || + shExpMatch(host, "hf.co") || + shExpMatch(host, "*.hf.co") || + shExpMatch(host, "huggingfacecdn.com") || + shExpMatch(host, "*.huggingfacecdn.com")) { + return proxy; + } + + // Microsoft Copilot 全系 + Bing + Azure CDN + if (shExpMatch(host, "microsoft.com") || + shExpMatch(host, "*.microsoft.com") || + shExpMatch(host, "bing.com") || + shExpMatch(host, "*.bing.com") || + shExpMatch(host, "bingapis.com") || + shExpMatch(host, "*.bingapis.com") || + shExpMatch(host, "bing.net") || + shExpMatch(host, "*.bing.net") || + shExpMatch(host, "live.com") || + shExpMatch(host, "*.live.com") || + shExpMatch(host, "microsoftonline.com") || + shExpMatch(host, "*.microsoftonline.com") || + shExpMatch(host, "microsoft365.com") || + shExpMatch(host, "*.microsoft365.com") || + shExpMatch(host, "office.com") || + shExpMatch(host, "*.office.com") || + shExpMatch(host, "office.net") || + shExpMatch(host, "*.office.net") || + shExpMatch(host, "azure.com") || + shExpMatch(host, "*.azure.com") || + shExpMatch(host, "azureedge.net") || + shExpMatch(host, "*.azureedge.net") || + shExpMatch(host, "azurefd.net") || + shExpMatch(host, "*.azurefd.net") || + shExpMatch(host, "msn.com") || + shExpMatch(host, "*.msn.com") || + shExpMatch(host, "msecnd.net") || + shExpMatch(host, "*.msecnd.net") || + shExpMatch(host, "msftncsi.com") || + shExpMatch(host, "*.msftncsi.com") || + shExpMatch(host, "s-microsoft.com") || + shExpMatch(host, "*.s-microsoft.com")) { + return proxy; + } + + // Steam 全系 + CDN / 社区 / 下载 + if (shExpMatch(host, "steampowered.com") || + shExpMatch(host, "*.steampowered.com") || + shExpMatch(host, "steamcommunity.com") || + shExpMatch(host, "*.steamcommunity.com") || + shExpMatch(host, "steam.com") || + shExpMatch(host, "*.steam.com") || + shExpMatch(host, "steamgames.com") || + shExpMatch(host, "*.steamgames.com") || + shExpMatch(host, "steamusercontent.com") || + shExpMatch(host, "*.steamusercontent.com") || + shExpMatch(host, "steamcontent.com") || + shExpMatch(host, "*.steamcontent.com") || + shExpMatch(host, "steamstatic.com") || + shExpMatch(host, "*.steamstatic.com") || + shExpMatch(host, "steam-chat.com") || + shExpMatch(host, "*.steam-chat.com") || + shExpMatch(host, "steam-api.com") || + shExpMatch(host, "*.steam-api.com") || + shExpMatch(host, "steamserver.net") || + shExpMatch(host, "*.steamserver.net") || + shExpMatch(host, "steamcdn-a.akamaihd.net") || + shExpMatch(host, "*.steamcdn-a.akamaihd.net") || + shExpMatch(host, "steamcommunity-a.akamaihd.net") || + shExpMatch(host, "*.steamcommunity-a.akamaihd.net") || + shExpMatch(host, "steamstore-a.akamaihd.net") || + shExpMatch(host, "*.steamstore-a.akamaihd.net") || + shExpMatch(host, "steamuserimages-a.akamaihd.net") || + shExpMatch(host, "*.steamuserimages-a.akamaihd.net") || + shExpMatch(host, "akamaihd.net") || + shExpMatch(host, "*.akamaihd.net") || + shExpMatch(host, "valvesoftware.com") || + shExpMatch(host, "*.valvesoftware.com")) { + return proxy; + } + + // Discord 全系 + if (shExpMatch(host, "discord.com") || + shExpMatch(host, "*.discord.com") || + shExpMatch(host, "discordapp.com") || + shExpMatch(host, "*.discordapp.com") || + shExpMatch(host, "discord.gg") || + shExpMatch(host, "*.discord.gg") || + shExpMatch(host, "discord.media") || + shExpMatch(host, "*.discord.media") || + shExpMatch(host, "discordapp.net") || + shExpMatch(host, "*.discordapp.net")) { + return proxy; + } + + // Telegram 全系 + if (shExpMatch(host, "telegram.org") || + shExpMatch(host, "*.telegram.org") || + shExpMatch(host, "t.me") || + shExpMatch(host, "*.t.me") || + shExpMatch(host, "telega.one") || + shExpMatch(host, "*.telega.one") || + shExpMatch(host, "telegram-cdn.org") || + shExpMatch(host, "*.telegram-cdn.org")) { + return proxy; + } + + // Reddit 全系 + if (shExpMatch(host, "reddit.com") || + shExpMatch(host, "*.reddit.com") || + shExpMatch(host, "redd.it") || + shExpMatch(host, "*.redd.it") || + shExpMatch(host, "redditmedia.com") || + shExpMatch(host, "*.redditmedia.com") || + shExpMatch(host, "redditstatic.com") || + shExpMatch(host, "*.redditstatic.com")) { + return proxy; + } + + // LINE 全系 + if (shExpMatch(host, "line.me") || + shExpMatch(host, "*.line.me") || + shExpMatch(host, "line-apps.com") || + shExpMatch(host, "*.line-apps.com") || + shExpMatch(host, "line-scdn.net") || + shExpMatch(host, "*.line-scdn.net")) { + return proxy; + } + + // Spotify 全系 + if (shExpMatch(host, "spotify.com") || + shExpMatch(host, "*.spotify.com") || + shExpMatch(host, "spotifycdn.com") || + shExpMatch(host, "*.spotifycdn.com") || + shExpMatch(host, "scdn.co") || + shExpMatch(host, "*.scdn.co")) { + return proxy; + } + + // Netflix 全系 + if (shExpMatch(host, "netflix.com") || + shExpMatch(host, "*.netflix.com") || + shExpMatch(host, "nflxvideo.net") || + shExpMatch(host, "*.nflxvideo.net") || + shExpMatch(host, "nflximg.net") || + shExpMatch(host, "*.nflximg.net") || + shExpMatch(host, "nflxext.com") || + shExpMatch(host, "*.nflxext.com")) { + return proxy; + } + + // Disney+ 全系 + if (shExpMatch(host, "disneyplus.com") || + shExpMatch(host, "*.disneyplus.com") || + shExpMatch(host, "disney-plus.net") || + shExpMatch(host, "*.disney-plus.net") || + shExpMatch(host, "dssott.com") || + shExpMatch(host, "*.dssott.com")) { + return proxy; + } + + // TikTok 全系 + if (shExpMatch(host, "tiktok.com") || + shExpMatch(host, "*.tiktok.com") || + shExpMatch(host, "tiktokcdn.com") || + shExpMatch(host, "*.tiktokcdn.com") || + shExpMatch(host, "tiktokv.com") || + shExpMatch(host, "*.tiktokv.com")) { + return proxy; + } + + // PlayStation 全系 + if (shExpMatch(host, "playstation.com") || + shExpMatch(host, "*.playstation.com") || + shExpMatch(host, "sonyentertainmentnetwork.com") || + shExpMatch(host, "*.sonyentertainmentnetwork.com")) { + return proxy; + } + + // Nintendo 全系 + if (shExpMatch(host, "nintendo.com") || + shExpMatch(host, "*.nintendo.com") || + shExpMatch(host, "nintendowifi.net") || + shExpMatch(host, "*.nintendowifi.net")) { + return proxy; + } + + // Epic Games 全系 + if (shExpMatch(host, "epicgames.com") || + shExpMatch(host, "*.epicgames.com") || + shExpMatch(host, "unrealengine.com") || + shExpMatch(host, "*.unrealengine.com")) { + return proxy; + } + + // DuckDuckGo / Brave Search + if (shExpMatch(host, "duckduckgo.com") || + shExpMatch(host, "*.duckduckgo.com") || + shExpMatch(host, "search.brave.com") || + shExpMatch(host, "*.search.brave.com")) { + return proxy; + } + + // Proton 全系 + if (shExpMatch(host, "proton.me") || + shExpMatch(host, "*.proton.me") || + shExpMatch(host, "protonmail.com") || + shExpMatch(host, "*.protonmail.com") || + shExpMatch(host, "protonvpn.com") || + shExpMatch(host, "*.protonvpn.com")) { + return proxy; + } + + // Stack Overflow / Stack Exchange 全系 + if (shExpMatch(host, "stackoverflow.com") || + shExpMatch(host, "*.stackoverflow.com") || + shExpMatch(host, "stackexchange.com") || + shExpMatch(host, "*.stackexchange.com") || + shExpMatch(host, "superuser.com") || + shExpMatch(host, "*.superuser.com") || + shExpMatch(host, "serverfault.com") || + shExpMatch(host, "*.serverfault.com")) { + return proxy; + } + + // Quora / Medium + if (shExpMatch(host, "quora.com") || + shExpMatch(host, "*.quora.com") || + shExpMatch(host, "medium.com") || + shExpMatch(host, "*.medium.com")) { + return proxy; + } + + // Pixiv 全系 + if (shExpMatch(host, "pixiv.net") || + shExpMatch(host, "*.pixiv.net") || + shExpMatch(host, "pximg.net") || + shExpMatch(host, "*.pximg.net")) { + return proxy; + } + + // ニコニコ 全系 + if (shExpMatch(host, "nicovideo.jp") || + shExpMatch(host, "*.nicovideo.jp") || + shExpMatch(host, "nico.ms") || + shExpMatch(host, "*.nico.ms")) { + return proxy; + } + + // EA / Origin / Apex 全系 + if (shExpMatch(host, "ea.com") || + shExpMatch(host, "*.ea.com") || + shExpMatch(host, "origin.com") || + shExpMatch(host, "*.origin.com") || + shExpMatch(host, "eaassets.com") || + shExpMatch(host, "*.eaassets.com") || + shExpMatch(host, "apexlegends.com") || + shExpMatch(host, "*.apexlegends.com")) { + return proxy; + } + + // Battle.net / Blizzard 全系 + if (shExpMatch(host, "battle.net") || + shExpMatch(host, "*.battle.net") || + shExpMatch(host, "blizzard.com") || + shExpMatch(host, "*.blizzard.com")) { + return proxy; + } + + // Ubisoft 全系 + if (shExpMatch(host, "ubisoft.com") || + shExpMatch(host, "*.ubisoft.com") || + shExpMatch(host, "ubi.com") || + shExpMatch(host, "*.ubi.com")) { + return proxy; + } + + // Riot Games / 英雄联盟 / Valorant 全系 + if (shExpMatch(host, "riotgames.com") || + shExpMatch(host, "*.riotgames.com") || + shExpMatch(host, "leagueoflegends.com") || + shExpMatch(host, "*.leagueoflegends.com") || + shExpMatch(host, "valorant.com") || + shExpMatch(host, "*.valorant.com")) { + return proxy; + } + + // GOG / itch.io 全系 + if (shExpMatch(host, "gog.com") || + shExpMatch(host, "*.gog.com") || + shExpMatch(host, "itch.io") || + shExpMatch(host, "*.itch.io")) { + return proxy; + } + + // Twitch 全系 + if (shExpMatch(host, "twitch.tv") || + shExpMatch(host, "*.twitch.tv") || + shExpMatch(host, "ttvnw.net") || + shExpMatch(host, "*.ttvnw.net") || + shExpMatch(host, "twitchcdn.net") || + shExpMatch(host, "*.twitchcdn.net")) { + return proxy; + } + + // Crunchyroll 全系 + if (shExpMatch(host, "crunchyroll.com") || + shExpMatch(host, "*.crunchyroll.com")) { + return proxy; + } + + // Amazon Prime Video 全系 + if (shExpMatch(host, "primevideo.com") || + shExpMatch(host, "*.primevideo.com")) { + return proxy; + } + + // Apple TV+ 全系 + if (shExpMatch(host, "tv.apple.com") || + shExpMatch(host, "tvplus.apple.com")) { + return proxy; + } + + // HBO Max / Hulu / Paramount+ 全系 + if (shExpMatch(host, "max.com") || + shExpMatch(host, "*.max.com") || + shExpMatch(host, "hulu.com") || + shExpMatch(host, "*.hulu.com") || + shExpMatch(host, "paramountplus.com") || + shExpMatch(host, "*.paramountplus.com")) { + return proxy; + } + + // Slack 全系 + if (shExpMatch(host, "slack.com") || + shExpMatch(host, "*.slack.com") || + shExpMatch(host, "slack-edge.com") || + shExpMatch(host, "*.slack-edge.com") || + shExpMatch(host, "slack-imgs.com") || + shExpMatch(host, "*.slack-imgs.com")) { + return proxy; + } + + // Zoom 全系 + if (shExpMatch(host, "zoom.us") || + shExpMatch(host, "*.zoom.us") || + shExpMatch(host, "zoom.com") || + shExpMatch(host, "*.zoom.com") || + shExpMatch(host, "zoomgov.com") || + shExpMatch(host, "*.zoomgov.com")) { + return proxy; + } + + // Signal 全系 + if (shExpMatch(host, "signal.org") || + shExpMatch(host, "*.signal.org")) { + return proxy; + } + + // Docker 全系 + if (shExpMatch(host, "docker.com") || + shExpMatch(host, "*.docker.com") || + shExpMatch(host, "docker.io") || + shExpMatch(host, "*.docker.io")) { + return proxy; + } + + // GitLab 全系 + if (shExpMatch(host, "gitlab.com") || + shExpMatch(host, "*.gitlab.com") || + shExpMatch(host, "gitlab.io") || + shExpMatch(host, "*.gitlab.io")) { + return proxy; + } + + // Vercel 全系 + if (shExpMatch(host, "vercel.com") || + shExpMatch(host, "*.vercel.com") || + shExpMatch(host, "vercel.app") || + shExpMatch(host, "*.vercel.app")) { + return proxy; + } + + // Netlify 全系 + if (shExpMatch(host, "netlify.com") || + shExpMatch(host, "*.netlify.com") || + shExpMatch(host, "netlify.app") || + shExpMatch(host, "*.netlify.app")) { + return proxy; + } + + // Perplexity / Poe / Midjourney 全系 + if (shExpMatch(host, "perplexity.ai") || + shExpMatch(host, "*.perplexity.ai") || + shExpMatch(host, "poe.com") || + shExpMatch(host, "*.poe.com") || + shExpMatch(host, "midjourney.com") || + shExpMatch(host, "*.midjourney.com")) { + return proxy; + } + + // Figma / Canva 全系 + if (shExpMatch(host, "figma.com") || + shExpMatch(host, "*.figma.com") || + shExpMatch(host, "canva.com") || + shExpMatch(host, "*.canva.com")) { + return proxy; + } + + // LinkedIn 全系 + if (shExpMatch(host, "linkedin.com") || + shExpMatch(host, "*.linkedin.com") || + shExpMatch(host, "licdn.com") || + shExpMatch(host, "*.licdn.com")) { + return proxy; + } + + // Pinterest 全系 + if (shExpMatch(host, "pinterest.com") || + shExpMatch(host, "*.pinterest.com") || + shExpMatch(host, "pinimg.com") || + shExpMatch(host, "*.pinimg.com")) { + return proxy; + } + + // Tumblr 全系 + if (shExpMatch(host, "tumblr.com") || + shExpMatch(host, "*.tumblr.com")) { + return proxy; + } + + // Snapchat 全系 + if (shExpMatch(host, "snapchat.com") || + shExpMatch(host, "*.snapchat.com") || + shExpMatch(host, "sc-cdn.net") || + shExpMatch(host, "*.sc-cdn.net")) { + return proxy; + } + + // Wikipedia / Wikimedia 全系 + if (shExpMatch(host, "wikipedia.org") || + shExpMatch(host, "*.wikipedia.org") || + shExpMatch(host, "wikimedia.org") || + shExpMatch(host, "*.wikimedia.org")) { + return proxy; + } + + // PayPal 全系 + if (shExpMatch(host, "paypal.com") || + shExpMatch(host, "*.paypal.com") || + shExpMatch(host, "paypalobjects.com") || + shExpMatch(host, "*.paypalobjects.com")) { + return proxy; + } + + // Patreon 全系 + if (shExpMatch(host, "patreon.com") || + shExpMatch(host, "*.patreon.com")) { + return proxy; + } + + // 通用 CDN + if (shExpMatch(host, "cloudfront.net") || + shExpMatch(host, "*.cloudfront.net") || + shExpMatch(host, "fastly.net") || + shExpMatch(host, "*.fastly.net") || + shExpMatch(host, "fastlylb.net") || + shExpMatch(host, "*.fastlylb.net") || + shExpMatch(host, "jsdelivr.net") || + shExpMatch(host, "*.jsdelivr.net") || + shExpMatch(host, "unpkg.com") || + shExpMatch(host, "*.unpkg.com") || + shExpMatch(host, "statically.io") || + shExpMatch(host, "*.statically.io") || + shExpMatch(host, "cloudinary.com") || + shExpMatch(host, "*.cloudinary.com") || + shExpMatch(host, "imgur.com") || + shExpMatch(host, "*.imgur.com")) { + return proxy; + } + + // linux.do + if (shExpMatch(host, "linux.do") || + shExpMatch(host, "*.linux.do")) { + return proxy; + } + + return "DIRECT"; +} +''' + +def _build_pac(proxy_spec: str) -> str: + """使用内置完整 PAC,并替换为当前模式对应的代理地址。""" + return _BUILT_IN_PAC_DIRECT.replace( + 'var proxy = "PROXY 127.0.0.1:1080";', + f'var proxy = "PROXY {proxy_spec}";' + ) +def _start_pac_server(pac_content: str) -> int: + """在 127.0.0.1 启动内存 PAC HTTP 服务,返回实际监听的端口。""" + global _pac_server + _stop_pac_server() + import http.server + import socketserver + + class _PACHandler(http.server.BaseHTTPRequestHandler): + def do_GET(self): + if self.path in ("/proxy.pac", "/proxy_wg.pac"): + body = pac_content.encode("utf-8") + self.send_response(200) + self.send_header("Content-Type", "application/x-ns-proxy-autoconfig") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + else: + self.send_response(404) + self.end_headers() + + def log_message(self, format, *args): + pass # 避免在日志区输出大量 HTTP 访问日志 + + class _ReuseAddrTCPServer(socketserver.TCPServer): + allow_reuse_address = True + + srv = _ReuseAddrTCPServer(("127.0.0.1", 0), _PACHandler) + port = srv.server_address[1] + threading.Thread(target=srv.serve_forever, daemon=True).start() + _pac_server = {"server": srv, "port": port} + return port + +def _stop_pac_server(): + """停止本地 PAC HTTP 服务;shutdown() 可能阻塞,因此先关闭 socket 再异步收尾。""" + global _pac_server + if _pac_server: + srv = _pac_server["server"] + _pac_server = None + try: + # 先关闭 socket,让 serve_forever() 从 select/accept 中立即退出 + srv.socket.close() + except Exception: + pass + # 在后台线程里尝试优雅 shutdown,最多等 1 秒,避免阻塞 GUI + def _shutdown(): + try: + srv.shutdown() + except Exception: + pass + try: + srv.server_close() + except Exception: + pass + t = threading.Thread(target=_shutdown, daemon=True) + t.start() + t.join(timeout=1.0) + +# ── 日志输出 ────────────────────────────────────────── +# GUI 初始化后会把 _log_func 设为 MainWindow.log_signal.emit +_log_func = None + +def log(msg: str): + """输出一行日志到 GUI 日志区。""" + if _log_func: + _log_func(msg) + +def log_red(msg: str): + """输出一行红色警告日志到 GUI 日志区。""" + if _log_func: + _log_func(f'{msg}') + +# ── 通用工具函数 ────────────────────────────────────── + +def _run(cmd, warn=True): + """无窗口执行子进程,失败时记录警告日志。""" + r = subprocess.run(cmd, capture_output=True, text=True, + creationflags=subprocess.CREATE_NO_WINDOW) + if warn and r.returncode != 0: + err = r.stderr.strip() if r.stderr else "" + log(f"[警告] {' '.join(str(c) for c in cmd)} -> {r.returncode} {err}") + return r + +def is_admin(): + """判断当前进程是否以管理员身份运行。""" + try: + return ctypes.windll.shell32.IsUserAnAdmin() + except: + return False + +def elevate(): + """非管理员时请求 UAC 提权并重新启动自身。""" + script = str(Path(__file__).resolve()) + cwd = str(Path(__file__).resolve().parent) + # SW_SHOWNORMAL(1):GUI 版本必须显示窗口;编译为 EXE 后由 uac_admin 清单处理 + ctypes.windll.shell32.ShellExecuteW( + None, "runas", sys.executable, f'"{script}"', cwd, 1 + ) + +def _wg_active(max_age=150): + """判断 jp_client 接口是否处于活跃状态。 + + 使用 wg show 的机器可读输出 latest-handshakes(Unix 时间戳), + 不再解析人类可读文本——不同 wg 版本的文案不一致 + (例如刚握手时有的版本输出 "now"),文本解析会误报"握手过旧"。 + """ + r = _run([str(WG_CLI), "show", "jp_client", "latest-handshakes"], warn=False) + out = (r.stdout or "").strip() + if not out: + return False + try: + # 每行格式: \t<最近握手的 Unix 时间戳>,0 表示从未握手 + latest = max(int(line.split()[-1]) for line in out.splitlines() if line.strip()) + except (ValueError, IndexError): + return False + if latest == 0: + return False + return (time.time() - latest) <= max_age + +def _wg_show(): + """返回 jp_client 接口完整状态文本,用于故障诊断。""" + r = _run([str(WG_CLI), "show", "jp_client"], warn=False) + return r.stdout or "" + +def _cleanup_legacy_wg_service(): + """清理旧版 WireGuard 服务名(jp_wg_client.conf 时期遗留)。""" + legacy = "WireGuardTunnel$jp_wg_client" + _run(["sc", "stop", legacy], warn=False) + _run(["sc", "delete", legacy], warn=False) + + +def _service_installed(name): + """通过 sc query 判断服务是否已安装。""" + r = _run(["sc", "query", name], warn=False) + return r.returncode == 0 and "SERVICE_NAME" in (r.stdout or "") + +def _service_running(name): + """通过 sc query 判断服务是否正在运行。""" + r = _run(["sc", "query", name], warn=False) + return r.returncode == 0 and "RUNNING" in (r.stdout or "") + +def _wait_service_state(name, running=True, timeout=15): + """轮询等待服务进入指定状态。""" + for _ in range(timeout): + if _service_running(name) == running: + return True + time.sleep(1) + return False + +def _stop_service(name): + """停止服务并等待其进入停止状态。""" + if not _service_running(name): + return True + _run(["sc", "stop", name], warn=False) + return _wait_service_state(name, running=False, timeout=15) + +def _delete_service(name): + """删除服务并等待其从 sc query 中消失。""" + _run(["sc", "delete", name], warn=False) + for _ in range(10): + if not _service_installed(name): + return True + time.sleep(1) + return False + +def _start_service(name): + """启动服务;1056 表示服务已在运行,也视为成功。""" + r = _run(["sc", "start", name], warn=False) + if r.returncode in (0, 1056): + return True + return False + +def _ensure_persist_wg_files(): + """确保 EXE 目录下存在 wireguard.exe 和 jp_client.conf,供安装服务使用。 + + 打包后 wg/ 和配置在 _MEIPASS 临时目录(BASE_DIR),会被系统清理, + 服务安装必须用持久路径,因此统一从 BASE_DIR 拷贝到 EXE 所在目录。 + """ + try: + import shutil + if not _PERSIST_WG_EXE.exists(): + persist_wg_dir = PERSIST_DIR / "wg" + persist_wg_dir.mkdir(parents=True, exist_ok=True) + for name in ("wireguard.exe", "wg.exe"): + dst = persist_wg_dir / name + if not dst.exists(): + shutil.copy2(str(WG_DIR / name), str(dst)) + log(f" 已拷贝 wg/ 到 {persist_wg_dir}") + if not _PERSIST_WG_CONF.exists(): + shutil.copy2(str(WG_CONF), str(_PERSIST_WG_CONF)) + log(f" 已拷贝配置到 {_PERSIST_WG_CONF}") + return True + except Exception as e: + log(f" 准备服务文件失败: {e}") + return False + +def _install_wg_service(): + """停止并删除旧服务后,用 PERSIST_DIR 中的最新配置重新安装。""" + log(" 安装 WireGuard 隧道服务...") + _cleanup_legacy_wg_service() + if not _ensure_persist_wg_files(): + return False + if _service_installed(WG_SERVICE): + _stop_service(WG_SERVICE) + _delete_service(WG_SERVICE) + ir = _run([str(_PERSIST_WG_EXE), "/installtunnelservice", str(_PERSIST_WG_CONF)]) + log(f" installtunnelservice -> 返回码 {ir.returncode}" + (f" (错误: {ir.stderr.strip()})" if ir.returncode != 0 and ir.stderr.strip() else "")) + if ir.returncode == 0: + # installtunnelservice 注册的服务默认是自动启动,会导致开机关机自连、 + # 程序一打开就显示"已连接"。改为手动启动,只在用户开启代理时拉起隧道。 + _run(["sc", "config", WG_SERVICE, "start=", "demand"], warn=False) + return ir.returncode == 0 + +def _wait_handshake(max_attempts=15, interval=2): + """等待 WireGuard 握手成功。""" + for attempt in range(max_attempts): + time.sleep(interval) + if _wg_active(): + log(f" 握手成功 (第{attempt + 1}次检查)") + return True + return False + + +def wg_on(): + """启动 WireGuard 隧道并等待握手成功。""" + if _wg_active(): + log("WireGuard 隧道已在线") + return True + + # 预检:解析端点域名 + ep = _endpoint_domain() + log(f"预检: 解析端点 {ep} ...") + try: + import socket + wg_port = _endpoint_port() + addr = socket.getaddrinfo(ep, wg_port, socket.AF_INET, socket.SOCK_DGRAM) + ip = addr[0][4][0] + log(f" DNS 解析 -> {ip}:{wg_port}") + except Exception as e: + log(f" DNS 解析失败: {e}") + return False + + log(f"正在启动 WireGuard 服务: {WG_SERVICE} ...") + + # 服务未安装则安装;已安装但未运行则尝试启动 + if not _service_installed(WG_SERVICE): + if not _install_wg_service(): + log("WireGuard 隧道未连通") + return False + elif not _service_running(WG_SERVICE): + if not _start_service(WG_SERVICE): + log(" 服务启动失败,尝试重新安装...") + if not _install_wg_service(): + log("WireGuard 隧道未连通") + return False + + # 等待服务真正进入 RUNNING 状态 + if not _wait_service_state(WG_SERVICE, running=True, timeout=15): + log(" 服务未进入运行状态") + log("WireGuard 隧道未连通") + return False + + log(" 等待握手完成...") + if _wait_handshake(): + log("WireGuard 隧道已连接") + return True + + log(" 握手超时,重启服务重试...") + _stop_service(WG_SERVICE) + _delete_service(WG_SERVICE) + if not _install_wg_service(): + log("WireGuard 隧道未连通") + return False + if not _wait_service_state(WG_SERVICE, running=True, timeout=15): + log(" 服务重启后未进入运行状态") + log("WireGuard 隧道未连通") + return False + + log(" 再次等待握手...") + if _wait_handshake(): + log("WireGuard 隧道已连接") + return True + + log(" 握手仍未完成,当前接口状态:") + show_out = _wg_show() + for line in show_out.splitlines(): + log(f" {line.rstrip()}") + + # 本地接口已启动但有发送无接收,说明对端未响应 UDP 握手 + if "0 B received" in show_out: + wg_port = _endpoint_port() + tcp_ok = _tcp_endpoint_reachable(port=80) + if tcp_ok: + log(f" 诊断: TCP/HTTP 到服务器可达,但 WireGuard UDP {wg_port} 无响应。") + log(f" 常见原因:服务器端 WG 服务未运行、密钥不匹配、或 UDP {wg_port} 被防火墙拦截。") + else: + log(" 诊断: TCP/HTTP 到服务器也不通,可能是服务器整体不可达或本地网络受限。") + + log("WireGuard 隧道未连通") + return False + +def wg_off(): + """停止 WireGuard 服务(即使握手已过期也尝试停止)。""" + _run(["sc", "stop", WG_SERVICE], warn=False) + return True + +def proxy_on(pac_url=None): + """设置 Windows 系统代理。pac_url 不为空时启用 PAC 模式,否则使用固定代理。""" + if pac_url: + # PAC 模式:仅设置 AutoConfigURL,ProxyEnable 置 0, + # 避免程序读到"固定代理已启用但服务器为空"的混乱状态 + _run(["reg", "add", PROXY_REG, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "0", "/f"]) + # PAC 模式:清理固定代理遗留项,避免两种设置冲突 + _run(["reg", "delete", PROXY_REG, "/v", "ProxyServer", "/f"], warn=False) + _run(["reg", "delete", PROXY_REG, "/v", "ProxyOverride", "/f"], warn=False) + _run(["reg", "add", PROXY_REG, "/v", "AutoConfigURL", "/t", "REG_SZ", "/d", pac_url, "/f"]) + log(f"系统代理已设置 (PAC)") + else: + hp = f"{PROXY_HOST}:{PROXY_PORT}" + _run(["reg", "add", PROXY_REG, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "1", "/f"]) + _run(["reg", "add", PROXY_REG, "/v", "ProxyServer", "/t", "REG_SZ", "/d", hp, "/f"]) + _run(["reg", "add", PROXY_REG, "/v", "ProxyOverride", "/t", "REG_SZ", "/d", "", "/f"]) + log(f"系统代理已设置: {hp}") + +def proxy_off(): + """关闭系统代理并停止 TLS 转发器 / PAC 本地服务。""" + log("正在关闭系统代理...") + _run(["reg", "add", PROXY_REG, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "0", "/f"]) + # 清除 ProxyServer 和 AutoConfigURL,确保 PAC / 固定代理两种模式都能正确关闭 + _run(["reg", "delete", PROXY_REG, "/v", "ProxyServer", "/f"], warn=False) + _run(["reg", "delete", PROXY_REG, "/v", "AutoConfigURL", "/f"], warn=False) + log("系统代理已关闭") + _tls_stop() + _stop_pac_server() + +# ── 本地认证转发器(直连 / WG 模式均使用) ───────────────── + +# ── 流量统计 ────────────────────────────────────────── +# 所有代理流量都经过本地 127.0.0.1:1080 转发器(直连 / WG / PAC 均如此), +# 在转发器里计数即可覆盖全部模式。每次"开启代理"时清零,即"本次连接"流量。 +_traffic_lock = threading.Lock() +_traffic = {"up": 0, "down": 0} + +def _traffic_add(up=0, down=0): + with _traffic_lock: + _traffic["up"] += up + _traffic["down"] += down + +def _traffic_reset(): + with _traffic_lock: + _traffic["up"] = _traffic["down"] = 0 + +def _fmt_bytes(n): + f = float(n) + for unit in ("B", "KB", "MB", "GB", "TB"): + if f < 1024 or unit == "TB": + return f"{int(f)} {unit}" if unit == "B" else f"{f:.1f} {unit}" + f /= 1024 + +def _traffic_snapshot(): + with _traffic_lock: + return _traffic["up"], _traffic["down"] + +def _tls_start(remote_host, remote_port=443, use_tls=True): + """启动本地认证转发器:127.0.0.1:1080 -> remote_host:remote_port(可选 TLS 包裹)。""" + global _tls_forwarder + _tls_stop() + import socket, ssl, select + ctx = ssl.create_default_context() + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + + svr = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + svr.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + svr.bind(("127.0.0.1", _TLS_LOCAL_PORT)) + svr.listen(32) + svr.settimeout(1) + _tls_forwarder = {"sock": svr, "running": True} + + proto = "TLS" if use_tls else "TCP" + + def _run(): + while _tls_forwarder and _tls_forwarder.get("running"): + try: + client, addr = svr.accept() + threading.Thread(target=_tls_relay, args=(client, remote_host, remote_port, ctx, use_tls), daemon=True).start() + except socket.timeout: + continue + except Exception: + break + + t = threading.Thread(target=_run, daemon=True) + t.start() + log(f"本地转发器已启动 ({proto} 127.0.0.1:{_TLS_LOCAL_PORT} -> {remote_host}:{remote_port})") + +_HTTP_METHODS = (b"CONNECT ", b"GET ", b"POST ", b"PUT ", b"DELETE ", + b"HEAD ", b"OPTIONS ", b"PATCH ") + +def _starts_with_method(data: bytes) -> bool: + return any(data.startswith(m) for m in _HTTP_METHODS) + +def _inject_proxy_auth(data: bytes) -> bytes: + """在 HTTP 代理请求头中注入 Authorization(如果尚未存在)。 + + nginx 的 auth_basic 校验 Authorization 而非 Proxy-Authorization, + 因此转发器向上游发送 Basic 认证时使用 Authorization 头。 + """ + if not _starts_with_method(data): + return data + end = data.find(b"\r\n\r\n") + if end == -1: + return data + headers_lower = data[:end].lower() + if b"authorization:" in headers_lower: + return data + auth_line = f"Authorization: Basic {_PROXY_AUTH_BASIC}\r\n".encode() + return data[:end + 2] + auth_line + data[end + 2:] + +def _make_request_injector(): + """为明文 HTTP 代理连接生成逐条注入认证的流式处理器。 + + keep-alive 连接上的后续请求同样需要 Authorization,不能只在首包注入。 + 请求头跨包时先缓冲,凑齐 \r\n\r\n(或超过 64KB)后统一处理; + 请求体数据不以方法开头,原样透传。 + 注意:仅用于非 CONNECT 连接;CONNECT 隧道的后续流量是加密的,不能触碰。 + """ + pending = b"" + def feed(data: bytes) -> bytes: + nonlocal pending + if pending: + data, pending = pending + data, b"" + if not _starts_with_method(data): + return data + if b"\r\n\r\n" in data or len(data) >= 65536: + return _inject_proxy_auth(data) + pending = data + return b"" + return feed + +def _tls_relay(client, remote_host, remote_port, ctx, use_tls): + """处理一条客户端连接:注入代理认证后,与远端双向转发。""" + import socket, select + try: + remote = socket.create_connection((remote_host, remote_port), 10) + if use_tls: + remote = ctx.wrap_socket(remote, server_hostname=remote_host) + except Exception as e: + log(f"[转发器] 连接上游失败: {e}") + client.close() + return + + # 读取首包,判定连接类型:CONNECT 隧道 / 明文 HTTP / 其他 + client.settimeout(2.0) + is_connect = False + injector = None + try: + buf = b"" + is_http = None + max_headers = 65536 + while len(buf) < max_headers: + try: + chunk = client.recv(4096) + except socket.timeout: + break + if not chunk: + break + buf += chunk + if is_http is None: + first_crlf = buf.find(b"\r\n") + if first_crlf != -1: + first_line = buf[:first_crlf] + is_http = _starts_with_method(first_line + b" ") + if not is_http: + break + if b"\r\n\r\n" in buf: + break + + if is_http and b"\r\n\r\n" in buf: + is_connect = buf.startswith(b"CONNECT ") + if not is_connect: + # 明文 HTTP 代理:keep-alive 后续请求也要注入认证 + injector = _make_request_injector() + buf = _inject_proxy_auth(buf) + if buf: + remote.sendall(buf) + _traffic_add(up=len(buf)) + except Exception as e: + log(f"[转发器] 读取首包失败: {e}") + client.close() + remote.close() + return + + client.settimeout(None) + remote.settimeout(None) + # CONNECT 隧道承载 WebSocket / 推送等长连接,空闲属正常,不设超时; + # 明文 HTTP 连接空闲 120 秒回收 + idle_timeout = None if is_connect else 120 + try: + while True: + r, _, _ = select.select([client, remote], [], [], idle_timeout) + if not r: + break + if client in r: + data = client.recv(65536) + if not data: + break + if injector is not None: + data = injector(data) # 请求头未收全时会被缓冲,返回空 + if data: + remote.sendall(data) + _traffic_add(up=len(data)) + if remote in r: + data = remote.recv(65536) + if not data: + break + client.sendall(data) + _traffic_add(down=len(data)) + except Exception: + pass + finally: + try: + client.close() + except Exception: + pass + try: + remote.close() + except Exception: + pass + +def _tls_stop(): + """停止 TLS 转发器监听线程。""" + global _tls_forwarder + if _tls_forwarder: + _tls_forwarder["running"] = False + try: + _tls_forwarder["sock"].close() + except Exception: + pass + _tls_forwarder = None + +def is_proxy_on(): + """系统代理是否生效:固定代理已开启,或 AutoConfigURL 指向本地 PAC 服务。""" + r = _run(["reg", "query", PROXY_REG, "/v", "ProxyEnable"], warn=False) + if "0x1" in (r.stdout or ""): + return True + r = _run(["reg", "query", PROXY_REG, "/v", "AutoConfigURL"], warn=False) + return "127.0.0.1" in (r.stdout or "") + +def _cleanup_stale_proxy(): + """清理上次异常退出残留的系统代理设置。 + + TLS 转发器 / PAC 服务只活在进程内,程序启动时若注册表仍指向 + 127.0.0.1:1080 或本地 PAC 地址,说明是残留——不清理会导致全网不通。 + """ + try: + if not is_proxy_on(): + return + r = _run(["reg", "query", PROXY_REG, "/v", "ProxyServer"], warn=False) + r2 = _run(["reg", "query", PROXY_REG, "/v", "AutoConfigURL"], warn=False) + stale = (f"{PROXY_HOST}:{PROXY_PORT}" in (r.stdout or "") + or "127.0.0.1" in (r2.stdout or "")) + if stale: + proxy_off() + except Exception: + pass + +# ── 图标 ────────────────────────────────────────────── + +# 程序图标 base64 编码(原 ico.ico),避免打包后依赖外部资源文件 +_ICO_B64 = "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" + +def load_icon(): + """加载程序图标,base64 解码失败时返回纯色兜底图标。""" + try: + import base64 + data = base64.b64decode(_ICO_B64) + pixmap = QPixmap() + pixmap.loadFromData(data) + if not pixmap.isNull(): + return QIcon(pixmap) + except Exception: + pass + # 兜底:生成一个纯色方形图标 + img = QImage(64, 64, QImage.Format_ARGB32) + img.fill(QColor(C_TITLE)) + return QIcon(QPixmap.fromImage(img)) + +# ── 状态指示灯(小圆点) ─────────────────────────────── + +class StatusDot(QLabel): + """用于 WireGuard / 系统代理状态的小圆点。""" + def __init__(self): + super().__init__() + self.setFixedSize(14, 14) + self.set_off() + + def set_on(self): + self.setStyleSheet(f""" + QLabel {{ + background-color: {C_GREEN}; + border-radius: 7px; + border: 1px solid rgba(81, 207, 102, 50); + }} + """) + + def set_off(self): + self.setStyleSheet(f""" + QLabel {{ + background-color: {C_RED}; + border-radius: 7px; + border: 1px solid rgba(255, 107, 107, 50); + }} + """) + + def set_disabled(self): + """未启用(直连模式下不检测 WireGuard)的中性灰色。""" + self.setStyleSheet(f""" + QLabel {{ + background-color: {C_BORDER}; + border-radius: 7px; + border: 1px solid rgba(136, 153, 170, 50); + }} + """) + +# ── 主窗口 ──────────────────────────────────────────── + +# ── 主窗口 ──────────────────────────────────────────── + +class MainWindow(QWidget): + log_signal = pyqtSignal(str) + _op_done = pyqtSignal(str, bool) + _update_done = pyqtSignal() + _update_download_done = pyqtSignal(bool, str) + _pac_tooltip_ready = pyqtSignal(str) + + _status_ready = pyqtSignal(object) + + def __init__(self): + super().__init__() + self._using_wg = False + self._proxy_set_by_us = False # 系统代理是否由本程序开启(退出时只清理自己设置的) + self._status_busy = False # 防止状态轮询线程堆叠 + # 把全局 log() 函数接到 GUI 日志区 + global _log_func + _log_func = self.log_signal.emit + self.log_signal.connect(self._append_log) + self._op_done.connect(self._after_op) + self._update_done.connect(self._on_update_done) + self._update_download_done.connect(self._on_update_download_done) + self._pac_tooltip_ready.connect(self._set_pac_tooltip) + self._status_ready.connect(self._apply_status) + + self.init_ui() + + # 每 2 秒刷新一次状态指示灯 + self.timer = QTimer() + self.timer.timeout.connect(self.refresh_status) + self.timer.start(2000) + self.refresh_status() + + # 启动时后台检查更新,完成前禁用开启按钮 + threading.Thread(target=self._check_update, daemon=True).start() + + def init_ui(self): + """初始化主界面布局与样式。""" + self.setWindowTitle("Royirin Rosmontis Private Proxy") + self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) + self.setWindowIcon(load_icon()) + self.setFixedSize(_BASE_WINDOW_WIDTH, _BASE_WINDOW_HEIGHT) + + self.setStyleSheet(f""" + QWidget {{ + background-color: {C_BG}; + color: {C_TEXT}; + font-family: "Microsoft YaHei", "Segoe UI", sans-serif; + font-size: 13px; + }} + """) + + layout = QVBoxLayout(self) + layout.setSpacing(14) + layout.setContentsMargins(24, 20, 24, 20) + + # 标题 + title = QLabel("Royirin Rosmontis Private Proxy") + title.setFont(QFont("Microsoft YaHei", 16, QFont.Bold)) + title.setStyleSheet(f"color: {C_TITLE};") + title.setAlignment(Qt.AlignCenter) + layout.addWidget(title) + + # 节点副标题 + subtitle = QLabel(f"节点: {_endpoint_domain()} (JP)") + subtitle.setStyleSheet(f"color: {C_TITLE}; font-size: 12px;") + subtitle.setAlignment(Qt.AlignCenter) + layout.addWidget(subtitle) + + # 连接方式选择区 + mode_layout = QHBoxLayout() + mode_layout.setSpacing(8) + mode_layout.addStretch() + self.mode_group = QButtonGroup(self) + self.rb_direct = QRadioButton("直连") + self.rb_wg = QRadioButton("WG 隧道") + for rb, t in [(self.rb_direct, "直连"), (self.rb_wg, "WG 隧道")]: + rb.setStyleSheet(f""" + QRadioButton {{ + color: {C_SUBTEXT}; font-size: 12px; + }} + QRadioButton::checked {{ + color: {C_TEXT}; font-weight: bold; + }} + """) + self.mode_group.addButton(rb) + mode_layout.addWidget(rb) + self.rb_direct.setChecked(True) + self.mode_group.buttonClicked.connect(self._on_mode_change) + + self.cb_pac = QCheckBox("PAC 规则模式") + self.cb_pac.setChecked(False) # 默认关闭 PAC,由用户按需开启 + self.cb_pac.setStyleSheet(f"color: {C_SUBTEXT}; font-size: 12px;") + self.cb_pac.setToolTip("PAC 规则模式\n\n悬停此处可加载当前规则摘要...") + self.cb_pac.installEventFilter(self) + self._pac_tooltip_loaded = False + self._pac_tooltip_loading = False + mode_layout.addWidget(self.cb_pac) + mode_layout.addStretch() + layout.addLayout(mode_layout) + + # 分隔线 + line = QFrame() + line.setFrameShape(QFrame.HLine) + line.setStyleSheet(f"background-color: rgba(136, 153, 170, 80); max-height: 1px;") + layout.addWidget(line) + + # WireGuard 状态卡片 + wg_frame = QFrame() + wg_frame.setStyleSheet(f""" + QFrame {{ + background-color: {C_CARD}; + border: 1px solid {C_BORDER}; + border-radius: 8px; + }} + """) + wg_layout = QHBoxLayout(wg_frame) + wg_layout.setContentsMargins(16, 12, 16, 12) + wg_label = QLabel("WireGuard 隧道") + wg_label.setStyleSheet(f"color: {C_TEXT}; font-weight: bold; background: transparent;") + self.wg_dot = StatusDot() + self.wg_status = QLabel("检测中...") + self.wg_status.setStyleSheet(f"color: {C_SUBTEXT}; background: transparent;") + wg_layout.addWidget(wg_label) + wg_layout.addStretch() + wg_layout.addWidget(self.wg_status) + wg_layout.addWidget(self.wg_dot) + layout.addWidget(wg_frame) + + # 系统代理状态卡片 + px_frame = QFrame() + px_frame.setStyleSheet(f""" + QFrame {{ + background-color: {C_CARD}; + border: 1px solid {C_BORDER}; + border-radius: 8px; + }} + """) + px_layout = QHBoxLayout(px_frame) + px_layout.setContentsMargins(16, 12, 16, 12) + px_label = QLabel("IE 代理") + px_label.setStyleSheet(f"color: {C_TEXT}; font-weight: bold; background: transparent;") + self.px_dot = StatusDot() + self.px_status = QLabel("检测中...") + self.px_status.setStyleSheet(f"color: {C_SUBTEXT}; background: transparent;") + px_layout.addWidget(px_label) + px_layout.addStretch() + px_layout.addWidget(self.px_status) + px_layout.addWidget(self.px_dot) + layout.addWidget(px_frame) + + layout.addStretch() + + # 开启 / 关闭 代理按钮 + self.btn_toggle = QPushButton("开启代理") + self.btn_toggle.setMinimumHeight(40) + self._set_toggle_button_style(is_start=True) + self.btn_toggle.clicked.connect(self.on_toggle) + self.btn_toggle.setEnabled(False) # 更新检查完成前禁用,避免旧版本被使用 + layout.addWidget(self.btn_toggle) + + # 日志输出区 + self.log_text = QTextEdit() + self.log_text.setReadOnly(True) + self.log_text.setMaximumHeight(140) + self.log_text.setStyleSheet(f""" + QTextEdit {{ + background-color: {C_CARD}; + border: 1px solid {C_BORDER}; + border-radius: 6px; + color: {C_SUBTEXT}; + font-size: 11px; + padding: 4px 6px; + }} + QScrollBar:vertical {{ + width: 6px; + background: transparent; + }} + QScrollBar::handle:vertical {{ + background: {C_BORDER}; + border-radius: 3px; + min-height: 20px; + }} + """) + layout.addWidget(self.log_text) + + # 底部提示小字:独立容器收紧两行间距(主布局 spacing=14 太宽) + hints = QWidget() + hints_layout = QVBoxLayout(hints) + hints_layout.setContentsMargins(0, 0, 0, 0) + hints_layout.setSpacing(1) + + warn_label = QLabel("请勿二次分发此软件!") + warn_label.setStyleSheet(f"color: {C_RED}; font-size: 11px;") + warn_label.setAlignment(Qt.AlignCenter) + hints_layout.addWidget(warn_label) + + # 主背景是白色,纯白字不可见,用接近白的浅灰达到同样的弱化效果 + privacy_label = QLabel("使用此软件将会收集并上报您的IP地址及部分设备信息") + privacy_label.setStyleSheet("color: #c8ccd4; font-size: 9px;") + privacy_label.setAlignment(Qt.AlignCenter) + hints_layout.addWidget(privacy_label) + + layout.addWidget(hints) + + def closeEvent(self, event): + """关闭窗口时自动清理代理和隧道。""" + self.quit_app() + event.accept() + + # ── 开关操作 ── + def _set_toggle_button_style(self, is_start=True): + if is_start: + self.btn_toggle.setText("开启代理") + self.btn_toggle.setStyleSheet(f""" + QPushButton {{ + background-color: {C_GREEN}; color: #fff; border: none; + border-radius: 8px; padding: 10px 24px; + font-size: 14px; font-weight: bold; + }} + QPushButton:hover {{ background-color: #5ed978; }} + QPushButton:pressed {{ background-color: #45b85a; }} + QPushButton:disabled {{ background-color: #2a3a2e; color: #666; }} + """) + else: + self.btn_toggle.setText("关闭代理") + self.btn_toggle.setStyleSheet(f""" + QPushButton {{ + background-color: {C_RED}; color: #fff; border: none; + border-radius: 8px; padding: 10px 24px; + font-size: 14px; font-weight: bold; + }} + QPushButton:hover {{ background-color: #ff8787; }} + QPushButton:pressed {{ background-color: #e05555; }} + QPushButton:disabled {{ background-color: #3a1e1e; color: #666; }} + """) + + def on_toggle(self): + """根据按钮当前文字判断是开启还是关闭。""" + if self.btn_toggle.text() == "开启代理": + self.on_start() + else: + self.on_stop() + + def on_start(self): + """禁用开关按钮与模式/PAC 控件,在后台线程执行开启流程。""" + self.btn_toggle.setEnabled(False) + self.rb_direct.setEnabled(False) + self.rb_wg.setEnabled(False) + self.cb_pac.setEnabled(False) + # 在 GUI 线程读取控件状态传参,避免子线程直接访问 Qt 控件(非线程安全) + use_wg = self.rb_wg.isChecked() + use_pac = self.cb_pac.isChecked() + threading.Thread(target=self._start_thread, args=(use_wg, use_pac), daemon=True).start() + + def _start_thread(self, use_wg, use_pac): + """后台开启代理:启动 WG/TLS,加载 PAC,设置系统代理。""" + try: + self._using_wg = use_wg + _traffic_reset() # 流量统计按"本次连接"计,开启时清零 + if use_wg: + if not wg_on(): + log("WireGuard 隧道未连通,未设置代理") + self._op_done.emit("start", False) + return + log("WG 隧道模式 — 代理走加密隧道") + _tls_start("10.10.0.1", 80, use_tls=False) + else: + log("TLS直连模式") + ep = _endpoint_domain() + log(f" 目标域名: {ep}") + _tls_start(ep, 443, use_tls=True) + if use_pac: + domain = _endpoint_domain() + if domain == "???": + log("无法获取服务器域名,未设置 PAC") + self._op_done.emit("start", False) + return + pac_name = "proxy_wg.pac" if use_wg else "proxy.pac" + proxy_spec = f"{PROXY_HOST}:{PROXY_PORT}" + # Python 自带 SSL 跳过证书校验;Windows 直接取 HTTPS PAC 会因证书不信任失败 + remote_pac_url = f"https://{domain}/{pac_name}" + try: + import urllib.request + req = urllib.request.Request(remote_pac_url) + req.add_header("Authorization", f"Basic {_PROXY_AUTH_BASIC}") + data = urllib.request.urlopen(req, context=_SSL_NO_VERIFY, timeout=10).read().decode("utf-8-sig") + log(" 已从服务器加载 PAC") + # 兼容旧版 WG PAC(可能仍指向 10.10.0.1:80),统一替换为本地转发器 + data = data.replace('"PROXY 10.10.0.1:80"', f'"PROXY {proxy_spec}"') + except Exception as e: + log(f" 服务器 PAC 加载失败,使用内置规则: {e}") + data = _build_pac(proxy_spec) + # 在内存中启动本地 PAC HTTP 服务,不往 EXE 目录写任何文件 + pac_port = _start_pac_server(data) + pac_url = f"http://127.0.0.1:{pac_port}/{pac_name}" + log(f"使用 PAC: {pac_url}") + proxy_on(pac_url=pac_url) + else: + proxy_on() + self._proxy_set_by_us = True # 标记系统代理由本程序设置,退出时据此清理 + log("验证代理连通性...") + import urllib.request + if use_pac: + # PAC 模式下只验证代理服务器本身可达;具体域名路由交给 PAC 判断 + test_urls = [("google.com", "http://www.google.com")] + else: + test_urls = [("baidu.com", "http://www.baidu.com"), ("google.com", "http://www.google.com")] + for name, url in test_urls: + try: + req = urllib.request.Request(url) + req.set_proxy(f"{PROXY_HOST}:{PROXY_PORT}", "http") + urllib.request.urlopen(req, timeout=10) + log(f" {name} 可达") + except Exception as e: + log(f" {name} 不可达: {e}") + log("开启成功") + if use_pac: + log_red("注意:PAC 模式旨在开启代理时使微信等国内常用软件可以正常连接服务器, " + "但 PAC 对国外网站优化较差,开启时可能出现访问速度慢, 此时建议关闭 PAC.") + self._op_done.emit("start", True) + except Exception as e: + log(f"[错误] 开启失败: {e}") + self._op_done.emit("start", False) + + def on_stop(self): + """禁用按钮并在后台线程执行关闭流程。""" + self.btn_toggle.setEnabled(False) + threading.Thread(target=self._stop_thread, daemon=True).start() + + def _stop_thread(self): + """后台关闭代理:清理系统代理、停止 TLS/PAC 服务、断开 WG。""" + try: + log("正在关闭代理...") + proxy_off() + self._proxy_set_by_us = False + if self._using_wg: + log("正在断开 WireGuard...") + wg_off() + log("已关闭") + self._op_done.emit("stop", True) + except Exception as e: + log(f"[错误] 关闭失败: {e}") + self._op_done.emit("stop", False) + + def _on_mode_change(self, btn): + """切换直连 / WG 隧道时更新全局代理地址。 + + 两种模式最终都通过本地 127.0.0.1:1080 认证转发器访问 nginx 正向代理, + 由转发器根据模式选择 TLS 直连或 WG 网关作为上游。 + """ + global PROXY_HOST, PROXY_PORT + PROXY_HOST = "127.0.0.1" + PROXY_PORT = _TLS_LOCAL_PORT + log(f"连接方式 -> {btn.text()}") + + def _after_op(self, op, wg_ok): + """开启/关闭操作完成后刷新界面状态并恢复按钮/控件可用性。""" + self.refresh_status() + self.btn_toggle.setEnabled(True) + # 恢复模式/PAC 控件的时机:关闭完成后、或开启失败时。 + # 不能靠按钮文字判断——refresh_status 是异步的,此刻按钮样式还没更新 + is_off = (op == "stop") or (op == "start" and not wg_ok) + self.rb_direct.setEnabled(is_off) + self.rb_wg.setEnabled(is_off) + self.cb_pac.setEnabled(is_off) + if op == "start" and not wg_ok: + QMessageBox.warning(self, "提示", "代理已设置,但 WireGuard 隧道未能连通,请检查配置。") + + # ── 日志 ── + def _append_log(self, msg: str): + """追加日志并自动滚动,最多保留 200 行。""" + self.log_text.append(msg) + scrollbar = self.log_text.verticalScrollBar() + scrollbar.setValue(scrollbar.maximum()) + if self.log_text.document().blockCount() > 200: + cursor = self.log_text.textCursor() + cursor.movePosition(cursor.Start) + cursor.select(cursor.BlockUnderCursor) + cursor.removeSelectedText() + cursor.deleteChar() + + # ── 状态刷新 ── + def refresh_status(self): + """触发一次后台状态轮询(不在 GUI 线程起子进程,避免周期性卡顿)。""" + if self._status_busy: + return + self._status_busy = True + # GUI 线程读取模式选择,传给后台线程;直连模式下不检测 WG,避免无谓的 wg 子进程 + wg_interested = self._using_wg or self.rb_wg.isChecked() + threading.Thread(target=self._poll_status, args=(wg_interested,), daemon=True).start() + + def _poll_status(self, wg_interested): + """后台线程:查询 WG 握手与系统代理状态,结果发回 GUI 线程。""" + try: + wg = _wg_active() if wg_interested else None + px = is_proxy_on() + except Exception: + wg, px = (False if wg_interested else None), False + self._status_ready.emit((wg, px)) + + def _apply_status(self, state): + """GUI 线程:根据轮询结果刷新状态指示灯与开关按钮。""" + self._status_busy = False + wg_on_, px_on_ = state + + if wg_on_ is None: + self.wg_dot.set_disabled() + self.wg_status.setText("未启用") + self.wg_status.setStyleSheet(f"color: {C_SUBTEXT}; background: transparent;") + elif wg_on_: + self.wg_dot.set_on() + self.wg_status.setText("已连接") + self.wg_status.setStyleSheet(f"color: {C_GREEN}; background: transparent;") + else: + self.wg_dot.set_off() + self.wg_status.setText("未连接") + self.wg_status.setStyleSheet(f"color: {C_RED}; background: transparent;") + + if px_on_: + self.px_dot.set_on() + up, down = _traffic_snapshot() + # ↓ / ↑ 小字两行,压缩行高,整体只占一行的高度 + self.px_status.setText( + f'' + f'' + f'
    已开启 | ' + f'↓{_fmt_bytes(down)}' + f'
    ↑{_fmt_bytes(up)}
    ' + f'
    ') + self.px_status.setStyleSheet(f"color: {C_GREEN}; background: transparent;") + self._set_toggle_button_style(is_start=False) + else: + self.px_dot.set_off() + self.px_status.setText("已关闭") + self.px_status.setStyleSheet(f"color: {C_RED}; background: transparent;") + self._set_toggle_button_style(is_start=True) + + def _check_update(self): + """后台检查服务器是否有新版本。""" + try: + import json, urllib.request, base64 + domain = _endpoint_domain() + if domain == "???": + log("更新检查: 无法获取服务器域名") + self._update_done.emit() + return + log("正在检查更新...") + url = f"https://{domain}/latest_version.json" + req = urllib.request.Request(url) + auth = base64.b64encode(f"{UPDATE_USER}:{UPDATE_PASSWORD}".encode()).decode() + req.add_header("Authorization", f"Basic {auth}") + data = urllib.request.urlopen(req, context=_SSL_NO_VERIFY, timeout=10).read().decode("utf-8-sig") + info = json.loads(data) + log("客户端认证成功") + self._latest_version = info.get("latest_version", "") + self._download_url = info.get("download_url", "") + log(f"当前版本: {VERSION},最新版本: {self._latest_version}") + except Exception as e: + log(f"更新检查失败: {e}") + self._latest_version = "" + self._download_url = "" + finally: + self._update_done.emit() + + def _on_update_done(self): + """更新检查完成后恢复按钮;发现新版本时弹窗询问是否下载。""" + self.btn_toggle.setEnabled(True) + if self._latest_version and self._latest_version > VERSION: + reply = QMessageBox.question( + self, "发现新版本", + f"当前版本: {VERSION}\n最新版本: {self._latest_version}\n\n是否下载更新?", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.Yes, + ) + if reply == QMessageBox.Yes: + threading.Thread(target=self._download_update, daemon=True).start() + + def _download_update(self): + """后台下载新版本 EXE 到 EXE 所在目录。""" + try: + import urllib.request, urllib.parse, base64 + url = self._download_url + if not url: + self._update_download_done.emit(False, "下载链接为空") + return + + # 对 URL 进行安全编码,兼容空格或已编码空格 + url = urllib.parse.quote(url, safe=':/?#[]@!$&\'()*+,;=%') + save_path = PERSIST_DIR / f"Royirin Rosmontis Private Proxy {self._latest_version}.exe" + log(f"正在下载新版本: {url}") + log(f"保存到: {save_path}") + + req = urllib.request.Request(url) + auth = base64.b64encode(f"{UPDATE_USER}:{UPDATE_PASSWORD}".encode()).decode() + req.add_header("Authorization", f"Basic {auth}") + + with urllib.request.urlopen(req, context=_SSL_NO_VERIFY, timeout=120) as resp: + data = resp.read() + + if len(data) < 1024: + self._update_download_done.emit(False, "下载文件过小,可能不是有效的 EXE") + return + + save_path.write_bytes(data) + log(f"新版本已下载: {save_path}") + self._update_download_done.emit(True, str(save_path)) + except Exception as e: + log(f"下载更新失败: {e}") + self._update_download_done.emit(False, str(e)) + + def _on_update_download_done(self, success, message): + """下载完成后提示用户手动替换 EXE。""" + if success: + QMessageBox.information( + self, "下载完成", + f"新版本已下载到:\n{message}\n\n请关闭本程序后,用该文件替换当前运行的程序,然后重新启动。" + ) + else: + QMessageBox.warning(self, "下载失败", f"无法下载新版本:\n{message}") + + def eventFilter(self, obj, event): + """鼠标悬停到 PAC 复选框时异步加载规则摘要。""" + if obj is self.cb_pac and event.type() == QEvent.Enter: + if not self._pac_tooltip_loaded and not self._pac_tooltip_loading: + self._pac_tooltip_loading = True + # GUI 线程读取模式选择传参,避免子线程直接访问 Qt 控件 + use_wg = self.rb_wg.isChecked() + threading.Thread(target=self._load_pac_tooltip, args=(use_wg,), daemon=True).start() + return super().eventFilter(obj, event) + + def _load_pac_tooltip(self, use_wg): + """从服务器拉取 PAC 并解析出规则分类摘要;拉取失败则使用内置 PAC。""" + try: + import re, urllib.request + domain = _endpoint_domain() + if domain == "???": + self._pac_tooltip_ready.emit("PAC 规则模式\n\n无法获取服务器域名") + return + pac_name = "proxy_wg.pac" if use_wg else "proxy.pac" + url = f"https://{domain}/{pac_name}" + try: + req = urllib.request.Request(url) + req.add_header("Authorization", f"Basic {_PROXY_AUTH_BASIC}") + data = urllib.request.urlopen(req, context=_SSL_NO_VERIFY, timeout=10).read().decode("utf-8-sig") + except Exception as e: + # 服务器不可达时回退到内置规则,确保提示始终可用 + proxy_spec = f"{PROXY_HOST}:{PROXY_PORT}" + data = _build_pac(proxy_spec) + + # 按 "// 分类名" + "if (...)" 的格式解析 PAC,生成摘要 + blocks = re.findall(r'\n\s*//\s*([^\n]+?)\s*\n\s*if\s*\(([^/]*?)\)\s*\{', data, re.DOTALL) + + lines = ["PAC 规则模式", ""] + + total = 0 + for comment, conditions in blocks: + domains = re.findall(r'shExpMatch\(host,\s*"([^"]+)"\)', conditions) + total += len(domains) + if domains: + lines.append(f"• {comment}({len(domains)} 条)") + + lines[1] = f"共 {total} 条域名规则" + + tooltip = "\n".join(lines) + if len(tooltip) > 2000: + tooltip = tooltip[:2000] + "\n...(已截断)" + self._pac_tooltip_ready.emit(tooltip) + except Exception as e: + self._pac_tooltip_ready.emit(f"PAC 规则模式\n\n加载 PAC 失败: {e}") + finally: + self._pac_tooltip_loading = False + + def _set_pac_tooltip(self, text): + """设置并显示 PAC 规则摘要提示。""" + self.cb_pac.setToolTip(text) + self._pac_tooltip_loaded = True + if self.cb_pac.underMouse(): + QToolTip.showText( + self.cb_pac.mapToGlobal(self.cb_pac.rect().center()), + text, + self.cb_pac, + ) + + def quit_app(self): + """退出前清理本程序开启的代理与 WireGuard。 + + 只清理自己设置的系统代理:用户或其他软件设置的代理不受影响。 + 本程序异常退出残留的代理设置由下次启动时 _cleanup_stale_proxy() 处理。 + """ + if self._proxy_set_by_us: + proxy_off() + if self._using_wg: + wg_off() + QApplication.quit() + +# ── 程序入口 ────────────────────────────────────────── + +def _set_per_monitor_dpi_aware(): + """在创建 QApplication 前尽量设置为每显示器 DPI 感知, + + 使程序在 2K/4K 高分屏以及多显示器不同缩放比例之间移动时, + 由系统通知 WM_DPICHANGED 而不是被位图拉伸。 + """ + try: + # Windows 10 1607+:Per Monitor V2(最优) + ctypes.windll.user32.SetThreadDpiAwarenessContext(ctypes.c_ssize_t(-4)) + return + except Exception: + pass + try: + # Windows 8.1+:Per Monitor + ctypes.windll.shcore.SetProcessDpiAwareness(2) + return + except Exception: + pass + try: + # 最低兜底:System DPI Aware + ctypes.windll.user32.SetProcessDPIAware() + except Exception: + pass + + +_SINGLE_INSTANCE_MUTEX = None + +def _acquire_single_instance(): + """通过命名互斥体保证单实例运行;已有实例时返回 False。""" + global _SINGLE_INSTANCE_MUTEX + try: + kernel32 = ctypes.windll.kernel32 + _SINGLE_INSTANCE_MUTEX = kernel32.CreateMutexW(None, True, r"Local\RRPP_SingleInstance") + return kernel32.GetLastError() != 183 # ERROR_ALREADY_EXISTS + except Exception: + return True # 互斥体创建失败时放行,避免把用户锁在门外 + +def main(): + """主入口:检查管理员权限、依赖文件,然后启动 GUI。""" + _set_per_monitor_dpi_aware() + + if not is_admin(): + elevate() + sys.exit(0) + + # 单实例:第二个实例直接退出(且不能执行下面的残留代理清理, + # 否则会把第一个实例正在使用的系统代理清掉) + if not _acquire_single_instance(): + app = QApplication(sys.argv) + QMessageBox.information(None, "提示", "程序已在运行中。") + sys.exit(0) + + # 上次异常退出可能残留指向 127.0.0.1:1080 的系统代理(转发器已随进程消失), + # 不清理会导致全网不通,启动时先清掉 + _cleanup_stale_proxy() + + # 任务栏图标:显式设置 AppUserModelID, + # 避免 Windows 依赖 exe 图标缓存推断(冷缓存下任务栏会显示空白/默认图标) + try: + ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( + "RRPP.RoyirinRosmontisPrivateProxy") + except Exception: + pass + + missing = [] + if not WG_EXE.exists(): + missing.append(str(WG_EXE)) + if not WG_CLI.exists(): + missing.append(str(WG_CLI)) + if not WG_CONF.exists(): + missing.append(str(WG_CONF)) + if missing: + app = QApplication(sys.argv) + QMessageBox.critical(None, "缺少必需文件", + "以下文件缺失:\n " + "\n ".join(missing) + + "\n\n请确保 wg/ 目录和 jp_client.conf 与脚本同目录。") + sys.exit(1) + + # Qt5 默认把缩放因子四舍五入到整数倍:2K 屏常见的 150% 会被取整为 2x, + # 界面直接翻倍过大。改为 PassThrough,按实际比例(1.5x)缩放。 + os.environ.setdefault("QT_SCALE_FACTOR_ROUNDING_POLICY", "PassThrough") + try: + QApplication.setHighDpiScaleFactorRoundingPolicy( + Qt.HighDpiScaleFactorRoundingPolicy.PassThrough) + except Exception: + pass + + QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) + QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True) + app = QApplication(sys.argv) + icon = load_icon() + app.setWindowIcon(icon) + app.setQuitOnLastWindowClosed(True) + + window = MainWindow() + window.show() + # 开机自启等场景下任务栏/Explorer 可能尚未就绪, + # 延迟重设一次图标兜底,避免首次启动任务栏图标丢失 + QTimer.singleShot(2000, lambda: window.setWindowIcon(icon)) + + sys.exit(app.exec_()) + +if __name__ == "__main__": + main() \ No newline at end of file