예제 #1
0
        public int LoadFrom(byte[] bytes, int offset, ushort count)
        {
            int currentOffset = offset;

            for (int index = 0; index < count; index++)
            {
                // TODO: move this code into the Question object

                Question question = new Question();

                question.Name = DnsProtocol.ReadString(bytes, ref currentOffset);

                question.Type  = (ResourceType)(BitConverter.ToUInt16(bytes, currentOffset).SwapEndian());
                currentOffset += 2;

                question.Class = (ResourceClass)(BitConverter.ToUInt16(bytes, currentOffset).SwapEndian());
                currentOffset += 2;

                this.Add(question);
            }

            int bytesRead = currentOffset - offset;

            return(bytesRead);
        }
예제 #2
0
        public static DomainNamePointRData Parse(byte[] bytes, int offset, int size)
        {
            DomainNamePointRData domainName = new DomainNamePointRData();

            domainName.Name = DnsProtocol.ReadString(bytes, ref offset);
            return(domainName);
        }
예제 #3
0
        public static CNameRData Parse(byte[] bytes, int offset, int size)
        {
            CNameRData cname = new CNameRData();

            cname.Name = DnsProtocol.ReadString(bytes, ref offset);
            return(cname);
        }
예제 #4
0
        public static NameServerRData Parse(byte[] bytes, int offset, int size)
        {
            NameServerRData nsRdata = new NameServerRData();

            nsRdata.Name = DnsProtocol.ReadString(bytes, ref offset);
            return(nsRdata);
        }
예제 #5
0
        public static StatementOfAuthorityRData Parse(byte[] bytes, int offset, int size)
        {
            StatementOfAuthorityRData soaRdata = new StatementOfAuthorityRData();

            soaRdata.PrimaryNameServer = DnsProtocol.ReadString(bytes, ref offset);
            soaRdata.ResponsibleAuthoritativeMailbox = DnsProtocol.ReadString(bytes, ref offset);
            soaRdata.Serial          = DnsProtocol.ReadUint(bytes, ref offset).SwapEndian();
            soaRdata.RefreshInterval = DnsProtocol.ReadUint(bytes, ref offset).SwapEndian();
            soaRdata.RetryInterval   = DnsProtocol.ReadUint(bytes, ref offset).SwapEndian();
            soaRdata.ExpirationLimit = DnsProtocol.ReadUint(bytes, ref offset).SwapEndian();
            soaRdata.MinimumTTL      = DnsProtocol.ReadUint(bytes, ref offset).SwapEndian();
            return(soaRdata);
        }
예제 #6
0
        public int LoadFrom(byte[] bytes, int offset, ushort count)
        {
            int currentOffset = offset;

            for (int index = 0; index < count; index++)
            {
                // TODO: move this code into the Resource object

                Resource resource = new Resource();
                //// extract the domain, question type, question class and Ttl

                resource.Name = DnsProtocol.ReadString(bytes, ref currentOffset);

                resource.Type  = (ResourceType)(BitConverter.ToUInt16(bytes, currentOffset).SwapEndian());
                currentOffset += sizeof(ushort);

                resource.Class = (ResourceClass)(BitConverter.ToUInt16(bytes, currentOffset).SwapEndian());
                currentOffset += sizeof(ushort);

                resource.TTL   = BitConverter.ToUInt32(bytes, currentOffset).SwapEndian();
                currentOffset += sizeof(uint);

                resource.DataLength = BitConverter.ToUInt16(bytes, currentOffset).SwapEndian();
                currentOffset      += sizeof(ushort);

                if (resource.Class == ResourceClass.IN && resource.Type == ResourceType.A)
                {
                    resource.RData = ANameRData.Parse(bytes, currentOffset, resource.DataLength);
                }
                else if (resource.Type == ResourceType.CNAME)
                {
                    resource.RData = CNameRData.Parse(bytes, currentOffset, resource.DataLength);
                }

                // move past resource data record
                currentOffset = currentOffset + resource.DataLength;

                this.Add(resource);
            }

            int bytesRead = currentOffset - offset;

            return(bytesRead);
        }
