예제 #1
0
        public static async Task <SecondaryZone> CreateAsync(DnsServer dnsServer, string name, string primaryNameServerAddresses = null, DnsTransportProtocol zoneTransferProtocol = DnsTransportProtocol.Tcp, string tsigKeyName = null)
        {
            switch (zoneTransferProtocol)
            {
            case DnsTransportProtocol.Tcp:
            case DnsTransportProtocol.Tls:
                break;

            default:
                throw new NotSupportedException("Zone transfer protocol is not supported: XFR-over-" + zoneTransferProtocol.ToString().ToUpper());
            }

            SecondaryZone secondaryZone = new SecondaryZone(dnsServer, name);

            DnsQuestionRecord soaQuestion = new DnsQuestionRecord(name, DnsResourceRecordType.SOA, DnsClass.IN);
            DnsDatagram       soaResponse;

            if (primaryNameServerAddresses == null)
            {
                soaResponse = await secondaryZone._dnsServer.DirectQueryAsync(soaQuestion);
            }
            else
            {
                DnsClient dnsClient = new DnsClient(primaryNameServerAddresses);

                foreach (NameServerAddress nameServerAddress in dnsClient.Servers)
                {
                    if (nameServerAddress.IsIPEndPointStale)
                    {
                        await nameServerAddress.ResolveIPAddressAsync(secondaryZone._dnsServer, secondaryZone._dnsServer.PreferIPv6);
                    }
                }

                dnsClient.Proxy      = secondaryZone._dnsServer.Proxy;
                dnsClient.PreferIPv6 = secondaryZone._dnsServer.PreferIPv6;

                DnsDatagram soaRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { soaQuestion }, null, null, null, DnsDatagram.EDNS_DEFAULT_UDP_PAYLOAD_SIZE);

                if (string.IsNullOrEmpty(tsigKeyName))
                {
                    soaResponse = await dnsClient.ResolveAsync(soaRequest);
                }
                else if ((dnsServer.TsigKeys is not null) && dnsServer.TsigKeys.TryGetValue(tsigKeyName, out TsigKey key))
                {
                    soaResponse = await dnsClient.ResolveAsync(soaRequest, key, REFRESH_TSIG_FUDGE);
                }
예제 #2
0
        private async Task OnDnsQueryReceived(QueryReceivedEventArgs e, IEnumerable <DomainName> domains)
        {
            DnsMessage message = e.Query as DnsMessage;

            if (message == null || message.Questions.Count != 1)
            {
                return;
            }

            DnsQuestion question = message.Questions[0];
            DnsMessage  response = message.CreateResponseInstance();

            //If domain match return localhost
            if ((Program.Options.Ncsi && question.Name.Equals(_ncsiDomain)) || domains.Any(x => x.Equals(question.Name)))
            {
                if (question.RecordType == RecordType.A)
                {
                    response.ReturnCode = ReturnCode.NoError;
                    response.AnswerRecords.Add(new ARecord(question.Name, 10, IPAddress.Loopback));
                }
                else if (question.RecordType == RecordType.Aaaa)
                {
                    response.ReturnCode = ReturnCode.NoError;
                    response.AnswerRecords.Add(new AaaaRecord(question.Name, 10, IPAddress.IPv6Loopback));
                }
            }
            else if (_upStreamDnsClient != null)
            {
                // send query to upstream server
                DnsMessage upstreamResponse = await _upStreamDnsClient.ResolveAsync(question.Name, question.RecordType, question.RecordClass);

                if (upstreamResponse == null)
                {
                    return;
                }

                // if got an answer, copy it to the message sent to the client
                response.AnswerRecords.AddRange(upstreamResponse.AnswerRecords);
                response.AdditionalRecords.AddRange(upstreamResponse.AdditionalRecords);
                response.ReturnCode = upstreamResponse.ReturnCode;
            }


            // set the response
            e.Response = response;

            if (response.AnswerRecords.Count != 0)
            {
                Logging.WriteVerbose("DNS Response: {0}", response.AnswerRecords.FirstOrDefault());
            }
            else
            {
                Logging.WriteVerbose("DNS Response: Can not find {0} records for {1}", question.RecordType.ToString().ToUpperInvariant(), question.Name);
            }
        }
예제 #3
0
        private async Task NotifyNameServerAsync(NameServerAddress nameServer)
        {
            try
            {
                DnsClient client = new DnsClient(nameServer);

                client.Timeout = NOTIFY_TIMEOUT;
                client.Retries = NOTIFY_RETRIES;

                DnsDatagram notifyRequest = new DnsDatagram(0, false, DnsOpcode.Notify, true, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN) }, _entries[DnsResourceRecordType.SOA]);
                DnsDatagram response      = await client.ResolveAsync(notifyRequest);

                switch (response.RCODE)
                {
                case DnsResponseCode.NoError:
                case DnsResponseCode.NotImplemented:
                {
                    //transaction complete
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server successfully notified name server for '" + _name + "' zone changes: " + nameServer.ToString());
                    }
                }
                break;

                default:
                {
                    //transaction failed
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received RCODE=" + response.RCODE.ToString() + " from name server for '" + _name + "' zone notification: " + nameServer.ToString());
                    }
                }
                break;
                }
            }
            catch (Exception ex)
            {
                LogManager log = _dnsServer.LogManager;
                if (log != null)
                {
                    log.Write("DNS Server failed to notify name server for '" + _name + "' zone changes: " + nameServer.ToString());
                    log.Write(ex);
                }
            }
            finally
            {
                lock (_notifyList)
                {
                    _notifyList.Remove(nameServer);
                }
            }
        }
