Support NTLM/Kerberos upstream proxy authentication #944
Description
I'm trying to create a local proxy service based on the WindowsService example to overcome limitations in my company.
Every PC is set up with a PAC URL that contains what proxy to use for each destination. This is what a correct request to the outside world looks like:
$ curl --proxy {upstreamproxy}:8080 --proxy-ntlm --proxy-user ":" --verbose https://ipinfo.io
* Trying {omitted}:8080...
* Connected to {upstreamproxy} ({omitted}) port 8080 (#0)
* allocate connect buffer
> CONNECT ipinfo.io:443 HTTP/1.1
> Host: ipinfo.io:443
> Proxy-Authorization: NTLM {omitted}
> User-Agent: curl/7.83.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 407 authenticationrequired
< Date: Wed, 04 Jan 2023 10:36:50 GMT
< Content-Type: text/html
< Cache-Control: no-cache
< Content-Length: 0
< X-Frame-Options: deny
< Proxy-Connection: Keep-Alive
< Proxy-Authenticate: NTLM {omitted}
<
> CONNECT ipinfo.io:443 HTTP/1.1
> Host: ipinfo.io:443
> Proxy-Authorization: NTLM {omitted}
> User-Agent: curl/7.83.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.0 200 Connection established
<
> GET / HTTP/1.1
> Host: ipinfo.io
> User-Agent: curl/7.83.1
> Accept: */*
>
< HTTP/1.1 200 OK
< {ipinfo.io response headers, omitted}
Based on the example provided, this is what I've written:
protected override void OnStart(string[] args)
{
proxyServerInstance = new(userTrustRootCertificate: false) {
CheckCertificateRevocation = X509RevocationMode.NoCheck,
ConnectionTimeOutSeconds = 30,
Enable100ContinueBehaviour = true,
EnableConnectionPool = true,
EnableTcpServerConnectionPrefetch = true,
EnableWinAuth = true,
ForwardToUpstreamGateway = true,
MaxCachedConnections = 2,
ReuseSocket = true,
TcpTimeWaitSeconds = 30,
EnableHttp2 = true,
NoDelay = true,
ThreadPoolWorkerThread = Environment.ProcessorCount,
ExceptionFunc = ProxyException,
};
proxyServerInstance.CertificateManager.SaveFakeCertificates = false;
var explicitEndPointV4 = new ExplicitProxyEndPoint(IPAddress.Loopback, ListeningPort, false);
proxyServerInstance.AddEndPoint(explicitEndPointV4);
var explicitEndPointV6 = new ExplicitProxyEndPoint(IPAddress.IPv6Loopback, ListeningPort, false);
proxyServerInstance.AddEndPoint(explicitEndPointV6);
proxyServerInstance.Start();
#if DEBUG
Console.WriteLine($"Service Listening on port {ListeningPort}");
#else
ProxyServiceEventLog.WriteEntry($"Service Listening on port {ListeningPort}", EventLogEntryType.Information);
#endif
}
However the exception Upstream proxy failed to create a secure tunnel
is raised.
Looking at the code it may depend on how Windows authentication is handled.
titanium-web-proxy/src/Titanium.Web.Proxy/ResponseHandler.cs
Lines 40 to 47 in 902504a
I guess the problem here is the upstream proxy replying with 407 rather then 401, but I have limited debugging capabilities (work PC) and it's hard to investigate further.
Can someone please help me troubleshoot this? I'm using .NET Core 6 (can't install full Visual Studio) and Titanium 3.2.0.