使用PowerShell以编程方式将Internet Explorer代理设置配置为在打开之前工作

Dic*_*ore 9 powershell proxy internet-explorer automation amazon-web-services

许多PowerShell cmdlet(例如AWS cmdlet)引用Internet Explorer代理设置以查找要使用的代理和绕过列表.

我正在尝试配置代理服务器并绕过列表,以用作在新AWS实例上执行的userdata脚本的一部分.

我已经尝试了多种方法来实现这一功能,但似乎无法使其正常工作.

首先让我们为代理服务器和绕过列表设置变量,并注意这些地址是不同的,具体取决于实例所在的VPC:

$proxy = "security-elb-1111111111.us-east-2.elb.amazonaws.com:3128"
$bypassList = "169.254.169.254;octopus-769734587.us-east-2.elb.amazonaws.com;s3.dualstack.us-east-1.amazonaws.com"
Run Code Online (Sandbox Code Playgroud)

其次,netsh:

netsh winhttp set proxy $proxy bypass-list=$bypassList
Run Code Online (Sandbox Code Playgroud)

这很好用,但遗憾的是很多cmdlet都没有引用它.

这看起来也很有用:

& C:\windows\System32\bitsadmin.exe /Util /SetIEProxy LOCALSYSTEM Manual_proxy $proxy $bypassList
Run Code Online (Sandbox Code Playgroud)

但这只为帐户LOCALSYSTEM,NETWORKSERVICE或LOCALSERVICE设置代理服务器.我认为userdata脚本以管理员身份运行,因此这看起来并不像它最初出现时那么有用.

所以我试图破解注册表,像这样:

$reg = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-ItemProperty -Path $reg -Name ProxyServer -Value $proxy
Set-ItemProperty -Path $reg -Name ProxyEnable -Value 1
Set-ItemProperty -Path $reg -Name ProxyOverride -Value $bypassList
Run Code Online (Sandbox Code Playgroud)

这打开了代理并设置了基本细节.但看起来有一个重要的部分缺失,因为它不起作用.然后我找到了

[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Connections]
Run Code Online (Sandbox Code Playgroud)

其中包含"DefaultConnectionSettings"和"SavedLegacySettings"键.这些似乎包含代理设置的十六进制版本.所以我创造了这个:

$proxyString = ""
    for ($i = 0;$i -lt (([System.Text.Encoding]::Unicode.GetBytes($proxy)).length); $i++) {
        if ($i % 2 -eq 0) {
            $byte = (([System.Text.Encoding]::Unicode.GetBytes($proxy))[$i])
            $convertedByte=%{[System.Convert]::ToString($byte,16)}
            $proxyString = $proxystring + $convertedByte  + ","
        }
    }
    $bypassString = ""
    for ($i = 0;$i -lt (([System.Text.Encoding]::Unicode.GetBytes($bypassList)).length); $i++) {
        if ($i % 2 -eq 0) {
            $byte = (([System.Text.Encoding]::Unicode.GetBytes($bypassList))[$i])
            $convertedByte=%{[System.Convert]::ToString($byte,16)}
            $bypassString = $bypassString + $convertedByte  + ","
        }
    }
Run Code Online (Sandbox Code Playgroud)

这将$ proxy和$ bypass转换为十六进制字符串,我将它组合成长字符串以在注册表中使用,如下所示:

$regString="46,00,00,00,00,00,00,00,0b,00,00,00,3c,00,00,00," + $proxystring + (%{[System.Convert]::ToString($bypassList.length,16)}) + ",00,00,00," + $bypassString +  "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00"
Run Code Online (Sandbox Code Playgroud)

这放入一些(看似)任意十六进制行(这可能是我的问题所在),然后是代理字符串,接着是旁路列表长度的十六进制指示符,然后是旁路列表,然后是另一个看似任意一系列十六进制值.

它适用于某些网络上的实例,但不适用于其他网络.代理地址在故障网络上比工作地址短一个字符.