예제 #4
0
        public static async Task <StubZone> CreateAsync(DnsServer dnsServer, string name, string primaryNameServerAddresses = null)
        {
            StubZone stubZone = new StubZone(dnsServer, name);

            DnsQuestionRecord soaQuestion = new DnsQuestionRecord(name, DnsResourceRecordType.SOA, DnsClass.IN);
            DnsDatagram       soaResponse;

            if (primaryNameServerAddresses == null)
            {
                soaResponse = await stubZone._dnsServer.DirectQueryAsync(soaQuestion);
            }
            else
            {
                DnsClient dnsClient = new DnsClient(primaryNameServerAddresses);

                foreach (NameServerAddress nameServerAddress in dnsClient.Servers)
                {
                    if (nameServerAddress.IsIPEndPointStale)
                    {
                        await nameServerAddress.ResolveIPAddressAsync(stubZone._dnsServer, stubZone._dnsServer.PreferIPv6);
                    }
                }

                dnsClient.Proxy      = stubZone._dnsServer.Proxy;
                dnsClient.PreferIPv6 = stubZone._dnsServer.PreferIPv6;

                DnsDatagram soaRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { soaQuestion }, null, null, null, DnsDatagram.EDNS_DEFAULT_UDP_PAYLOAD_SIZE);

                soaResponse = await dnsClient.ResolveAsync(soaRequest);
            }

            if ((soaResponse.Answer.Count == 0) || (soaResponse.Answer[0].Type != DnsResourceRecordType.SOA))
            {
                throw new DnsServerException("DNS Server failed to find SOA record for: " + name);
            }

            DnsSOARecordData receivedSoa = soaResponse.Answer[0].RDATA as DnsSOARecordData;

            DnsSOARecordData soa = new DnsSOARecordData(receivedSoa.PrimaryNameServer, receivedSoa.ResponsiblePerson, 0u, receivedSoa.Refresh, receivedSoa.Retry, receivedSoa.Expire, receivedSoa.Minimum);

            DnsResourceRecord[] soaRR = new DnsResourceRecord[] { new DnsResourceRecord(stubZone._name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) };

            if (!string.IsNullOrEmpty(primaryNameServerAddresses))
            {
                soaRR[0].SetPrimaryNameServers(primaryNameServerAddresses);
            }

            stubZone._entries[DnsResourceRecordType.SOA] = soaRR;

            stubZone._isExpired    = true; //new stub zone is considered expired till it refreshes
            stubZone._refreshTimer = new Timer(stubZone.RefreshTimerCallback, null, Timeout.Infinite, Timeout.Infinite);

            return(stubZone);
        }
예제 #5
0
        static async Task OnQueryReceived(object sender, QueryReceivedEventArgs e)
        {
            DnsMessage query = e.Query as DnsMessage;

            if (query == null)
            {
                return;
            }

            DnsMessage response = query.CreateResponseInstance();

            foreach (var question in query.Questions)
            {
                //Console.WriteLine(question.Name.ToString());

                DnsMessage upstreamResponse;
                Boolean    useDefault = true;

                foreach (var domain in domains)
                {
                    if (question.Name.ToString().ToLower().Contains(domain))
                    {
                        useDefault = false;
                    }
                }

                if (useDefault)
                {
                    upstreamResponse = await defaultClient.ResolveAsync(question.Name, question.RecordType, question.RecordClass);
                }
                else
                {
                    upstreamResponse = await netflixClient.ResolveAsync(question.Name, question.RecordType, question.RecordClass);
                }

                if (upstreamResponse != null)
                {
                    foreach (DnsRecordBase record in (upstreamResponse.AnswerRecords))
                    {
                        response.AnswerRecords.Add(record);
                    }
                    foreach (DnsRecordBase record in (upstreamResponse.AdditionalRecords))
                    {
                        response.AdditionalRecords.Add(record);
                    }

                    response.ReturnCode = ReturnCode.NoError;

                    e.Response = response;
                }
            }
        }
        public async Task ManualTest()
        {
            var testClient = new DnsClient(IPAddress.Parse("100.84.16.18"), 10);

            using var cancelSource = new CancellationTokenSource();

            var token = cancelSource.Token;

            cancelSource.CancelAfter(4000);

            var result = await testClient.ResolveAsync(DomainName.Parse("4yw3dw.id.enclave"));

            Assert.True(result.AnswerRecords.Any(x => x is ARecord arec && arec.Address.Equals(IPAddress.Parse("100.119.20.243"))));
        }
