Exemplo n.º 1
0
        /// <summary>
        /// Runs the tool
        /// </summary>
        /// <param name="request">Incoming request</param>
        /// <param name="responseStream">Stream to write responses to</param>
        /// <param name="cancellationToken">Cancellation token for if user cancels the request</param>
        public async Task RunAsync(
            DnsTraversalRequest request,
            IServerStreamWriter <DnsTraversalResponse> responseStream,
            CancellationToken cancellationToken
            )
        {
            var responseQueue = new GrpcStreamResponseQueue <DnsTraversalResponse>(responseStream);

            request.Host = ConvertToArpaNameIfRequired(request);

            var servers = request.Servers.Count == 0
                                ? _rootServers
                                : request.Servers;

            try
            {
                await Task.WhenAll(servers.Select(
                                       async serverName => await DoLookup(
                                           request,
                                           responseQueue,
                                           cancellationToken,
                                           serverName,
                                           null,
                                           1
                                           )
                                       ));
            }
            finally
            {
                await responseQueue.CompleteAsync();
            }
        }
Exemplo n.º 2
0
 /// <summary>
 /// Wraps <see cref="DoLookupImpl"/> and ensures each lookup is only performed once, even
 /// if multiple servers return the same referral.
 /// </summary>
 private async Task DoLookup(
     DnsTraversalRequest request,
     GrpcStreamResponseQueue <DnsTraversalResponse> responseQueue,
     CancellationToken cancellationToken,
     string serverName,
     IDnsQueryResponse?responseForGlue,
     uint level
     )
 {
     await _lookupsByServer.GetOrAdd(
         $"{serverName}-{level}",
         new Lazy <Task>(async() => await DoLookupImpl(
                             request,
                             responseQueue,
                             cancellationToken,
                             serverName,
                             responseForGlue,
                             level
                             ))
         ).Value;
 }
Exemplo n.º 3
0
        private async Task DoLookupImpl(
            DnsTraversalRequest request,
            GrpcStreamResponseQueue <DnsTraversalResponse> responseQueue,
            CancellationToken cancellationToken,
            string serverName,
            IDnsQueryResponse?responseForGlue,
            uint level
            )
        {
            var serverIps = await GetDnsServerIPs(serverName, responseForGlue);

            var client = new LookupClient(new LookupClientOptions(serverIps)
            {
                UseCache       = false,
                ThrowDnsErrors = true,
                Retries        = 0,
                Timeout        = _timeout,
            });
            IDnsQueryResponse response;
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            try
            {
                response = await client.QueryAsync(
                    request.Host,
                    request.Type.ToQueryType(),
                    cancellationToken : cancellationToken
                    );

                stopwatch.Stop();
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                await responseQueue.WriteAsync(new DnsTraversalResponse
                {
                    Duration = (uint)stopwatch.ElapsedMilliseconds,
                    Error    = new Error
                    {
                        Title   = $"Failed: {ex.Message}",
                        Message = $"There is a problem with the DNS server at {serverName}",
                    },
                    From  = serverName,
                    Level = level,
                }, cancellationToken);

                return;
            }

            // DNS server was authoritive and no results exist
            if (response.Header.HasAuthorityAnswer && response.Answers.Count == 0)
            {
                await responseQueue.WriteAsync(new DnsTraversalResponse
                {
                    Duration = (uint)stopwatch.ElapsedMilliseconds,
                    Error    = new Error
                    {
                        Title   = "Failed: No results",
                        Message = "This DNS record does not exist",
                    },
                    From  = serverName,
                    Level = level,
                }, cancellationToken);

                return;
            }

            await responseQueue.WriteAsync(new DnsTraversalResponse
            {
                Duration = (uint)stopwatch.ElapsedMilliseconds,
                From     = serverName,
                Level    = level,
                Reply    = response.ToReply()
            }, cancellationToken);

            // Was this server non-authoritive?
            if (response.Answers.Count == 0)
            {
                await Task.WhenAll(
                    response.Authorities.NsRecords().Select(async record => await DoLookup(
                                                                request,
                                                                responseQueue,
                                                                cancellationToken,
                                                                record.NSDName.Value.TrimEnd('.'),
                                                                response,
                                                                level + 1
                                                                ))
                    );
            }
        }