예제 #7
0
        /// <summary>Process UDP Request</summary>
        /// <param name="args"></param>
        private void ProcessUdpRequest(SocketAsyncEventArgs args)
        {
            DnsMessage message;

            if (!DnsProtocol.TryParse(args.Buffer, out message))
            {
                // TODO log bad message
                Console.WriteLine("unable to parse message");
                return;
            }

            Interlocked.Increment(ref _requests);

            if (message.IsQuery())
            {
                if (message.Questions.Count > 0)
                {
                    foreach (Question question in message.Questions)
                    {
                        Console.WriteLine("{0} asked for {1} {2} {3}", args.RemoteEndPoint.ToString(), question.Name, question.Class, question.Type);
                        IPHostEntry entry;
                        if (question.Type == ResourceType.PTR)
                        {
                            if (question.Name == "1.0.0.127.in-addr.arpa") // query for PTR record
                            {
                                message.QR = true;
                                message.AA = true;
                                message.RA = false;
                                message.AnswerCount++;
                                message.Answers.Add(new ResourceRecord {
                                    Name = question.Name, Class = ResourceClass.IN, Type = ResourceType.PTR, TTL = 3600, DataLength = 0xB, RData = new DomainNamePointRData()
                                    {
                                        Name = "localhost"
                                    }
                                });
                            }
                        }
                        else if (_resolver.TryGetHostEntry(question.Name, question.Class, question.Type, out entry)) // Right zone, hostname/machine function does exist
                        {
                            message.QR    = true;
                            message.AA    = true;
                            message.RA    = false;
                            message.RCode = (byte)RCode.NOERROR;
                            foreach (IPAddress address in entry.AddressList)
                            {
                                message.AnswerCount++;
                                message.Answers.Add(new ResourceRecord {
                                    Name = question.Name, Class = ResourceClass.IN, Type = ResourceType.A, TTL = 10, RData = new ANameRData {
                                        Address = address
                                    }
                                });
                            }
                        }
                        else if (question.Name.EndsWith(_resolver.GetZoneName())) // Right zone, but the hostname/machine function doesn't exist
                        {
                            message.QR          = true;
                            message.AA          = true;
                            message.RA          = false;
                            message.RCode       = (byte)RCode.NXDOMAIN;
                            message.AnswerCount = 0;
                            message.Answers.Clear();

                            var soaResourceData = new StatementOfAuthorityRData()
                            {
                                PrimaryNameServer = Environment.MachineName, ResponsibleAuthoritativeMailbox = "stephbu." + Environment.MachineName, Serial = _resolver.GetZoneSerial(), ExpirationLimit = 86400, RetryInterval = 300, RefreshInterval = 300, MinimumTTL = 300
                            };
                            var soaResourceRecord = new ResourceRecord {
                                Class = ResourceClass.IN, Type = ResourceType.SOA, TTL = 300, RData = soaResourceData
                            };
                            message.NameServerCount++;
                            message.Authorities.Add(soaResourceRecord);
                        }
                        //
                        else // Referral to regular DC DNS servers
                        {
                            // store current IP address and Query ID.
                            try
                            {
                                string key = GetKeyName(message);
                                _requestResponseMapLock.EnterWriteLock();
                                _requestResponseMap.Add(key, args.RemoteEndPoint);
                            }
                            finally
                            {
                                _requestResponseMapLock.ExitWriteLock();
                            }
                        }

                        using (MemoryStream responseStream = new MemoryStream(512))
                        {
                            message.WriteToStream(responseStream);
                            if (message.IsQuery())
                            {
                                // send to upstream DNS servers
                                foreach (IPHostEntry dnsServer in _defaultDns)
                                {
                                    SendUdp(responseStream.GetBuffer(), 0, (int)responseStream.Position, new IPEndPoint(dnsServer.AddressList.First(addr => addr.AddressFamily == AddressFamily.InterNetwork), 53));
                                }
                            }
                            else
                            {
                                Interlocked.Increment(ref _responses);
                                SendUdp(responseStream.GetBuffer(), 0, (int)responseStream.Position, args.RemoteEndPoint);
                            }
                        }
                    }
                }
            }
            else
            {
                // message is response to a delegated query
                string key = GetKeyName(message);
                try
                {
                    _requestResponseMapLock.EnterUpgradeableReadLock();

                    EndPoint ep;
                    if (_requestResponseMap.TryGetValue(key, out ep))
                    {
                        // first test establishes presence
                        try
                        {
                            _requestResponseMapLock.EnterWriteLock();
                            // second test within lock means exclusive access
                            if (_requestResponseMap.TryGetValue(key, out ep))
                            {
                                using (MemoryStream responseStream = new MemoryStream(512))
                                {
                                    message.WriteToStream(responseStream);
                                    Interlocked.Increment(ref _responses);

                                    Console.WriteLine("{0} answered {1} {2} {3} to {4}", args.RemoteEndPoint.ToString(), message.Questions[0].Name, message.Questions[0].Class, message.Questions[0].Type, ep.ToString());

                                    SendUdp(responseStream.GetBuffer(), 0, (int)responseStream.Position, ep);
                                }
                                _requestResponseMap.Remove(key);
                            }
                        }
                        finally
                        {
                            _requestResponseMapLock.ExitWriteLock();
                        }
                    }
                    else
                    {
                        Interlocked.Increment(ref _nacks);
                    }
                }
                finally
                {
                    _requestResponseMapLock.ExitUpgradeableReadLock();
                }
            }
        }