예제 #7
0
        public override async Task <List <DnsRecordBase> > ResolveAsync(DnsQuestion dnsQuestion,
                                                                        CancellationToken cancellationToken)
        {
            using (DnsContextAccessor.DnsContext.Logger.BeginScope($"{StrategyName} =>"))
            {
                var stopwatch = new Stopwatch();
                LogDnsQuestion(dnsQuestion, stopwatch);
                var result = new List <DnsRecordBase>();

                try
                {
                    var dnsClient = new DnsClient(Rule.NameServerIpAddresses, Rule.QueryTimeout);

                    var response = await dnsClient.ResolveAsync(dnsQuestion.Name, dnsQuestion.RecordType,
                                                                dnsQuestion.RecordClass, null, cancellationToken)
                                   .ConfigureAwait(false);

                    result.AddRange(response.AnswerRecords);
                    dnsClient = null;
                }
                catch (NullReferenceException nre)
                {
                    throw new DnsServerException($"The DNS Result is Empty! Check the DNS Server IpAddresses! [{stopwatch.ElapsedMilliseconds} ms]", nre);
                }
                catch (OperationCanceledException operationCanceledException)
                {
                    LogDnsCanncelQuestion(dnsQuestion, operationCanceledException, stopwatch);
                }
                catch (Exception e)
                {
                    DnsContextAccessor.DnsContext.Logger.LogError(e, e.Message);
                    throw;
                }

                if (result.Any())
                {
                    var ttl = result.First().TimeToLive;
                    if (ttl <= CacheConfigOptionsMonitor.CurrentValue.MinimalTimeToLiveInSeconds)
                    {
                        ttl = CacheConfigOptionsMonitor.CurrentValue.MinimalTimeToLiveInSeconds;
                    }

                    StoreInCache(dnsQuestion, result, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromSeconds(ttl)));
                }

                LogDnsQuestionAndResult(dnsQuestion, result, stopwatch);
                return(result);
            }
        }