但奇怪的是,如果我登录到机器,打开Internet Explorer并再次关闭它,突然cmdlet将能够成功使用代理.

那么当我打开Internet Explorer时究竟发生了什么?必须有正在更改的注册表项,这有助于此过程吗?我尝试比较之前和之后的注册表项,但看不到任何东西.

我尝试的另一件事是以编程方式创建PAC文件来配置设置.我是这样做的:

'[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings]
"AutoConfigURL"="C:\\scripts\\proxyConfig.pac"'| out-file c:\proxyReg.reg
$proxy = "internal-sec-elb-937750220.us-east-1.elb.amazonaws.com:3128"
$bypassList = "169.254.169.254;internal-mgt-priv-adr-prod-man-lb-769734587.us-east-1.elb.amazonaws.com;" + "s3.dualstack.us-east-1.amazonaws.com"

$pacFileLocation = "c:\scripts\proxyConfig.pac"
if (!(test-path (split-path $pacFileLocation))) {New-Item -ItemType Directory -Path (Split-Path $pacFileLocation)}

$pacText = 'function FindProxyForURL(url, host) {
return "PROXY ' + $proxy + ';
DIRECT";
}
'
foreach ($localAddress in ($bypassList.Split(";"))) {
$pacText = $pacText + 'if (isPlainHostName(' + $localAddress+ '))
{
return "DIRECT";
}
'

}

$pacText = $pacText + "
if (isInNet(hostIP, '0.0.0.0', '255.0.0.0') ||
isInNet(hostIP, '10.0.0.0', '255.0.0.0') ||
isInNet(hostIP, '127.0.0.0', '255.0.0.0') ||
isInNet(hostIP, '169.254.0.0', '255.255.0.0') ||
isInNet(hostIP, '172.16.0.0', '255.240.0.0') ||
isInNet(hostIP, '192.0.2.0', '255.255.255.0') ||
isInNet(hostIP, '192.88.99.0', '255.255.255.0') ||
isInNet(hostIP, '192.168.0.0', '255.255.0.0') ||
isInNet(hostIP, '198.18.0.0', '255.254.0.0') ||
isInNet(hostIP, '224.0.0.0', '240.0.0.0') ||
isInNet(hostIP, '240.0.0.0', '240.0.0.0'))
{
return 'DIRECT';
}"


$pacText | out-file $pacFileLocation -Force
Run Code Online (Sandbox Code Playgroud)

但是,似乎情况再次出现,这些设置仅在打开Internet Explorer时生效.

不幸的是我无法打开Internet Explorer,因为代理需要在用户登录到计算机之前工作,并且从脚本中运行iexplore.exe不会这样做.

这一切看起来都非常复杂.我可以在两行内的linux服务器中配置代理.我肯定错过了某处的简单解决方案.它是什么?

Tim*_*mje 6

在为 Server Core 2016 设置代理时,我得到了与 Richard 相同的结果(略短)。太可怕了,这是必要的!

function Set-Proxy($proxy, $bypassUrls){
    $proxyBytes = [system.Text.Encoding]::ASCII.GetBytes($proxy)
    $bypassBytes = [system.Text.Encoding]::ASCII.GetBytes($bypassUrls)
    $defaultConnectionSettings = [byte[]]@(@(70,0,0,0,0,0,0,0,11,0,0,0,$proxyBytes.Length,0,0,0)+$proxyBytes+@($bypassBytes.Length,0,0,0)+$bypassBytes+ @(1..36 | % {0}))
    $registryPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
    Set-ItemProperty -Path $registryPath -Name ProxyServer -Value $proxy
    Set-ItemProperty -Path $registryPath -Name ProxyEnable -Value 1
    Set-ItemProperty -Path "$registryPath\Connections" -Name DefaultConnectionSettings -Value $defaultConnectionSettings
    netsh winhttp set proxy $proxy bypass-list=$bypassUrls
}
Set-Proxy "someproxy:1234" "*.example.com;<local>"
Run Code Online (Sandbox Code Playgroud)