예제 #8
0
        /// <summary>Process UDP Request</summary>
        /// <param name="args"></param>
        private void ProcessUdpRequest(SocketAsyncEventArgs args)
        {
            DnsMessage message;

            if (!DnsProtocol.TryParse(args.Buffer, out message))
            {
                // TODO log bad message
                Logger.Warn("Unable to parse message...");
                return;
            }

            Interlocked.Increment(ref _requests);

            if (message.IsQuery())
            {
                if (message.Questions.Count > 0)
                {
                    foreach (Question question in message.Questions)
                    {
                        Logger.Debug("{0} asked for {1} {2} {3}", args.RemoteEndPoint.ToString(), question.Name, question.Class, question.Type);

                        IPHostEntry entry;
                        if (question.Type == ResourceType.PTR && question.Name == "1.0.0.127.in-addr.arpa")
                        {
                            message.QR = true;
                            message.AA = true;
                            message.RA = false;
                            message.AnswerCount++;
                            message.Answers.Add(new ResourceRecord {
                                Name = question.Name, Class = ResourceClass.IN, Type = ResourceType.PTR, TTL = 3600, DataLength = 0xB, RData = new DomainNamePointRData()
                                {
                                    Name = "localhost"
                                }
                            });
                        }
                        //else if (_resolvers.Any(o => o.TryGetHostEntry(question.Name, question.Class, question.Type, out entry)) // Right zone, hostname/machine function does exist
                        //{
                        //    message.QR = true;
                        //    message.AA = true;
                        //    message.RA = false;
                        //    message.RCode = (byte)RCode.NOERROR;
                        //    foreach (IPAddress address in entry.AddressList)
                        //    {
                        //        message.AnswerCount++;
                        //        message.Answers.Add(new ResourceRecord { Name = question.Name, Class = ResourceClass.IN, Type = ResourceType.A, TTL = 10, RData = new ANameRData { Address = address } });
                        //    }
                        //}
                        //else if (question.Name.EndsWith(_resolvers.GetZoneName())) // Right zone, but the hostname/machine function doesn't exist
                        //{
                        //    message.QR = true;
                        //    message.AA = true;
                        //    message.RA = false;
                        //    message.RCode = (byte)RCode.NXDOMAIN;
                        //    message.AnswerCount = 0;
                        //    message.Answers.Clear();

                        //    var soaResourceData = new StatementOfAuthorityRData() { PrimaryNameServer = Environment.MachineName, ResponsibleAuthoritativeMailbox = "stephbu." + Environment.MachineName, Serial = _resolvers.GetZoneSerial(), ExpirationLimit = 86400, RetryInterval = 300, RefreshInterval = 300, MinimumTTL = 300 };
                        //    var soaResourceRecord = new ResourceRecord { Class = ResourceClass.IN, Type = ResourceType.SOA, TTL = 300, RData = soaResourceData };
                        //    message.NameServerCount++;
                        //    message.Authorities.Add(soaResourceRecord);
                        //}
                        // Host Resolution
                        else if (_dnsConfig.HostOverrides.Any(o => String.Equals(question.Name, o.Hostname, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            var address = _dnsConfig.HostOverrides.First(o => String.Equals(question.Name, o.Hostname, StringComparison.InvariantCultureIgnoreCase));
                            message.QR    = true;
                            message.AA    = true;
                            message.RA    = false;
                            message.RCode = (byte)RCode.NOERROR;
                            message.AnswerCount++;
                            message.Answers.Add(new ResourceRecord {
                                Name = question.Name, Class = ResourceClass.IN, Type = ResourceType.A, TTL = 86400, RData = new ANameRData {
                                    Address = address.Address
                                }
                            });
                        }
                        // Blacklist Resolution
                        else if (DnsBlacklist.Search(question.Name))
                        {
                            message.QR    = true;
                            message.AA    = true;
                            message.RA    = false;
                            message.RCode = (byte)RCode.NOERROR;
                            message.AnswerCount++;
                            message.Answers.Add(new ResourceRecord {
                                Name = question.Name, Class = ResourceClass.IN, Type = ResourceType.A, TTL = 86400, RData = new ANameRData {
                                    Address = new IPAddress(0)
                                }
                            });
                        }
                        else // Referral to regular DC DNS servers
                        {
                            // store current IP address and Query ID.
                            try
                            {
                                string key = GetKeyName(message);
                                _requestResponseMapLock.EnterWriteLock();
                                _requestResponseMap.Add(key, args.RemoteEndPoint);
                            }
                            finally
                            {
                                _requestResponseMapLock.ExitWriteLock();
                            }
                        }

                        using (MemoryStream responseStream = new MemoryStream(512))
                        {
                            message.WriteToStream(responseStream);
                            if (message.IsQuery())
                            {
                                // Figure out which server to use, local dns servers or remote dns servers
                                var localZoneServer = _dnsConfig.LocalZones.FirstOrDefault(o => question.Name.EndsWith(o.Zone, StringComparison.InvariantCultureIgnoreCase));
                                foreach (IPEndPoint dnsServer in localZoneServer != null ? localZoneServer.Servers : _dnsConfig.DnsServers)
                                {
                                    SendUdp(responseStream.GetBuffer(), 0, (int)responseStream.Position, dnsServer);
                                }
                            }
                            else
                            {
                                Interlocked.Increment(ref _responses);
                                SendUdp(responseStream.GetBuffer(), 0, (int)responseStream.Position, args.RemoteEndPoint);
                            }
                        }
                    }
                }
            }
            else
            {
                // message is response to a delegated query
                string key = GetKeyName(message);
                try
                {
                    _requestResponseMapLock.EnterUpgradeableReadLock();

                    EndPoint ep;
                    if (_requestResponseMap.TryGetValue(key, out ep))
                    {
                        // first test establishes presence
                        try
                        {
                            _requestResponseMapLock.EnterWriteLock();
                            // second test within lock means exclusive access
                            if (_requestResponseMap.TryGetValue(key, out ep))
                            {
                                using (MemoryStream responseStream = new MemoryStream(512))
                                {
                                    message.WriteToStream(responseStream);
                                    Interlocked.Increment(ref _responses);

                                    Logger.Debug("{0} answered {1} {2} {3} to {4}", args.RemoteEndPoint.ToString(), message.Questions[0].Name, message.Questions[0].Class, message.Questions[0].Type, ep.ToString());

                                    SendUdp(responseStream.GetBuffer(), 0, (int)responseStream.Position, ep);
                                }
                                _requestResponseMap.Remove(key);
                            }
                        }
                        finally
                        {
                            _requestResponseMapLock.ExitWriteLock();
                        }
                    }
                    else
                    {
                        Interlocked.Increment(ref _nacks);
                    }
                }
                finally
                {
                    _requestResponseMapLock.ExitUpgradeableReadLock();
                }
            }
        }