예제 #8
0
        public static async Task <SecondaryZone> CreateAsync(DnsServer dnsServer, string name, string primaryNameServerAddresses = null, DnsTransportProtocol zoneTransferProtocol = DnsTransportProtocol.Tcp, string tsigKeyName = null)
        {
            switch (zoneTransferProtocol)
            {
            case DnsTransportProtocol.Tcp:
            case DnsTransportProtocol.Tls:
                break;

            default:
                throw new NotSupportedException("Zone transfer protocol is not supported: XFR-over-" + zoneTransferProtocol.ToString().ToUpper());
            }

            SecondaryZone secondaryZone = new SecondaryZone(dnsServer, name);

            DnsQuestionRecord soaQuestion = new DnsQuestionRecord(name, DnsResourceRecordType.SOA, DnsClass.IN);
            DnsDatagram       soaResponse;

            if (primaryNameServerAddresses == null)
            {
                soaResponse = await secondaryZone._dnsServer.DirectQueryAsync(soaQuestion).WithTimeout(2000);
            }
            else
            {
                DnsClient dnsClient = new DnsClient(primaryNameServerAddresses);

                dnsClient.Proxy      = secondaryZone._dnsServer.Proxy;
                dnsClient.PreferIPv6 = secondaryZone._dnsServer.PreferIPv6;

                if (string.IsNullOrEmpty(tsigKeyName))
                {
                    soaResponse = await dnsClient.ResolveAsync(soaQuestion);
                }
                else if ((dnsServer.TsigKeys is not null) && dnsServer.TsigKeys.TryGetValue(tsigKeyName, out TsigKey key))
                {
                    soaResponse = await dnsClient.ResolveAsync(soaQuestion, key, REFRESH_TSIG_FUDGE);
                }
예제 #9
0
        public static async Task <StubZone> CreateAsync(DnsServer dnsServer, string name, string primaryNameServerAddresses = null)
        {
            StubZone stubZone = new StubZone(name);

            stubZone._dnsServer = dnsServer;

            DnsQuestionRecord soaQuestion = new DnsQuestionRecord(name, DnsResourceRecordType.SOA, DnsClass.IN);
            DnsDatagram       soaResponse = null;

            if (primaryNameServerAddresses == null)
            {
                soaResponse = await stubZone._dnsServer.DirectQueryAsync(soaQuestion);
            }
            else
            {
                DnsClient dnsClient = new DnsClient(primaryNameServerAddresses);

                dnsClient.Proxy      = stubZone._dnsServer.Proxy;
                dnsClient.PreferIPv6 = stubZone._dnsServer.PreferIPv6;

                soaResponse = await dnsClient.ResolveAsync(soaQuestion);
            }

            if ((soaResponse == null) || (soaResponse.Answer.Count == 0) || (soaResponse.Answer[0].Type != DnsResourceRecordType.SOA))
            {
                throw new DnsServerException("DNS Server failed to find SOA record for: " + name);
            }

            DnsSOARecord receivedSoa = soaResponse.Answer[0].RDATA as DnsSOARecord;

            DnsSOARecord soa = new DnsSOARecord(receivedSoa.PrimaryNameServer, receivedSoa.ResponsiblePerson, receivedSoa.Serial - 1, receivedSoa.Refresh, receivedSoa.Retry, receivedSoa.Expire, receivedSoa.Minimum);

            DnsResourceRecord[] soaRR = new DnsResourceRecord[] { new DnsResourceRecord(stubZone._name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) };

            if (!string.IsNullOrEmpty(primaryNameServerAddresses))
            {
                soaRR[0].SetGlueRecords(primaryNameServerAddresses);
            }

            stubZone._entries[DnsResourceRecordType.SOA] = soaRR;

            stubZone._isExpired    = true; //new stub zone is considered expired till it refreshes
            stubZone._refreshTimer = new Timer(stubZone.RefreshTimerCallback, null, Timeout.Infinite, Timeout.Infinite);

            return(stubZone);
        }
예제 #10
0
        static async Task OnQueryReceived(object sender, QueryReceivedEventArgs e)
        {
            DnsMessage query = e.Query as DnsMessage;

            LogToThreadLockedConsole(string.Format("--> DNS query recieved from {0} for {1} (Type: {2})",
                                                   e.RemoteEndpoint,
                                                   query.Questions[0].Name,
                                                   query.Questions[0].RecordType),
                                     ConsoleColor.Green, true);

            if (query == null)
            {
                return;
            }

            DnsMessage  response = query.CreateResponseInstance();
            DnsQuestion question = response.Questions[0];

            if (IsAllowed(question.Name.ToString()))
            {
                DnsClient  client           = new DnsClient(IPAddress.Parse("208.67.222.222"), 5000); // This is the IP for OpenDNS
                DnsMessage upstreamResponse = await client.ResolveAsync(question.Name, question.RecordType, question.RecordClass);

                List <string> recordsRecieved = new List <string>();

                foreach (DnsRecordBase record in upstreamResponse.AnswerRecords)
                {
                    response.AnswerRecords.Add(record);

                    if (!recordsRecieved.Contains(record.Name.ToString() + "|" + record.RecordType.ToString() + "|" + record.RecordType.ToString()))
                    {
                        if (record.RecordType.ToString().ToUpper() != "OPT")
                        {
                            LogToThreadLockedConsole(string.Format("<-- Response from upstream: {0} (Type: {1})", record.Name, record.RecordType), ConsoleColor.Gray, true);
                            recordsRecieved.Add(record.Name.ToString() + "|" + record.RecordType.ToString() + "|" + record.RecordType.ToString());
                        }
                    }
                }
            }

            response.ReturnCode = ReturnCode.NoError;
            e.Response          = response;
        }
예제 #11
0
        static async Task <IPAddress> DnsResolverAsync(DnsClient dnsClient, string domain)
        {
            var dnsMessage = await dnsClient.ResolveAsync(DomainName.Parse(domain));

            if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
            {
                return(null);
            }

            if (dnsMessage != null)
            {
                foreach (var dnsRecord in dnsMessage.AnswerRecords)
                {
                    var aRecord = dnsRecord as ARecord;
                    if (aRecord == null)
                    {
                        continue;
                    }
                    return(aRecord.Address);
                }
            }
            return(null);
        }
예제 #12
0
        private static async Task Server_QueryReceived(object sender, QueryReceivedEventArgs eventArgs)
        {
            DnsMessage query = eventArgs.Query as DnsMessage;

            if (query != null)
            {
                DnsMessage response = query.CreateResponseInstance();
                if ((query.Questions.Count == 1))
                {
                    DnsQuestion question = query.Questions[0];
                    System.Diagnostics.Trace.WriteLine(question.Name.ToString());
                    //DnsMessage upstreamResponse = await DnsClient.Default.ResolveAsync(question.Name, question.RecordType, question.RecordClass);
                    DnsClient  dc = new DnsClient(IPAddress.Parse("192.168.1.254"), 5000);
                    DnsMessage upstreamResponse = await dc.ResolveAsync(question.Name, question.RecordType, question.RecordClass);

                    if (upstreamResponse != null)
                    {
                        foreach (DnsRecordBase record in (upstreamResponse.AnswerRecords))
                        {
                            response.AnswerRecords.Add(record);
                        }
                        foreach (DnsRecordBase record in (upstreamResponse.AdditionalRecords))
                        {
                            response.AdditionalRecords.Add(record);
                        }

                        response.ReturnCode = ReturnCode.NoError;

                        // set the response
                        eventArgs.Response = response;
                    }
                }
            }

            //await Task.Delay(1000);
        }
예제 #13
0
        private void CreateSets(IpTablesDetails config, RuleBuilder rb)
        {
            foreach (var set in config.Sets)
            {
                var      ipset    = new IpSetSet(IpSetTypeHelper.StringToType(set.Type), set.Name, 0, set.Family, _iptables, IpSetSyncMode.SetAndEntries);
                String[] resolved = set.Entries.ToArray();

                if (ipset.Type == IpSetType.HashIp)
                {
                    IPAddress ip;
                    int       retries = 0;
                    do
                    {
                        List <Task> tasks = new List <Task>();
                        for (int index = 0; index < resolved.Length; index++)
                        {
                            var entry = resolved[index];

                            String entryIp = rb.Format(entry);
                            if (!IPAddress.TryParse(entryIp, out ip))
                            {
                                DomainName domain;
                                if (!DomainName.TryParse(entryIp, out domain))
                                {
                                    throw new Exception("Unable to parse domain " + entryIp);
                                }
                                var asyncResult = _dns.ResolveAsync(domain).ContinueWith(CompleteLambda(index, resolved));
                                tasks.Add(asyncResult);
                            }
                        }

                        if (tasks.Any())
                        {
                            Task.WaitAll(tasks.ToArray());
                        }
                    } while (++retries <= 3 && resolved.Any((entry) => !IPAddress.TryParse(rb.Format(entry), out ip)));
                    for (int index = 0; index < resolved.Length; index++)
                    {
                        var entry = resolved[index];

                        String entryIp = rb.Format(entry);
                        if (!IPAddress.TryParse(entryIp, out ip))
                        {
                            throw new Exception("Unable to resolve " + entryIp);
                        }
                    }
                }

                //Check Uniqueness
                HashSet <IpSetEntry> ipsetEntries = new HashSet <IpSetEntry>();

                for (int index = 0; index < resolved.Length; index++)
                {
                    var    entry    = resolved[index];
                    String entryIp  = rb.Format(entry);
                    var    setEntry = IpSetEntry.ParseFromParts(ipset, entryIp);
                    if (ipsetEntries.Add(setEntry))
                    {
                        ipset.Entries.Add(setEntry);
                    }
                }
                _sets.AddSet(ipset);
            }

            //Add new sets (dont delete!)
            _sets.Sync((a) => false);
        }
예제 #14
0
        private async Task <bool> RefreshZoneAsync(IReadOnlyList <NameServerAddress> primaryNameServers)
        {
            try
            {
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server has started zone refresh for stub zone: " + _name);
                    }
                }

                DnsClient client = new DnsClient(primaryNameServers);
                client.Timeout = REFRESH_TIMEOUT;
                client.Retries = REFRESH_RETRIES;

                DnsDatagram soaRequest  = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN) });
                DnsDatagram soaResponse = await client.ResolveAsync(soaRequest);

                if (soaResponse.RCODE != DnsResponseCode.NoError)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received RCODE=" + soaResponse.RCODE.ToString() + " for '" + _name + "' stub zone refresh from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                if (soaResponse.Answer.Count < 1)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received an empty response for SOA query for '" + _name + "' stub zone refresh from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                DnsSOARecord currentSoaRecord  = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                DnsSOARecord receivedSoaRecord = soaResponse.Answer[0].RDATA as DnsSOARecord;

                //compare using sequence space arithmetic
                if (!currentSoaRecord.IsZoneUpdateAvailable(receivedSoaRecord))
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server successfully checked for update to '" + _name + "' stub zone from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(true);
                }

                //update available; do zone sync with TCP transport
                List <NameServerAddress> tcpNameServers = new List <NameServerAddress>();

                foreach (NameServerAddress nameServer in primaryNameServers)
                {
                    tcpNameServers.Add(new NameServerAddress(nameServer, DnsTransportProtocol.Tcp));
                }

                primaryNameServers = tcpNameServers;
                client             = new DnsClient(primaryNameServers);
                client.Timeout     = REFRESH_TIMEOUT;
                client.Retries     = REFRESH_RETRIES;

                DnsDatagram nsRequest  = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.NS, DnsClass.IN) });
                DnsDatagram nsResponse = await client.ResolveAsync(nsRequest);

                if (nsResponse.RCODE != DnsResponseCode.NoError)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received RCODE=" + nsResponse.RCODE.ToString() + " for '" + _name + "' stub zone refresh from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                if (nsResponse.Answer.Count < 1)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received an empty response for NS query for '" + _name + "' stub zone from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                List <DnsResourceRecord> allRecords = new List <DnsResourceRecord>();

                allRecords.AddRange(nsResponse.Answer);
                allRecords.AddRange(soaResponse.Answer); //to sync latest SOA record

                _dnsServer.AuthZoneManager.SyncRecords(_name, allRecords, nsResponse.Additional, true);

                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server successfully refreshed '" + _name + "' stub zone from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                LogManager log = _dnsServer.LogManager;
                if (log != null)
                {
                    string strNameServers = null;

                    foreach (NameServerAddress nameServer in primaryNameServers)
                    {
                        if (strNameServers == null)
                        {
                            strNameServers = nameServer.ToString();
                        }
                        else
                        {
                            strNameServers += ", " + nameServer.ToString();
                        }
                    }

                    log.Write("DNS Server failed to refresh '" + _name + "' stub zone from: " + strNameServers);
                    log.Write(ex);
                }

                return(false);
            }
        }
