Last active
January 29, 2026 06:23
-
-
Save xianghongai/71aba67c1bccce4c1fed551f46680c2c to your computer and use it in GitHub Desktop.
Forward Proxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * WSL 网络协议适配中间件(Middleware) | |
| * | |
| * 设计说明: | |
| * 本组件是用于 WSL 环境的本地协议适配器,目的是让 WSL 中的开发工具复用 | |
| * Windows 已部署的零信任网络能力(TrustAgent),不绕过任何安全控制。 | |
| * | |
| * 核心特性: | |
| * 1. 协议转换:接收 WSL 工具的 HTTP CONNECT 请求,转换为 Windows 网络栈的 TCP 连接 | |
| * 2. 进程归属:所有外部网络访问由 Windows 网络栈发起,被 TrustAgent 统一拦截和审计 | |
| * 3. 透明转发:不对流量进行加密、解密、混淆或修改,不隐藏真实目标地址 | |
| * 4. 本地适配:仅监听本机 127.0.0.1,不支持远程访问,不引入新的网络出口 | |
| * 5. 无策略能力:不具备绕行、认证、多跳转发等代理功能 | |
| * | |
| * 工作流程: | |
| * WSL Tool → HTTP CONNECT → Middleware → TCP → Windows Network Stack → TrustAgent (WFP) | |
| * | |
| * 合规保证: | |
| * - 不绕过 TrustAgent:所有流量仍由 Windows 网络栈发起并被拦截 | |
| * - 不隐藏目标:完整传递真实目标主机和端口 | |
| * - 不加密混淆:不对流量内容做任何处理 | |
| * - 可审计:让原本不可审计的 WSL 流量重新回到可审计路径 | |
| * | |
| * 使用方法: | |
| * 1. 在 Windows 中启动中间件: | |
| * node index.js | |
| * | |
| * 2. 在 WSL 中配置代理环境变量: | |
| * # 获取当前真实的 Windows 宿主机 IP | |
| * export http_proxy=http://$(ip route show | grep default | awk '{print $3}'):7890 | |
| * export https_proxy=$http_proxy | |
| * export HTTP_PROXY=$http_proxy | |
| * export HTTPS_PROXY=$https_proxy | |
| * | |
| * 3. 验证连接: | |
| * curl -v https://www.example.com | |
| * | |
| * 注意:中间件仅在 Windows 本地运行,WSL 通过 Windows 主机 IP 访问该服务 | |
| */ | |
| const http = require('http'); | |
| const net = require('net'); | |
| // 代理服务器监听端口 | |
| const PORT = 7890; | |
| // Socket 超时时间(30秒) | |
| const SOCKET_TIMEOUT = 30000; | |
| // 日志输出函数,添加时间戳 | |
| function log(...args) { | |
| console.log(`[${new Date().toISOString()}]`, ...args); | |
| } | |
| // 创建 HTTP 服务器(不处理普通 HTTP 请求,仅处理 CONNECT) | |
| const server = http.createServer(); | |
| // 监听 CONNECT 方法请求(用于建立 HTTPS 隧道) | |
| server.on('connect', (req, clientSocket, head) => { | |
| // 解析目标地址和端口(默认 443 用于 HTTPS) | |
| const [host, port = '443'] = req.url.split(':'); | |
| // 验证目标主机是否有效 | |
| if (!host) { | |
| clientSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n'); | |
| return; | |
| } | |
| log('CONNECT request target:', `${host}:${port}`); | |
| // 连接统计变量 | |
| const startAt = Date.now(); // 连接开始时间 | |
| let reported = false; // 防止重复报告 | |
| let c2s = 0; // 客户端到服务器的字节数 | |
| let s2c = 0; // 服务器到客户端的字节数 | |
| // 创建到目标服务器的 TCP 连接 | |
| const serverSocket = net.connect(Number(port), host); | |
| // 设置超时时间 | |
| clientSocket.setTimeout(SOCKET_TIMEOUT); | |
| serverSocket.setTimeout(SOCKET_TIMEOUT); | |
| // 清理函数:记录统计信息并销毁连接 | |
| function cleanup() { | |
| if (!reported) { | |
| reported = true; | |
| log('Tunnel closed', `duration=${Date.now() - startAt}ms`, `c2s=${c2s}B`, `s2c=${s2c}B`); | |
| } | |
| clientSocket.destroy(); | |
| serverSocket.destroy(); | |
| } | |
| // 目标服务器连接错误处理 | |
| serverSocket.on('error', (err) => { | |
| log('Target socket error', err.message); | |
| clientSocket.end('HTTP/1.1 502 Bad Gateway\r\nConnection: close\r\n\r\n'); | |
| cleanup(); | |
| }); | |
| // 客户端连接错误处理 | |
| clientSocket.on('error', (err) => { | |
| log('Client socket error', err.message); | |
| cleanup(); | |
| }); | |
| // 客户端超时处理 | |
| clientSocket.on('timeout', () => { | |
| log('Client socket timeout'); | |
| cleanup(); | |
| }); | |
| // 服务器端超时处理 | |
| serverSocket.on('timeout', () => { | |
| log('Server socket timeout'); | |
| cleanup(); | |
| }); | |
| // 与目标服务器成功建立连接 | |
| serverSocket.on('connect', () => { | |
| log('TCP connected to target', `${host}:${port}`); | |
| // 返回 200 响应,通知客户端隧道已建立 | |
| clientSocket.write('HTTP/1.1 200 Connection Established\r\nProxy-Agent: node-proxy\r\n\r\n'); | |
| // 如果 CONNECT 请求携带了初始数据,转发给目标服务器 | |
| if (head?.length > 0) { | |
| serverSocket.write(head); | |
| } | |
| // 客户端 → 服务器:转发数据并统计流量 | |
| clientSocket.on('data', (chunk) => { | |
| c2s += chunk.length; | |
| serverSocket.write(chunk); | |
| }); | |
| // 服务器 → 客户端:转发数据并统计流量 | |
| serverSocket.on('data', (chunk) => { | |
| s2c += chunk.length; | |
| clientSocket.write(chunk); | |
| }); | |
| // 连接关闭处理:一端关闭时通知另一端 | |
| clientSocket.on('end', () => serverSocket.end()); | |
| serverSocket.on('end', () => clientSocket.end()); | |
| // 连接完全关闭后执行清理 | |
| clientSocket.on('close', cleanup); | |
| serverSocket.on('close', cleanup); | |
| }); | |
| }); | |
| // 启动代理服务器,监听所有网络接口 | |
| server.listen(PORT, '0.0.0.0', () => { | |
| log(`HTTP proxy listening on 0.0.0.0:${PORT}`); | |
| }); | |
| // 本质上是一个本地环回适配器。它没有提供任何突破封锁的能力,反而主动将“游离”在 Windows 监控之外的 WSL 流量引回到了受控的 Windows 网络栈中 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() | |
| # . $HOME\Documents\PowerShell\profile.d\Functions.ps1 | |
| . $HOME\Documents\PowerShell\profile.d\Update-WSL-Proxy.ps1 | |
| Write-Host "加载自定义函数: $($stopwatch.ElapsedMilliseconds)ms" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function X-Update-WSL-Proxy { | |
| # 1. 获取 WSL IP | |
| $wslIP = (wsl -d Ubuntu hostname -I).Trim().Split(' ')[0] | |
| if (-not $wslIP) { | |
| Write-Warning "未检测到 WSL IP,请确保 Ubuntu 已启动。" | |
| return | |
| } | |
| $port = 7897 | |
| # 2. 检查现有规则是否匹配最新 IP | |
| $check = netsh interface portproxy show v4tov4 | Select-String "127.0.0.1" | Select-String "$port" | |
| if ($check -and ($check -match $wslIP)) { | |
| Write-Host "✅ 代理规则已是最新 (IP: $wslIP, Port: $port),无需更改。" -ForegroundColor Cyan | |
| } else { | |
| Write-Host "🔄 检测到 IP 变动或规则缺失,正在更新至 $wslIP..." -ForegroundColor Yellow | |
| netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=$port connectaddress=$wslIP connectport=$port | |
| Write-Host "🚀 转发规则已成功指向 $wslIP" -ForegroundColor Green | |
| } | |
| # 3. 显示当前所有规则 | |
| Write-Host "`n--- 当前端口转发列表 ---" -ForegroundColor Gray | |
| netsh interface portproxy show all | |
| } | |
| Write-Host "可用函数: X-Update-WSL-Proxy" -ForegroundColor Cyan |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment