Files
deploy.stack/shell/proxy.ps1
T

354 lines
14 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.SYNOPSIS
通用代理管理脚本 (PowerShell 版)
.DESCRIPTION
source/加载后使用 proxy 命令管理代理开/关/状态/测试
.NOTES
File: proxy.ps1
用法:
. .\proxy.ps1 # 加载脚本
proxy on # 开启代理
proxy off # 关闭代理
proxy status # 查看代理状态
proxy test # 测试代理连通性
proxy set <host> <port> [type] # 临时设置代理地址
proxy toggle # 切换开/关
proxy help # 显示帮助
#>
# -------------------- 默认配置 --------------------
if (-not $env:_PROXY_HOST) { $env:_PROXY_HOST = "127.0.0.1" }
if (-not $env:_PROXY_PORT) { $env:_PROXY_PORT = "7890" }
if (-not $env:_PROXY_TYPE) { $env:_PROXY_TYPE = "http" } # http | socks5 | socks4
$global:NO_PROXY_LIST = "localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
# -------------------- 辅助:构建代理 URL --------------------
function _BuildProxyUrl {
$type = $env:_PROXY_TYPE
$host_addr = $env:_PROXY_HOST
$port = $env:_PROXY_PORT
switch ($type.ToLower()) {
"http" { return "http://$host_addr`:$port" }
"socks5" { return "socks5://$host_addr`:$port" }
"socks4" { return "socks4://$host_addr`:$port" }
default { return "$type`://$host_addr`:$port" }
}
}
# -------------------- 辅助:控制台 WinINET 代理 (系统级 IE/Edge) --------------------
function _SetWinInetProxy([string]$proxyUrl) {
$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
if ($proxyUrl) {
Set-ItemProperty -Path $regPath -Name ProxyEnable -Value 1
Set-ItemProperty -Path $regPath -Name ProxyServer -Value ($proxyUrl -replace '^\w+://', '')
Set-ItemProperty -Path $regPath -Name ProxyOverride -Value $global:NO_PROXY_LIST
} else {
Set-ItemProperty -Path $regPath -Name ProxyEnable -Value 0
}
# 广播 WM_SETTINGCHANGE,让其他程序感知代理变更
$sig = @'
[DllImport("wininet.dll", SetLastError=true)]
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
'@
try {
Add-Type -MemberDefinition $sig -Namespace WinAPI -Name ProxyHelper -ErrorAction SilentlyContinue
[WinAPI.ProxyHelper]::InternetSetOption([IntPtr]::Zero, 39, [IntPtr]::Zero, 0) | Out-Null # PROXY_SETTINGS_CHANGED
$HWND_BROADCAST = [IntPtr]0xffff
$WM_SETTINGCHANGE = 0x1A
$result = [UIntPtr]::Zero
[WinAPI.ProxyHelper]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [UIntPtr]::Zero, "Environment", 2, 2000, [ref]$result) | Out-Null
} catch {}
}
# ====================================================================
# 开启代理
# ====================================================================
function Proxy-On {
$url = _BuildProxyUrl
# --- 进程级环境变量 ---
$env:http_proxy = $url
$env:HTTP_PROXY = $url
$env:https_proxy = $url
$env:HTTPS_PROXY = $url
$env:all_proxy = $url
$env:ALL_PROXY = $url
$env:no_proxy = $global:NO_PROXY_LIST
$env:NO_PROXY = $global:NO_PROXY_LIST
$env:ftp_proxy = $url
$env:FTP_PROXY = $url
$env:rsync_proxy = $url
# --- 用户级环境变量(持久化,新开终端也生效)---
[Environment]::SetEnvironmentVariable("http_proxy", $url, "User")
[Environment]::SetEnvironmentVariable("https_proxy", $url, "User")
[Environment]::SetEnvironmentVariable("all_proxy", $url, "User")
[Environment]::SetEnvironmentVariable("no_proxy", $global:NO_PROXY_LIST, "User")
# --- Git ---
git config --global http.proxy $url 2>$null
git config --global https.proxy $url 2>$null
# --- NPM ---
npm config set proxy $url 2>$null
npm config set https-proxy $url 2>$null
# --- Yarn ---
yarn config set proxy $url 2>$null
yarn config set https-proxy $url 2>$null
# --- Windows 系统 WinINET (IE/Edge/Chrome 等) ---
_SetWinInetProxy $url
Write-Host "[✓] 代理已开启 → " -ForegroundColor Green -NoNewline
Write-Host $url -ForegroundColor White
Write-Host " NO_PROXY → " -ForegroundColor Green -NoNewline
Write-Host $global:NO_PROXY_LIST -ForegroundColor White
}
# ====================================================================
# 关闭代理
# ====================================================================
function Proxy-Off {
# --- 进程级环境变量 ---
$vars = @("http_proxy","HTTP_PROXY","https_proxy","HTTPS_PROXY","all_proxy","ALL_PROXY",
"no_proxy","NO_PROXY","ftp_proxy","FTP_PROXY","rsync_proxy")
foreach ($v in $vars) { Remove-Item -Path "Env:$v" -ErrorAction SilentlyContinue }
# --- 用户级环境变量 ---
foreach ($v in @("http_proxy","https_proxy","all_proxy","no_proxy")) {
[Environment]::SetEnvironmentVariable($v, $null, "User")
}
# --- Git ---
git config --global --unset http.proxy 2>$null
git config --global --unset https.proxy 2>$null
# --- NPM ---
npm config delete proxy 2>$null
npm config delete https-proxy 2>$null
# --- Yarn ---
yarn config delete proxy 2>$null
yarn config delete https-proxy 2>$null
# --- Windows 系统 WinINET ---
_SetWinInetProxy $null
Write-Host "[✓] 代理已关闭" -ForegroundColor Red
}
# ====================================================================
# 查看代理状态
# ====================================================================
function Proxy-Status {
Write-Host ""
Write-Host "========== 代理状态 ==========" -ForegroundColor White
# 环境变量
Write-Host "`n[环境变量]" -ForegroundColor White
$envVars = @("http_proxy", "https_proxy", "all_proxy", "no_proxy", "ftp_proxy")
foreach ($v in $envVars) {
$val = [Environment]::GetEnvironmentVariable($v, "Process")
if ($val) {
Write-Host (" {0,-14} → {1}" -f $v, $val) -ForegroundColor Green
} else {
Write-Host (" {0,-14} → (未设置)" -f $v) -ForegroundColor DarkGray
}
}
# 用户级环境变量
Write-Host "`n[用户级环境变量 (持久化)]" -ForegroundColor White
foreach ($v in @("http_proxy", "https_proxy", "all_proxy", "no_proxy")) {
$val = [Environment]::GetEnvironmentVariable($v, "User")
if ($val) {
Write-Host (" {0,-14} → {1}" -f $v, $val) -ForegroundColor Green
} else {
Write-Host (" {0,-14} → (未设置)" -f $v) -ForegroundColor DarkGray
}
}
# Git
Write-Host "`n[Git 配置] (global)" -ForegroundColor White
$gitHttp = git config --global --get http.proxy 2>$null
$gitHttps = git config --global --get https.proxy 2>$null
if ($gitHttp -or $gitHttps) {
if ($gitHttp) { Write-Host " http.proxy → $gitHttp" -ForegroundColor Green }
if ($gitHttps) { Write-Host " https.proxy → $gitHttps" -ForegroundColor Green }
} else {
Write-Host " (未配置)" -ForegroundColor DarkGray
}
# NPM
if (Get-Command npm -ErrorAction SilentlyContinue) {
Write-Host "`n[NPM 配置]" -ForegroundColor White
$npmProxy = npm config get proxy 2>$null
$npmHttps = npm config get https-proxy 2>$null
if ($npmProxy -and $npmProxy -ne "null" -and $npmProxy -ne "undefined") {
Write-Host " proxy → $npmProxy" -ForegroundColor Green
} else {
Write-Host " proxy → (未设置)" -ForegroundColor DarkGray
}
if ($npmHttps -and $npmHttps -ne "null" -and $npmHttps -ne "undefined") {
Write-Host " https-proxy → $npmHttps" -ForegroundColor Green
} else {
Write-Host " https-proxy → (未设置)" -ForegroundColor DarkGray
}
}
# Windows 系统代理
Write-Host "`n[Windows 系统 WinINET 代理]" -ForegroundColor White
$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
if (Test-Path $regPath) {
$enabled = (Get-ItemProperty -Path $regPath -Name ProxyEnable -ErrorAction SilentlyContinue).ProxyEnable
$server = (Get-ItemProperty -Path $regPath -Name ProxyServer -ErrorAction SilentlyContinue).ProxyServer
if ($enabled -eq 1) {
Write-Host " ProxyEnable → 1" -ForegroundColor Green
Write-Host " ProxyServer → $server" -ForegroundColor Green
} else {
Write-Host " ProxyEnable → 0 (已禁用)" -ForegroundColor DarkGray
}
} else {
Write-Host " (无法读取注册表)" -ForegroundColor DarkGray
}
Write-Host ""
}
# ====================================================================
# 测试代理连通性
# ====================================================================
function Proxy-Test {
$url = _BuildProxyUrl
Write-Host "[测试代理] $url`n" -ForegroundColor White
# Google (通过代理)
Write-Host " Google (proxy) → " -NoNewline
try {
$r = Invoke-WebRequest -Uri "https://www.google.com" -Proxy $url -TimeoutSec 5 -UseBasicParsing -ErrorAction Stop
if ($r.StatusCode -in 200,301,302) { Write-Host "✓ OK ($($r.StatusCode))" -ForegroundColor Green }
else { Write-Host "✗ FAIL ($($r.StatusCode))" -ForegroundColor Red }
} catch { Write-Host "✗ FAIL" -ForegroundColor Red }
# GitHub (通过代理)
Write-Host " GitHub (proxy) → " -NoNewline
try {
$r = Invoke-WebRequest -Uri "https://github.com" -Proxy $url -TimeoutSec 5 -UseBasicParsing -ErrorAction Stop
if ($r.StatusCode -in 200,301,302) { Write-Host "✓ OK ($($r.StatusCode))" -ForegroundColor Green }
else { Write-Host "✗ FAIL ($($r.StatusCode))" -ForegroundColor Red }
} catch { Write-Host "✗ FAIL" -ForegroundColor Red }
# 本地直连 (不走代理)
Write-Host " Baidu (direct) → " -NoNewline
try {
$r = Invoke-WebRequest -Uri "https://www.baidu.com" -TimeoutSec 3 -UseBasicParsing -NoProxy -ErrorAction Stop
if ($r.StatusCode -in 200,301,302) { Write-Host "✓ OK ($($r.StatusCode))" -ForegroundColor Green }
else { Write-Host "✗ FAIL ($($r.StatusCode))" -ForegroundColor Red }
} catch {
# PowerShell 5.1 不支持 -NoProxy,退而用 curl
try {
$code = (curl.exe -s -o NUL -w "%{http_code}" --max-time 3 --noproxy "*" https://www.baidu.com 2>$null)
if ($code -match "200|301|302") { Write-Host "✓ OK ($code)" -ForegroundColor Green }
else { Write-Host "✗ FAIL" -ForegroundColor Red }
} catch { Write-Host "✗ FAIL" -ForegroundColor Red }
}
Write-Host ""
}
# ====================================================================
# 临时设置代理地址
# ====================================================================
function Proxy-Set {
param(
[Parameter(Position=0)][string]$ProxyHost,
[Parameter(Position=1)][string]$ProxyPort,
[Parameter(Position=2)][string]$ProxyType = "http"
)
if (-not $ProxyHost -or -not $ProxyPort) {
Write-Host "用法: proxy set <host> <port> [http|socks5]" -ForegroundColor Yellow
Write-Host '示例: proxy set 192.168.1.100 1080 socks5' -ForegroundColor Yellow
return
}
$env:_PROXY_HOST = $ProxyHost
$env:_PROXY_PORT = $ProxyPort
$env:_PROXY_TYPE = $ProxyType
Write-Host "[✓] 代理地址已设置为 ${ProxyType}://${ProxyHost}:${ProxyPort}" -ForegroundColor Green
Write-Host " 执行 'proxy on' 启用新的代理地址" -ForegroundColor Green
}
# ====================================================================
# 主入口:proxy 命令
# ====================================================================
function proxy {
param(
[Parameter(Position=0)][string]$Action = "help",
[Parameter(Position=1, ValueFromRemainingArguments)][string[]]$Args
)
switch ($Action.ToLower()) {
"on" { Proxy-On }
"off" { Proxy-Off }
"status" { Proxy-Status }
"test" { Proxy-Test }
"toggle" {
if ($env:http_proxy) { Proxy-Off } else { Proxy-On }
}
"set" {
if ($Args -and $Args.Count -ge 2) {
$type = if ($Args.Count -ge 3) { $Args[2] } else { "http" }
Proxy-Set -ProxyHost $Args[0] -ProxyPort $Args[1] -ProxyType $type
} else {
Proxy-Set
}
}
"help" {
Write-Host @"
========== proxy.ps1 ==========
:
. .\proxy.ps1 # Dot-Source
proxy on # ( + WinINET + git + npm)
proxy off #
proxy status #
proxy test #
proxy toggle # /
proxy set <host> <port> [type]#
proxy help #
():
_PROXY_HOST = $($env:_PROXY_HOST)
_PROXY_PORT = $($env:_PROXY_PORT)
_PROXY_TYPE = $($env:_PROXY_TYPE) (http | socks5 | socks4)
:
`$env:_PROXY_HOST = "10.0.0.5" #
`$env:_PROXY_PORT = "1080" #
proxy on #
"@ -ForegroundColor Cyan
}
default {
Write-Host "未知命令: $Action (使用 'proxy help' 查看帮助)" -ForegroundColor Red
}
}
}
# -------------------- 加载提示 --------------------
if ($MyInvocation.Line -notmatch '\$\s*\(?\s*\.\s+.*proxy\.ps1') {
# 被直接执行而非 dot-source 时
if ($args.Count -eq 0) {
# 无参数直接执行,先 dot-source 自己
Write-Host "[proxy.ps1] 请使用 '. .\proxy.ps1' 来加载脚本。" -ForegroundColor Yellow
Write-Host "[proxy.ps1] 如果要直接执行命令, 请运行: .\proxy.ps1 on" -ForegroundColor Yellow
}
} else {
Write-Host "[proxy.ps1] 已加载。使用 'proxy help' 查看用法。" -ForegroundColor Cyan
}