예제 #15
0
        private async Task <DnsMessage> umleitung_process_request(DnsMessage query)
        {
            DnsMessage upstreamResponse;
            DnsMessage response  = query.CreateResponseInstance();
            DomainName queryhost = DomainName.Parse(query.Questions[0].Name.ToString());

            if ((query.Questions.Count == 1))
            {
                m_log.WriteLine("[+] Processing " + query.Questions[0].RecordType + " query for " + queryhost);

                Boolean   match = false;
                IPAddress ip4   = null;
                IPAddress ip6   = null;

                // handle masqueraded entries first
                m_masq_config.DNSMasqEntries.ForEach(h =>
                {
                    if (queryhost.ToString().StartsWith(h.name))
                    {
                        match = true;

                        m_log.WriteLine(2, "[d] Using masquerading rules.");

                        response.ReturnCode = ReturnCode.NoError;

                        if (query.Questions[0].RecordType == RecordType.A)
                        {
                            ip4           = IPAddress.Parse(h.a);
                            ARecord new_a = new ARecord(query.Questions[0].Name, 666, ip4);
                            response.AnswerRecords.Add(new_a);
                        }
                        else if (query.Questions[0].RecordType == RecordType.Aaaa)
                        {
                            ip6 = IPAddress.Parse(h.aaaa);
                            AaaaRecord new_aaaa = new AaaaRecord(query.Questions[0].Name, 666, ip6);
                            response.AnswerRecords.Add(new_aaaa);
                        }
                    }
                });

                if (match)
                {
                    return(response);
                }

                // send query to upstream server
                DnsQuestion question = query.Questions[0];

                if (!m_props.UseCustomDns)
                {
                    m_log.WriteLine(2, "[d] Using system's DNS servers");
                    upstreamResponse = await DnsClient.Default.ResolveAsync(
                        question.Name, question.RecordType, question.RecordClass);
                }
                else
                {
                    m_props.CustomDnsServers.ForEach(d =>
                    {
                        m_log.WriteLine(2, "[d] Using custom DNS servers: " + d.ToString());
                    });

                    DnsClient dnsc = new DnsClient(m_props.CustomDnsServers, 10000);
                    upstreamResponse = await dnsc.ResolveAsync(
                        question.Name, question.RecordType, question.RecordClass);
                }

                // if we got an answer, copy it to the message sent to the client
                if (upstreamResponse != null && upstreamResponse.AnswerRecords.Count > 0)
                {
                    foreach (DnsRecordBase record in (upstreamResponse.AnswerRecords))
                    {
                        response.AnswerRecords.Add(record);
                    }

                    foreach (DnsRecordBase record in (upstreamResponse.AdditionalRecords))
                    {
                        response.AdditionalRecords.Add(record);
                    }
                }
                else
                {
                    // no dns record for queried host
                    if (upstreamResponse == null)
                    {
                        m_log.WriteLine(2, "upstreamResponse == null (timeout?)");
                    }
                }
                response.ReturnCode = ReturnCode.NoError;
            }
            return(response);
        }
