forked from DevOps/deploy.stack
354 lines
14 KiB
PowerShell
354 lines
14 KiB
PowerShell
|
|
<#
|
|||
|
|
.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
|
|||
|
|
}
|