Странный сбой при некоторых подключениях к Интернету для ответов rdap с использованием httpClient, но не через почтальона.
Я пытаюсь написать приложение, которое позволит любому пользователю, находящемуся в любой точке мира, получить ответ rdap для соответствующего доменного имени для любого доменного имени на основе официального списка серверов rdap здесь: https://data.iana.org/rdap/dns.json , используя собственное локальное подключение к Интернету.
Однако происходит что-то странное. При использовании моего локального подключения к Интернету (на данный момент расположенного в Юго-Восточной Азии) следующий запрос для google.com (на соответствующем сервере rdap для .com, то есть https://rdap.verisign.com/com/v1/) потерпит неудачу примерно в 80% случаев:
open System.Net.Http
let httpClient = new HttpClient()
let resp = httpClient.GetAsync($"https://rdap.verisign.com/com/v1/domain/google.com").Result
resp
Вот полученная ошибка:
System.AggregateException: One or more errors occurred. (The SSL connection could not be established, see inner exception.)
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
---> System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
--- End of inner exception stack trace ---
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](CancellationToken cancellationToken)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.HttpConnectionWaiter`1.WaitForConnectionAsync(Boolean async, CancellationToken requestCancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at FSI_0138.makeRequestWithHeaders(String url)
at <StartupCode$FSI_0138>.$FSI_0138.main@()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at FSI_0138.makeRequestWithHeaders(String url)
at <StartupCode$FSI_0138>.$FSI_0138.main@()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
В этом нет ничего интересного, можно легко объяснить проблемами с местным интернет-провайдером, верно?
Однако в почтальоне запрос работает в 100% случаев. Например:
Это никогда не терпит неудачу. Интересный!
Поэтому я подумал о перехвате пакетов в Wireshark. Ниже показано взаимодействие F# с использованием httpClient (мой реальный IP-адрес заменен на «myip»):
95 2.307971 myip rdap-1.verisigndns.com TCP 86 4 63296 → 443 [SYN] Seq=0 Win=64952 Len=0 MSS=1412 WS=256 SACK_PERM=1
106 2.550129 rdap-1.verisigndns.com myip TCP 78 4 443 → 63296 [SYN, ACK] Seq=0 Ack=1 Win=1240 Len=0 MSS=1240
107 2.550336 myip rdap-1.verisigndns.com TCP 74 4 63296 → 443 [ACK] Seq=1 Ack=1 Win=64952 Len=0
108 2.550804 myip rdap-1.verisigndns.com TLSv1.2 253 4 Client Hello
118 3.112553 myip rdap-1.verisigndns.com TCP 253 4 [TCP Retransmission] 63296 → 443 [PSH, ACK] Seq=1 Ack=1 Win=64952 Len=179
134 3.832227 myip rdap-1.verisigndns.com TCP 253 4 [TCP Retransmission] 63296 → 443 [PSH, ACK] Seq=1 Ack=1 Win=64952 Len=179
159 5.264697 myip rdap-1.verisigndns.com TCP 253 4 [TCP Retransmission] 63296 → 443 [PSH, ACK] Seq=1 Ack=1 Win=64952 Len=179
215 7.797828 rdap-1.verisigndns.com myip TCP 74 4 443 → 63296 [RST, ACK] Seq=1 Ack=1 Win=24000 Len=0
Как можно видеть, сервер rdap, похоже, игнорирует запросы моих клиентов после успешного установления связи.
Вот сетевой трафик внутри почтальона, который работает:
19193 526.178083 myip rdap.verisign.com TCP 66 98 53194 → 443 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1
19199 526.406075 rdap.verisign.com myip TCP 58 98 443 → 53194 [SYN, ACK] Seq=0 Ack=1 Win=1480 Len=0 MSS=1412
19200 526.406368 myip rdap.verisign.com TCP 54 98 53194 → 443 [ACK] Seq=1 Ack=1 Win=64240 Len=0
19201 526.407322 myip rdap.verisign.com TLSv1.3 571 98 Client Hello
19208 526.638776 rdap.verisign.com myip TLSv1.3 1454 98 Server Hello, Change Cipher Spec, Application Data
19209 526.639594 rdap.verisign.com myip TCP 1454 98 443 → 53194 [ACK] Seq=1401 Ack=518 Win=28944 Len=1400 [TCP segment of a reassembled PDU]
19210 526.639648 myip rdap.verisign.com TCP 54 98 53194 → 443 [ACK] Seq=518 Ack=2801 Win=64952 Len=0
19211 526.640264 rdap.verisign.com myip TLSv1.3 1003 98 Application Data, Application Data, Application Data
19212 526.641121 myip rdap.verisign.com TLSv1.3 368 98 Change Cipher Spec, Application Data, Application Data
19213 526.645057 rdap.verisign.com myip TCP 54 98 443 → 53194 [ACK] Seq=1 Ack=518 Win=28944 Len=0
19214 526.645082 myip rdap.verisign.com TCP 54 98 [TCP Dup ACK 19212#1] 53194 → 443 [ACK] Seq=832 Ack=3750 Win=64003 Len=0
19219 526.868863 rdap.verisign.com myip TLSv1.3 293 98 Application Data
19220 526.870003 rdap.verisign.com myip TLSv1.3 1454 98 Application Data
19221 526.870305 myip rdap.verisign.com TCP 54 98 53194 → 443 [ACK] Seq=832 Ack=5389 Win=64952 Len=0
19222 526.870775 rdap.verisign.com myip TCP 1454 98 443 → 53194 [ACK] Seq=5389 Ack=832 Win=30016 Len=1400 [TCP segment of a reassembled PDU]
19223 526.871672 rdap.verisign.com myip TLSv1.3 127 98 Application Data
19224 526.871895 myip rdap.verisign.com TCP 54 98 53194 → 443 [ACK] Seq=832 Ack=6863 Win=64952 Len=0
19225 526.878734 myip rdap.verisign.com TCP 54 98 [TCP Previous segment not captured] 53194 → 443 [FIN, ACK] Seq=856 Ack=6863 Win=64952 Len=0
19226 526.878795 myip rdap.verisign.com TCP 78 98 [TCP Out-Of-Order] 53194 → 443 [PSH, ACK] Seq=832 Ack=6863 Win=64952 Len=24
19231 527.125064 rdap.verisign.com myip TCP 60 98 [TCP Dup ACK 19219#1] 443 → 53194 [ACK] Seq=6863 Ack=832 Win=300
Поэтому я подумал, что, возможно, по какой-то причине сервер rdap отклоняет трафик от .NET httpClient, но не от почтальона (хотя это, конечно, не имело бы смысла, поскольку служба rdap должна ожидать, что большинство ее запросов поступит из автоматического источника). , а не ручные запросы почтальона). Я попытался вручную настроить заголовки для репликации почтальона в .NET:
open System.Net.Http
open System.Net.Http.Headers
let makeRequestWithHeaders (url: string) =
let httpClient = new HttpClient()
// Add headers similar to what Postman sends
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("PostmanRuntime/7.26.10")
httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/json")
httpClient.DefaultRequestHeaders.CacheControl <- CacheControlHeaderValue.Parse("no-cache")
let response = httpClient.GetAsync(url).Result
response
let url = "https://rdap.verisign.com/com/v1/domain/google.com"
let resp = makeRequestWithHeaders url
resp
Однако ничего не изменилось (по-прежнему лишь ~20% успеха).
А вот здесь все становится очень странно. Я подключился к VPN-серверу в США (через NordVPN), и теперь код .NET работает 100% времени без каких-либо сбоев (и, конечно же, почтальон тоже работает).
Но если я подключаюсь к некоторым региональным VPN-серверам, возникают аналогичные проблемы, но для разных серверов RDAP! Например, при подключении к Аргентинской VPN через NordVPN https://rdap.verisign.com/com/v1/domain/google.com работает нормально, однако официальный rdap-сервер, например, для .limo не работает ( https ://rdap.identitydigital.services/rdap/ ). Ниже приведен пример ошибочного кода .NET:
open System.Net.Http
let httpClient = new HttpClient()
let resp = httpClient.GetAsync($"https://rdap.identitydigital.services/rdap/domain/virginia.limo/").Result
resp
(не удается только на VPN-сервере Nord в Аргентине, а не на каком-либо другом сервере или при моем локальном подключении к Интернету).
Итак, я сделал следующие наблюдения относительно официальных серверов RDAP:
- Мое локальное подключение к Интернету может нормально запрашивать домены .limo как в .NET, так и в Postman, но только в доменах .com из Postman (а не в .NET).
- Сервер NordVPN в Аргентине может нормально запрашивать домены .com как в .NET, так и в Postman, но только в доменах .limo из Postman (а не в .NET).
- Сервер NordVPN в США может нормально запрашивать все расширения/домены, не сталкиваясь ни с одним сбоем, как в .NET, так и в Postman.
Эта запутанная серия фактов исключает множество правдоподобных причин, таких как проблемы с httpClient, протоколом SSL и т. д., потому что, если бы это было что-то из этого, то, конечно же, оно всегда должно давать сбой, и переключение на другой IP-адрес и геолокацию не должно Найди решение?
Итак, некоторые RDAP-серверы по какой-то причине отклоняют запросы из определенных географических местоположений иногда, если они приходят от httpClient, но никогда, если они приходят от почтальона? И почему это не одни и те же серверы RDAP, например: официальный сервер .com нормально принимает трафик Аргентины, но иногда отклоняет мой локальный IP-адрес, в то время как официальный rdap-сервер .limo принимает мой локальный трафик нормально, но иногда отклоняет трафик Аргентины.
Это очень сбивает с толку, и мне нужны отзывы о том, в чем здесь может быть проблема? Если это действительно ошибка различных RDAP-серверов и каких-то странных политик, которые они имеют, то я могу списать это на то, что это находится вне моего контроля, но я хотел бы убедиться, что это действительно так, прежде чем делать такой вывод.
Предостережения:
- Это не имеет ничего общего с вызовом .Result в GetAsync, который отлично подходит для иллюстрации.
- И мое локальное соединение, и аргентинский сервер nordVPN могут прекрасно запрашивать веб-сайты напрямую (как из .NET, так и из почтальона), проблема возникает только при взаимодействии с официальными серверами rdap.
Обновление (19 ноября 2023 г.) – 2 дня спустя
Мое локальное подключение к Интернету сегодня работает нормально для всех запросов, как если бы оно было подключено к VPN NordVPN в США, однако VPN в Аргентине по-прежнему не работает на .limo.
Это все больше похоже на проблемы со сторонними сетями, но где, как и почему я не понимаю.