예제 #16
0
        private async Task <bool> RefreshZoneAsync(IReadOnlyList <NameServerAddress> nameServers)
        {
            try
            {
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server has started zone refresh for stub zone: " + (_name == "" ? "<root>" : _name));
                    }
                }

                DnsClient client = new DnsClient(nameServers);

                client.Proxy       = _dnsServer.Proxy;
                client.PreferIPv6  = _dnsServer.PreferIPv6;
                client.Timeout     = REFRESH_TIMEOUT;
                client.Retries     = REFRESH_RETRIES;
                client.Concurrency = 1;

                DnsDatagram soaRequest  = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN) }, null, null, null, DnsDatagram.EDNS_DEFAULT_UDP_PAYLOAD_SIZE);
                DnsDatagram soaResponse = await client.ResolveAsync(soaRequest);

                if (soaResponse.RCODE != DnsResponseCode.NoError)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received RCODE=" + soaResponse.RCODE.ToString() + " for '" + (_name == "" ? "<root>" : _name) + "' stub zone refresh from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                if ((soaResponse.Answer.Count < 1) || (soaResponse.Answer[0].Type != DnsResourceRecordType.SOA) || !_name.Equals(soaResponse.Answer[0].Name, StringComparison.OrdinalIgnoreCase))
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received an empty response for SOA query for '" + (_name == "" ? "<root>" : _name) + "' stub zone refresh from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                DnsResourceRecord currentSoaRecord  = _entries[DnsResourceRecordType.SOA][0];
                DnsResourceRecord receivedSoaRecord = soaResponse.Answer[0];

                DnsSOARecordData currentSoa  = currentSoaRecord.RDATA as DnsSOARecordData;
                DnsSOARecordData receivedSoa = receivedSoaRecord.RDATA as DnsSOARecordData;

                //compare using sequence space arithmetic
                if (!_resync && !currentSoa.IsZoneUpdateAvailable(receivedSoa))
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server successfully checked for '" + (_name == "" ? "<root>" : _name) + "' stub zone update from: " + soaResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(true);
                }

                //update available; do zone sync with TCP transport
                List <NameServerAddress> tcpNameServers = new List <NameServerAddress>();

                foreach (NameServerAddress nameServer in nameServers)
                {
                    tcpNameServers.Add(nameServer.ChangeProtocol(DnsTransportProtocol.Tcp));
                }

                nameServers = tcpNameServers;
                client      = new DnsClient(nameServers);

                client.Proxy       = _dnsServer.Proxy;
                client.PreferIPv6  = _dnsServer.PreferIPv6;
                client.Timeout     = REFRESH_TIMEOUT;
                client.Retries     = REFRESH_RETRIES;
                client.Concurrency = 1;

                DnsDatagram nsRequest  = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.NS, DnsClass.IN) });
                DnsDatagram nsResponse = await client.ResolveAsync(nsRequest);

                if (nsResponse.RCODE != DnsResponseCode.NoError)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received RCODE=" + nsResponse.RCODE.ToString() + " for '" + (_name == "" ? "<root>" : _name) + "' stub zone refresh from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                if (nsResponse.Answer.Count < 1)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server received an empty response for NS query for '" + (_name == "" ? "<root>" : _name) + "' stub zone from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }

                    return(false);
                }

                //prepare sync records
                List <DnsResourceRecord> nsRecords = new List <DnsResourceRecord>(nsResponse.Answer.Count);

                foreach (DnsResourceRecord record in nsResponse.Answer)
                {
                    if ((record.Type == DnsResourceRecordType.NS) && record.Name.Equals(_name, StringComparison.OrdinalIgnoreCase))
                    {
                        record.SyncGlueRecords(nsResponse.Additional);
                        nsRecords.Add(record);
                    }
                }

                receivedSoaRecord.CopyRecordInfoFrom(currentSoaRecord);

                //sync records
                _entries[DnsResourceRecordType.NS]  = nsRecords;
                _entries[DnsResourceRecordType.SOA] = new DnsResourceRecord[] { receivedSoaRecord };

                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server successfully refreshed '" + (_name == "" ? "<root>" : _name) + "' stub zone from: " + nsResponse.Metadata.NameServerAddress.ToString());
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                LogManager log = _dnsServer.LogManager;
                if (log != null)
                {
                    string strNameServers = null;

                    foreach (NameServerAddress nameServer in nameServers)
                    {
                        if (strNameServers == null)
                        {
                            strNameServers = nameServer.ToString();
                        }
                        else
                        {
                            strNameServers += ", " + nameServer.ToString();
                        }
                    }

                    log.Write("DNS Server failed to refresh '" + (_name == "" ? "<root>" : _name) + "' stub zone from: " + strNameServers);
                    log.Write(ex);
                }

                return(false);
            }
        }
