当您的系统通过 Web 代理发出 HTTPS 请求时,我的理解是客户端和代理之间存在 TCP 握手,然后客户端发送 HTTP CONNECT 以建立与最终服务器的连接。
我目前遇到了一个奇怪的问题,我发现 TCP 握手和 HTTP CONNECT 之间有明显的延迟(约 20 秒),问题显然出在客户端。我的猜测是客户端正在尝试执行某项操作(从任何日志中都看不到),然后超时。
我想知道在建立 TCP 连接和 HTTP CONNECT 请求之间发生了什么。是否有 DNS 查找或类似的东西?
我之前问过服务器故障,但那里的问题太过宽泛且偏离主题。
答案1
我想知道在建立 TCP 连接和 HTTP CONNECT 请求之间发生了什么。是否有 DNS 查找或类似的东西?
用一个数据包捕获使用 Wireshark、tcpdump 或 MS Network Monitor 等程序查看发生了什么。如果它通过网络传输,无论它是什么,您都会在捕获中看到它。
如果事实证明确实如此不是通过网络,那么问题很大程度上取决于客户端软件(主要是操作系统),因为跟踪本质上是特定于平台的。对于 Linux,我会从“strace”或 Sysprof 开始,看看程序正在做什么;对于 Windows,请尝试“API Monitor”。
答案2
Kerberos 身份验证
在我们的案例中,实现了 NTLM 身份验证,但未实现 Kerberos。默认情况下,.net 客户端会尝试 Kerberos 身份验证,而不是 NTLM。
代理上没有日志的原因是客户端正在尝试连接到各种域控制器以启动 Kerberos 身份验证。由于这些连接都因超时而失败,它最终会回退到 NTLM,这是代理所期望的。
对于使用的.net客户端System.Net.WebProxy
,您需要在配置中指定身份验证类型:
var credentials = new NetworkCredential(proxyUsername, proxyPassword);
var credentialCache = new CredentialCache();
credentialCache.Add(new System.Uri(proxyUrl), "NTLM", credentials);
var myProxy = new WebProxy(proxyUrl)
{
UseDefaultCredentials = false,
Credentials = credentialCache
}
// You can then use myProxy in HttpClient instances
答案3
我们遇到过与您非常相似的问题,只是我们的代理在 Linux 上运行 Squid,并且 ACL 基于源 IP 而不是客户端身份验证。
对于其他阅读本文的人来说,如果您在 Framework 4.8 上运行的 .NET C# 代码中有一个调用:
WebRequest.GetSystemWebProxy();
然后,当操作系统试图找出您可能拥有哪条通往互联网的“路径”时,各种内置测试都会超时,这也是在发出 HTTP 请求之前延迟 15-25 秒的另一个原因。
在 .config 文件中明确设置代理设置,然后在代码中设置如下:
var proxy = new WebProxy(_environmentProxyIp, _environmentProxyPort ?? 0)
然后延迟就消失了。
Andy 的延迟用例与 Kerberos 有关,而(虽然我没有确认,因为没有通过数据包捕获看到任何东西)我怀疑在我们的案例中,这是 MS 正在使用的其他“反复试验”技术,用于尝试检测如何在未定义明确代理的情况下访问互联网,并且每个测试最终都会超时,然后才能继续下一个测试。至少这是我的理论......