Exemplo n.º 1
0
        public async Task TestQuery()
        {
            using var tokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(500));

            var endpoint = GenerateEndPoint();

            // Create a real upstream DNS client to serve the request (todo: mock this)
            using var upstream = new DnsUdpClient(IPAddress.Parse("1.1.1.1"));

            // Create a loopback server
            using var server = new DnsUdpServer(endpoint, upstream);

            // Start recieving
            using var receiveTask = server.Listen(tokenSource.Token);

            // Create a loopback DNS client to talk to the server
            using var client = new DnsUdpClient(endpoint);

            try
            {
                var query = DnsQueryFactory.CreateQuery("google.com");

                // Send a DNS request to the server, verify the results
                var response = await client.Query(query, tokenSource.Token);

                Assert.Equal(query.Id, response.Header.Id);
                Assert.Equal(query.Host, response.Header.Host);
                Assert.True(response.Answers.Count > 0);
            }
            finally
            {
                tokenSource.Cancel();
                await receiveTask;
            }
        }
Exemplo n.º 2
0
        private void buttonClientSend_Click(object sender, EventArgs e)
        {
            string    errorMessage;
            IPAddress serverAddr;

            Cursor = Cursors.WaitCursor;
            buttonClientSend.Enabled = false;

            if (!ValidateServerText(textBoxClientServer.Text, out errorMessage))
            {
                errorProvider1.SetError(textBoxClientServer, errorMessage);
                return;
            }
            try
            {
                // resolve server name by System.Net.Dns
                serverAddr = System.Net.Dns.GetHostAddresses(textBoxClientServer.Text.Trim()).First();
            }
            catch (SocketException)
            {
                errorProvider1.SetError(textBoxClientServer, "Server name cannot be resolved.");
                return;
            }

            try
            {
                IDnsClient client;
                if (radioButtonClientTCP.Checked)
                {
                    client = new DnsTcpClient();
                }
                else
                {
                    client = new DnsUdpClient();
                }

                Request request = new Request(
                    (ushort)DateTime.Now.Ticks,
                    checkBoxClientRD.Checked,
                    (OPCODE)Enum.Parse(typeof(OPCODE), comboBoxClientOPCODE.SelectedValue.ToString()),
                    new Question(
                        textBoxClientQNAME.Text.Trim(),
                        (QTYPE)Enum.Parse(typeof(QTYPE), comboBoxClientQTYPE.SelectedValue.ToString()),
                        (QCLASS)Enum.Parse(typeof(QCLASS), comboBoxClientQCLASS.SelectedValue.ToString())));


                labelClientResponse.Text   = String.Empty;
                textBoxClientResponse.Text = String.Empty;

                client.Connect(serverAddr);
                client.BeginProcess(request, new AsyncCallback(OnClientResponseReceived),
                                    new ClientAsyncState {
                    Client = client, Request = request, Server = serverAddr
                });

                //try
                //{
                //  client.Connect(serverAddr);
                //  DnsClient.Response response = client.LookUp(request);
                //  labelClientResponse.Text = String.Format("{0}: {1} from [{2}] in {3}ms",
                //    (response.Header.AA ? "Authoritative Response" : "Non-Authoritative Response"),
                //    response.Header.RCODE.ToString(),
                //    serverAddr.ToString(),
                //    response.Timestamp.Subtract(request.Timestamp).TotalMilliseconds);
                //  StringBuilder result = new StringBuilder();
                //  RenderResponse(response, result);
                //  textBoxClientResponse.Text = result.ToString();
                //}
                //finally
                //{
                //  Cursor = Cursors.Default;
                //  buttonClientSend.Enabled = true;
                //}
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
Exemplo n.º 3
0
 public void TestCleanup()
 {
     this.client?.Dispose();
     this.client = null;
 }
Exemplo n.º 4
0
 public void TestInitialize()
 {
     this.client = new DnsUdpClient();
 }
Exemplo n.º 5
0
        static void Main(string[] args)
        {
            try
            {
                File.Delete(filename);

                bool interactive = false;

                NameServer selected = null;
                while (true)
                {
                    if (File.Exists(filename))
                    {
                        using (DnsUdpClient client = new DnsUdpClient())
                        {
                            client.Client.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, System.Net.Sockets.SocketOptionName.ReceiveTimeout, 1000);

                            client.LogMessageCreated += new LogMessageEventHandler(OnLogMessage);
                            ResolutionIterator iterator = DeSerializeObject <ResolutionIterator>(filename);

                            iterator.Resolver.Connect(client);
                            if (iterator.MoveNext(selected))
                            {
                                Console.WriteLine();

                                ResolutionResult result = iterator.Current;

                                //Console.WriteLine("Response from {0} - chosen from {1} authorities", result.Authorities.Selected.Name, result.Authorities.ZoneName);
                                //foreach (NameServer ns in result.Authorities)
                                //{
                                //  Console.WriteLine("  {0}", ns);
                                //}

                                Console.WriteLine("Took {0}ms:", result.Duration.TotalMilliseconds);
                                RenderResponse(result.Response);

                                if (interactive)
                                {
                                    selected = null;
                                    if (result.NextAuthorities != null)
                                    {
                                        Console.WriteLine();
                                        Console.WriteLine("Next authorities:");
                                        int i = 1;
                                        foreach (NameServer ns in result.NextAuthorities)
                                        {
                                            Console.WriteLine("  ({0}) {1}", i, ns.ToString());
                                            i++;
                                        }

                                        while (true)
                                        {
                                            Console.Write("Select next authority or ENTER for random: ");
                                            int    s;
                                            string choice = Console.ReadLine();
                                            if (!String.IsNullOrEmpty(choice))
                                            {
                                                if (int.TryParse(choice, out s))
                                                {
                                                    if (s >= 1 && s <= result.NextAuthorities.Count)
                                                    {
                                                        selected = result.NextAuthorities[s - 1];
                                                        break;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }
                                    }
                                }

                                SerializeObject <ResolutionIterator>(filename, iterator);
                                Console.WriteLine("====================================");
                            }
                            else
                            {
                                Console.WriteLine("finished.");
                                File.Delete(filename);
                            }
                        }
                    }
                    else
                    {
                        DnsDomain domain = null;
                        QTYPE     question;

                        try
                        {
                            Console.Write("enter name: ");
                            domain = DnsDomain.Parse(Console.ReadLine().Trim());
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            goto next;
                        }

                        try
                        {
                            Console.Write("enter question: ");
                            question = (QTYPE)Enum.Parse(typeof(QTYPE), Console.ReadLine().Trim(), true);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            goto next;
                        }

                        Console.WriteLine("OK: {0} IN {1}", domain, question.ToString());

                        DomainResolver     resolver = new DomainResolver(Options.Default, domain);
                        ResolutionIterator iterator = resolver.GetIterator(question);
                        iterator.LogMessageCreated += new LogMessageEventHandler(OnLogMessage);

                        SerializeObject <ResolutionIterator>(filename, iterator);
                    }

next:
                    Console.WriteLine();
                    Console.WriteLine("type 'q' to quit, ENTER to continue.");
                    ConsoleKeyInfo ck = Console.ReadKey();
                    if (ck.KeyChar == 'q')
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
Exemplo n.º 6
0
 public async Task TestLookupTimeout()
 {
     // Reserved - see https://en.wikipedia.org/wiki/Reserved_IP_addresses
     using var client = new DnsUdpClient(new NullLogger <DnsUdpClient>(), IPAddress.Parse("192.88.99.0"));
     await Assert.ThrowsAsync <DnsClientTimeoutException>(() => client.Query(DnsQueryFactory.CreateQuery("alanedwardes.com"), CancellationToken.None));
 }
Exemplo n.º 7
0
 public async Task TestLookupWithGoogle(string domain, DnsQueryType type)
 {
     using var client = new DnsUdpClient(new NullLogger <DnsUdpClient>(), IPAddress.Parse("8.8.8.8"));
     await client.RunQuery(domain, type);
 }
Exemplo n.º 8
0
 public async Task TestLookupWithCloudFlare(string domain, DnsQueryType type)
 {
     using var client = new DnsUdpClient(new NullLogger <DnsUdpClient>(), IPAddress.Parse("1.1.1.1"));
     await client.RunQuery(domain, type, type == DnsQueryType.ANY?DnsResponseCode.NotImp : DnsResponseCode.NoError);
 }
Exemplo n.º 9
0
        /// <summary>
        /// Resolves a DNS name.
        /// </summary>
        /// <param name="Name">Domain Name to resolve</param>
        /// <param name="TYPE">Resource Record Type of interest.</param>
        /// <param name="ExceptionType">If no answer of type <paramref name="TYPE"/> is found, records of this type can also be accepted.</param>
        /// <param name="CLASS">Resource Record Class of interest.</param>
        /// <returns>Answer to the query</returns>
        /// <exception cref="IOException">If the domain name could not be resolved for the TYPE and CLASS provided.</exception>
        public static async Task <ResourceRecord[]> Resolve(string Name, QTYPE TYPE,
                                                            TYPE?ExceptionType, QCLASS CLASS)
        {
            LinkedList <KeyValuePair <string, IPEndPoint> > Backup = null;
            TYPE?      ExpectedType;
            IPEndPoint Destination = null;
            string     LastName    = null;
            int        Timeout     = 2000;      // Local timeout

            if (Enum.TryParse <TYPE>(TYPE.ToString(), out TYPE T))
            {
                ExpectedType = T;
            }
            else
            {
                ExpectedType = null;
            }

            lock (synchObject)
            {
                if (nestingDepth == 0 && networkChanged)
                {
                    networkChanged = false;
                    client?.Dispose();
                    client = null;
                }

                if (client is null)
                {
                    client = new DnsUdpClient();
                }

                nestingDepth++;
            }

            try
            {
                while (true)
                {
                    DnsResponse Response = null;
                    DnsMessage  Message;

                    if (LastName is null || LastName != Name)
                    {
                        LastName = Name;

                        try
                        {
                            Response = await Database.FindFirstDeleteRest <DnsResponse>(new FilterAnd(
                                                                                            new FilterFieldEqualTo("Name", Name),
                                                                                            new FilterFieldEqualTo("Type", TYPE),
                                                                                            new FilterFieldEqualTo("Class", CLASS)));

                            if (!(Response is null) && Response.Expires <= DateTime.Now)
                            {
                                await Database.Delete(Response);

                                Response = null;
                            }
                        }
                        catch (Exception)
                        {
                            // Some inconsistency in database. Clear collection to get fresh set of DNS entries.
                            await Database.Clear("DnsCache");

                            Response = null;
                        }
                    }

                    if (Response is null)
                    {
                        try
                        {
                            Message = await client.SendRequestAsync(OpCode.Query, true, new Question[]
                            {
                                new Question(Name, TYPE, CLASS)
                            }, Destination, Timeout);

                            switch (Message.RCode)
                            {
                            case RCode.NXDomain:
                                throw new ArgumentException("Domain name does not exist.", nameof(Name));
                            }
                        }
                        catch (TimeoutException)
                        {
                            Message = null;
                        }

                        if (Message is null || Message.RCode != RCode.NoError)
                        {
                            Destination = await NextDestination(Backup);

                            if (Destination is null)
                            {
                                throw new IOException("Unable to resolve DNS query.");
                            }

                            continue;                               // Check an alternative
                        }

                        uint Ttl = 60 * 60 * 24 * 30;                               // Maximum TTL = 30 days

                        Response = new DnsResponse()
                        {
                            Name       = Name,
                            Type       = TYPE,
                            Class      = CLASS,
                            Answer     = CheckTtl(ref Ttl, Message.Answer),
                            Authority  = CheckTtl(ref Ttl, Message.Authority),
                            Additional = CheckTtl(ref Ttl, Message.Additional)
                        };

                        Response.Expires = DateTime.Now.AddSeconds(Ttl);

                        await Database.Insert(Response);
                    }

                    string CName = null;

                    if (!(Response.Answer is null))
                    {
                        if (!ExpectedType.HasValue)
                        {
                            return(Response.Answer);
                        }

                        foreach (ResourceRecord RR in Response.Answer)
                        {
                            if (RR.Type == ExpectedType.Value)
                            {
                                return(Response.Answer);
                            }

                            if (CName is null && RR.Type == Enumerations.TYPE.CNAME && RR is CNAME CNAME)
                            {
                                CName = CNAME.Name2;
                            }
                        }

                        if (ExceptionType.HasValue)
                        {
                            foreach (ResourceRecord RR in Response.Answer)
                            {
                                if (RR.Type == ExceptionType.Value)
                                {
                                    return(Response.Answer);
                                }
                            }
                        }

                        if (!(CName is null))
                        {
                            Name   = CName;
                            Backup = null;
                            continue;
                        }
                    }

                    if (!(Response.Authority is null))
                    {
                        foreach (ResourceRecord RR in Response.Authority)
                        {
                            if (RR is NS NS)
                            {
                                string    Authority        = NS.Name2;
                                IPAddress AuthorityAddress = null;

                                if (!(Response.Additional is null))
                                {
                                    foreach (ResourceRecord RR2 in Response.Additional)
                                    {
                                        if (RR2 is A A)
                                        {
                                            AuthorityAddress = A.Address;
                                            break;
                                        }
                                        else if (RR2 is AAAA AAAA)
                                        {
                                            AuthorityAddress = AAAA.Address;
                                            break;
                                        }
                                    }
                                }

                                if (Backup is null)
                                {
                                    Backup = new LinkedList <KeyValuePair <string, IPEndPoint> >();
                                }

                                if (AuthorityAddress is null)
                                {
                                    Backup.AddLast(new KeyValuePair <string, IPEndPoint>(Authority, null));
                                }
                                else
                                {
                                    Backup.AddLast(new KeyValuePair <string, IPEndPoint>(null, new IPEndPoint(AuthorityAddress, DefaultDnsPort)));
                                }
                            }
                        }
                    }

                    Destination = await NextDestination(Backup);

                    if (Destination is null)
                    {
                        throw new IOException("Unable to resolve DNS query.");
                    }

                    Timeout = 5000;
                }
            }
            finally
            {
                lock (synchObject)
                {
                    nestingDepth--;
                }
            }
        }