예제 #17
0
        public void Configure(IApplicationBuilder app, IHostEnvironment env)
        {
            int staticFilesCachePeriod;

            if (env.IsDevelopment())
            {
                staticFilesCachePeriod = 60;
                app.UseDeveloperExceptionPage();
            }
            else
            {
                staticFilesCachePeriod = 14400;
            }

            app.UseDefaultFiles();
            app.UseStaticFiles(new StaticFileOptions()
            {
                OnPrepareResponse = delegate(StaticFileResponseContext ctx)
                {
                    ctx.Context.Response.Headers.Append("Cache-Control", $"public, max-age={staticFilesCachePeriod}");
                }
            });

            app.Run(async(context) =>
            {
                HttpRequest request   = context.Request;
                HttpResponse response = context.Response;

                if (request.Path == "/api/dnsclient/")
                {
                    try
                    {
                        string server = request.Query["server"];
                        string domain = request.Query["domain"];
                        DnsResourceRecordType type = (DnsResourceRecordType)Enum.Parse(typeof(DnsResourceRecordType), request.Query["type"], true);

                        domain = domain.Trim();

                        if (domain.EndsWith("."))
                        {
                            domain = domain.Substring(0, domain.Length - 1);
                        }

                        bool preferIpv6        = Configuration.GetValue <bool>("PreferIpv6");
                        bool randomizeName     = false;
                        bool qnameMinimization = false;
                        int retries            = Configuration.GetValue <int>("Retries");
                        int timeout            = Configuration.GetValue <int>("Timeout");

                        DnsDatagram dnsResponse;

                        if (server == "recursive-resolver")
                        {
                            DnsQuestionRecord question;

                            if ((type == DnsResourceRecordType.PTR) && IPAddress.TryParse(domain, out IPAddress address))
                            {
                                question = new DnsQuestionRecord(address, DnsClass.IN);
                            }
                            else
                            {
                                question = new DnsQuestionRecord(domain, type, DnsClass.IN);
                            }

                            dnsResponse = await DnsClient.RecursiveResolveAsync(question, null, null, preferIpv6, randomizeName, qnameMinimization, retries, timeout);
                        }
                        else
                        {
                            DnsTransportProtocol protocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), request.Query["protocol"], true);

                            if ((protocol == DnsTransportProtocol.Tls) && !server.Contains(":853"))
                            {
                                server += ":853";
                            }

                            NameServerAddress nameServer = new NameServerAddress(server, protocol);

                            if (nameServer.IPEndPoint == null)
                            {
                                await nameServer.ResolveIPAddressAsync(null, null, preferIpv6);
                            }
                            else if (nameServer.DomainEndPoint == null)
                            {
                                try
                                {
                                    await nameServer.ResolveDomainNameAsync(null, null, preferIpv6);
                                }
                                catch
                                { }
                            }

                            DnsClient dnsClient = new DnsClient(nameServer);

                            dnsClient.PreferIPv6    = preferIpv6;
                            dnsClient.RandomizeName = randomizeName;
                            dnsClient.Retries       = retries;
                            dnsClient.Timeout       = timeout;

                            dnsResponse = await dnsClient.ResolveAsync(domain, type);
                        }

                        string jsonResponse = JsonConvert.SerializeObject(dnsResponse, new StringEnumConverter());

                        response.Headers.Add("Content-Type", "application/json; charset=utf-8");
                        await response.WriteAsync("{\"status\":\"ok\", \"response\":" + jsonResponse + "}");
                    }
                    catch (Exception ex)
                    {
                        string jsonResponse = JsonConvert.SerializeObject(ex);

                        response.Headers.Add("Content-Type", "application/json; charset=utf-8");
                        await response.WriteAsync("{\"status\":\"error\", \"response\":" + jsonResponse + "}");
                    }
                }
            });
        }
예제 #18
0
        private async Task NotifyNameServerAsync(DnsServer dnsServer, string nameServerHost, IReadOnlyList <NameServerAddress> nameServers)
        {
            //use notify list to prevent multiple threads from notifying the same name server
            lock (_notifyList)
            {
                if (_notifyList.Contains(nameServerHost))
                {
                    return; //already notifying the name server in another thread
                }
                _notifyList.Add(nameServerHost);
            }

            try
            {
                DnsClient client = new DnsClient(nameServers);

                client.Proxy   = dnsServer.Proxy;
                client.Timeout = NOTIFY_TIMEOUT;
                client.Retries = NOTIFY_RETRIES;

                DnsDatagram notifyRequest = new DnsDatagram(0, false, DnsOpcode.Notify, true, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN) }, _entries[DnsResourceRecordType.SOA]);
                DnsDatagram response      = await client.ResolveAsync(notifyRequest);

                switch (response.RCODE)
                {
                case DnsResponseCode.NoError:
                case DnsResponseCode.NotImplemented:
                {
                    //transaction complete
                    lock (_notifyFailed)
                    {
                        _notifyFailed.Remove(nameServerHost);
                    }

                    LogManager log = dnsServer.LogManager;
                    if (log is not null)
                    {
                        log.Write("DNS Server successfully notified name server '" + nameServerHost + "' for zone: " + (_name == "" ? "<root>" : _name));
                    }
                }
                break;

                default:
                {
                    //transaction failed
                    lock (_notifyFailed)
                    {
                        if (!_notifyFailed.Contains(nameServerHost))
                        {
                            _notifyFailed.Add(nameServerHost);
                        }
                    }

                    LogManager log = dnsServer.LogManager;
                    if (log is not null)
                    {
                        log.Write("DNS Server failed to notify name server '" + nameServerHost + "' (RCODE=" + response.RCODE.ToString() + ") for zone : " + (_name == "" ? "<root>" : _name));
                    }
                }
                break;
                }
            }
            catch (Exception ex)
            {
                lock (_notifyFailed)
                {
                    if (!_notifyFailed.Contains(nameServerHost))
                    {
                        _notifyFailed.Add(nameServerHost);
                    }
                }

                LogManager log = dnsServer.LogManager;
                if (log is not null)
                {
                    log.Write("DNS Server failed to notify name server '" + nameServerHost + "' for zone: " + (_name == "" ? "<root>" : _name));
                    log.Write(ex);
                }
            }
            finally
            {
                lock (_notifyList)
                {
                    _notifyList.Remove(nameServerHost);
                }
            }
        }
