Skip to content

Instantly share code, notes, and snippets.

@nanto

nanto/pac-server.ps1

Created Mar 21, 2020
Embed
What would you like to do?
Serve proxy auto-configuration file on Windows
# Serve proxy auto-configuration file
Param(
[int]$PacPort = 2694,
[int]$SocksPort = 1080
)
# Write your pac file content here:
$pac = [System.Text.Encoding]::UTF8.GetBytes(@"
function FindProxyForURL(url, host) {
var socks = 'SOCKS5 127.0.0.1:$SocksPort';
if (
dnsDomainIs(host, '.internal.exapmle.com') ||
dnsDomainIs(host, '.internal.example.org')
) {
return socks;
}
var hostIP = dnsResolve(host);
if (
isInNet(hostIP, '10.0.0.0', '255.0.0.0') ||
isInNet(hostIP, '192.168.0.0', '255.255.0.0')
) {
return socks;
}
return 'DIRECT';
}
"@)
$url = "http://127.0.0.1:$PacPort/"
$registryPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings'
$registryName = 'AutoConfigURL'
# Refresh proxy settings.
# ref. https://web.archive.org/web/20170602213824/http://www.hsyntt.com/changing-proxy-server-settings-for-internet-explorer-using-powershell/
$WinInet = Add-Type -MemberDefinition @'
[DllImport("wininet.dll")]
public static extern bool InternetSetOption(IntPtr hInternet, uint dwOption, IntPtr lpBuffer, uint dwBufferLength);
'@ -Name Win32InternetSettings -PassThru
$INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95
$INTERNET_OPTION_REFRESH = 37
function Refresh-Proxy-Settings {
$WinInet::InternetSetOption([System.IntPtr]::Zero, $INTERNET_OPTION_PROXY_SETTINGS_CHANGED, [System.IntPtr]::Zero, 0) | Out-Null
$WinInet::InternetSetOption([System.IntPtr]::Zero, $INTERNET_OPTION_REFRESH, [System.IntPtr]::Zero, 0) | Out-Null
}
$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add($url)
try {
$listener.Start()
Set-ItemProperty -Path $registryPath -Name $registryName -Value $url
Refresh-Proxy-Settings
Write-Host "Serving Proxy Auto-Configuration File on $url"
Write-Host "Please execute 'ssh -D $SocksPort <gateway-server>'"
Write-Host ''
Write-Host 'Press Ctrl+C to exit.'
while ($True) {
# Use async method to accept Ctrl+C while waiting a request.
# ref. https://stackoverflow.com/questions/51218257/await-async-c-sharp-method-from-powershell
$task = $listener.GetContextAsync()
while (-not $task.AsyncWaitHandle.WaitOne(200)) { }
$context = $task.GetAwaiter().GetResult()
$response = $context.Response
$response.ContentType = 'application/x-ns-proxy-autoconfig'
$response.ContentLength64 = $pac.Length
$response.Close($pac, $True)
}
} finally {
Remove-ItemProperty -Path $registryPath -Name $registryName
Refresh-Proxy-Settings
$listener.Close()
}
@jay-99

This comment has been minimized.

Copy link

@jay-99 jay-99 commented Jun 19, 2020

Hi. I have noticed that the Refresh-Proxy-Settings function has stopped working on windows 10 version 2004. I've test this on 3 computers running Windows 1909 and it's working on all of them. I've also tested on 3 computers running Windows 10 2004 and none of them work, so I think an update has broken this. Are you able to confirm on your side?

@nanto

This comment has been minimized.

Copy link
Owner Author

@nanto nanto commented Jun 19, 2020

Thank you for your report! I'm afraid I don't have Windows 10 2004 computers.

Maybe we have to change proxy settings by calling the InternetSetOption function with the INTERNET_OPTION_PER_CONNECTION_OPTION flag as written in https://web.archive.org/web/20150110221907/http://support.microsoft.com/kb/226473/en-us , or we have to use some other API...

@jay-99

This comment has been minimized.

Copy link

@jay-99 jay-99 commented Jun 23, 2020

Thanks, I will look into this and let you know if I find anything useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.