diff --git a/Program.cs b/Program.cs index 116ad4a..f914d02 100644 --- a/Program.cs +++ b/Program.cs @@ -313,8 +313,16 @@ static class WinHttpHelper [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr GlobalFree(IntPtr hMem); + static readonly Uri ForcedUpstreamProxy = ReadForcedUpstreamProxy(); + public static Uri GetProxyForUrl(Uri url) { + if (ForcedUpstreamProxy != null) + { + Log.Info($"Using forced upstream proxy {ForcedUpstreamProxy.Host}:{ForcedUpstreamProxy.Port} for {url}"); + return ForcedUpstreamProxy; + } + IntPtr session = WinHttpOpen("proxy", WINHTTP_ACCESS_TYPE_NO_PROXY, null, null, 0); if (session == IntPtr.Zero) { @@ -331,15 +339,23 @@ static class WinHttpHelper if (WinHttpGetIEProxyConfigForCurrentUser(out ieConfig)) { var autoConfigUrl = PtrToString(ieConfig.lpszAutoConfigUrl); + bool hasSupportedAutoConfigUrl = !string.IsNullOrWhiteSpace(autoConfigUrl) + && (autoConfigUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) + || autoConfigUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)); + if (!string.IsNullOrWhiteSpace(autoConfigUrl) && !hasSupportedAutoConfigUrl) + { + Log.Warn($"IE PAC URL has unsupported scheme for WinHTTP: {autoConfigUrl}"); + } + var options = new WINHTTP_AUTOPROXY_OPTIONS { dwFlags = 0, dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A, - lpszAutoConfigUrl = ieConfig.lpszAutoConfigUrl, + lpszAutoConfigUrl = hasSupportedAutoConfigUrl ? ieConfig.lpszAutoConfigUrl : IntPtr.Zero, fAutoLogonIfChallenged = true }; - if (!string.IsNullOrWhiteSpace(autoConfigUrl)) + if (hasSupportedAutoConfigUrl) options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL; if (ieConfig.fAutoDetect) options.dwFlags |= WINHTTP_AUTOPROXY_AUTO_DETECT; @@ -453,6 +469,26 @@ static class WinHttpHelper return uri; } + static Uri ReadForcedUpstreamProxy() + { + var value = Environment.GetEnvironmentVariable("UPSTREAM_PROXY"); + if (string.IsNullOrWhiteSpace(value)) + return null; + + var normalized = value.StartsWith("http://", StringComparison.OrdinalIgnoreCase) + || value.StartsWith("https://", StringComparison.OrdinalIgnoreCase) + ? value + : "http://" + value; + + if (!Uri.TryCreate(normalized, UriKind.Absolute, out var uri) || string.IsNullOrWhiteSpace(uri.Host)) + { + Log.Error($"Invalid UPSTREAM_PROXY value: '{value}'"); + return null; + } + + return uri; + } + static void FreeWinHttpProxyInfo(WINHTTP_PROXY_INFO info) { if (info.lpszProxy != IntPtr.Zero)