예제 #19
0
파일: Program.cs 프로젝트: ismkdc/OrangeDNS
        static async Task OnQueryReceived(object sender, QueryReceivedEventArgs e)
        {
            DnsMessage message = e.Query as DnsMessage;
            DnsMessage query   = e.Query as DnsMessage;

            if (query == null)
            {
                return;
            }

            DnsMessage response = query.CreateResponseInstance();

            if (e.RemoteEndpoint.Address == null)
            {
                return;
            }
            string ipAdr  = e.RemoteEndpoint.Address.ToString();
            Client client = dc.Clients.SingleOrDefault(c => c.Ip == ipAdr);

            if (client == null)
            {
                dc.Clients.Add(new Client()
                {
                    Ip = ipAdr
                });
                dc.SaveChanges();
            }


            if ((message.Questions.Count == 1))
            {
                DnsQuestion question = message.Questions[0];
                if (client.IsBlocked)
                {
                    dc.Logs.Add(new Log()
                    {
                        ClientIp = ipAdr, Request = question.Name.ToString(), Result = Log.ResultType.success
                    });
                    dc.SaveChanges();
                    return;
                }
                DnsClient  dnsClient        = new DnsClient(IPAddress.Parse(mainDns), 5000);
                DnsMessage upstreamResponse = await dnsClient.ResolveAsync(question.Name, question.RecordType, question.RecordClass);

                if (globalBlock == "1")
                {
                    response.AnswerRecords.AddRange(
                        upstreamResponse.AnswerRecords
                        .Where(w => !(w is ARecord))
                        .Concat(
                            upstreamResponse.AnswerRecords
                            .OfType <ARecord>()
                            .Select(a => new ARecord(a.Name, a.TimeToLive, IPAddress.Parse(globalBlockIp)))
                            )
                        );
                    dc.Logs.Add(new Log()
                    {
                        ClientIp = ipAdr, Request = question.Name.ToString(), Result = Log.ResultType.blocked
                    });
                    dc.SaveChanges();
                }
                else
                {
                    string questionUrl    = question.Name.ToString();
                    Domain questionDomain = domainList.SingleOrDefault(d => questionUrl.Contains(d.Url));
                    if (questionDomain == null)
                    {
                        if (upstreamResponse.AnswerRecords[0] != null)
                        {
                            foreach (DnsRecordBase record in (upstreamResponse.AnswerRecords))
                            {
                                response.AnswerRecords.Add(record);
                            }
                            foreach (DnsRecordBase record in (upstreamResponse.AdditionalRecords))
                            {
                                response.AdditionalRecords.Add(record);
                            }

                            response.ReturnCode = ReturnCode.NoError;
                            dc.Logs.Add(new Log()
                            {
                                ClientIp = ipAdr, Request = question.Name.ToString(), Result = Log.ResultType.success
                            });
                            dc.SaveChanges();
                        }
                    }

                    else
                    {
                        if (questionDomain.Type == Data.DType.blocked)
                        {
                            response.AnswerRecords.AddRange(
                                upstreamResponse.AnswerRecords
                                .Where(w => !(w is ARecord))
                                .Concat(
                                    upstreamResponse.AnswerRecords
                                    .OfType <ARecord>()
                                    .Select(a => new ARecord(a.Name, a.TimeToLive, IPAddress.Parse(globalBlockIp)))
                                    )
                                );
                            dc.Logs.Add(new Log()
                            {
                                ClientIp = ipAdr, Request = question.Name.ToString(), Result = Log.ResultType.blocked
                            });
                            dc.SaveChanges();
                        }
                        else
                        {
                            response.AnswerRecords.AddRange(
                                upstreamResponse.AnswerRecords
                                .Where(w => !(w is ARecord))
                                .Concat(
                                    upstreamResponse.AnswerRecords
                                    .OfType <ARecord>()
                                    .Select(a => new ARecord(a.Name, a.TimeToLive, IPAddress.Parse(questionDomain.ForwardIp)))
                                    )
                                );
                            dc.Logs.Add(new Log()
                            {
                                ClientIp = ipAdr, Request = question.Name.ToString(), Result = Log.ResultType.forward
                            });
                            dc.SaveChanges();
                        }
                    }
                }

                e.Response = response;
            }
        }