Beispiel #1
0
        public PrimaryZone(DnsServer dnsServer, string name, string primaryNameServer, bool @internal)
            : base(name)
        {
            _dnsServer = dnsServer;
            _internal  = @internal;

            if (_internal)
            {
                _zoneTransfer = AuthZoneTransfer.Deny;
                _notify       = AuthZoneNotify.None;
            }
            else
            {
                _zoneTransfer = AuthZoneTransfer.AllowOnlyZoneNameServers;
                _notify       = AuthZoneNotify.ZoneNameServers;

                _notifyTimer = new Timer(NotifyTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
                _notifyList  = new List <NameServerAddress>();
            }

            DnsSOARecord soa = new DnsSOARecord(primaryNameServer, _name.Length == 0 ? "hostadmin" : "hostadmin." + _name, 1, 14400, 3600, 604800, 900);

            _entries[DnsResourceRecordType.SOA] = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) };
            _entries[DnsResourceRecordType.NS]  = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.NS, DnsClass.IN, soa.Refresh, new DnsNSRecord(soa.PrimaryNameServer)) };
        }
Beispiel #2
0
        public async Task <IReadOnlyList <NameServerAddress> > GetSecondaryNameServerAddressesAsync(DnsServer dnsServer)
        {
            List <NameServerAddress> nameServers = new List <NameServerAddress>();

            DnsSOARecord soa = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
            IReadOnlyList <DnsResourceRecord> nsRecords = GetRecords(DnsResourceRecordType.NS); //stub zone has no authority so cant use QueryRecords

            foreach (DnsResourceRecord nsRecord in nsRecords)
            {
                if (nsRecord.IsDisabled())
                {
                    continue;
                }

                string nsDomain = (nsRecord.RDATA as DnsNSRecord).NameServer;

                if (soa.PrimaryNameServer.Equals(nsDomain, StringComparison.OrdinalIgnoreCase))
                {
                    continue; //skip primary name server
                }
                nameServers.AddRange(await GetNameServerAddressesAsync(dnsServer, nsRecord));
            }

            return(nameServers);
        }
Beispiel #3
0
        private void UpdateServerDomain(string serverDomain)
        {
            _soaRecord = new DnsSOARecord(serverDomain, "hostadmin." + serverDomain, 1, 14400, 3600, 604800, 900);
            _nsRecord  = new DnsNSRecord(serverDomain);

            _zoneManager.ServerDomain = serverDomain;
        }
Beispiel #4
0
        public IReadOnlyList <NameServerAddress> GetPrimaryNameServerAddresses(DnsServer dnsServer)
        {
            List <NameServerAddress> nameServers = new List <NameServerAddress>();

            DnsResourceRecord soaRecord = _entries[DnsResourceRecordType.SOA][0];
            DnsSOARecord      soa       = soaRecord.RDATA as DnsSOARecord;
            IReadOnlyList <DnsResourceRecord> nsRecords = GetRecords(DnsResourceRecordType.NS); //stub zone has no authority so cant use QueryRecords

            foreach (DnsResourceRecord nsRecord in nsRecords)
            {
                if (nsRecord.IsDisabled())
                {
                    continue;
                }

                string nsDomain = (nsRecord.RDATA as DnsNSRecord).NameServer;

                if (soa.PrimaryNameServer.Equals(nsDomain, StringComparison.OrdinalIgnoreCase))
                {
                    //found primary NS
                    nameServers.AddRange(GetNameServerAddresses(dnsServer, nsRecord));
                    break;
                }
            }

            foreach (NameServerAddress nameServer in GetNameServerAddresses(dnsServer, soaRecord))
            {
                if (!nameServers.Contains(nameServer))
                {
                    nameServers.Add(nameServer);
                }
            }

            return(nameServers);
        }
Beispiel #5
0
        /// <inheritdoc/>
        public MockDnsZone(MockDnsServer server, string domainName)
            : base(server, domainName)
        {
            if (server == null)
            {
                throw new ArgumentNullException(nameof(server));
            }

            var records = new List <DnsRecord>();

            // add mock SOA record
            var soaRecord = new DnsSOARecord(
                zone: this,
                name: domainName,
                @class: DnsRecordClasses.IN,
                timeToLive: TimeSpan.FromHours(1),
                primaryServer: server.DomainName,
                responsiblePerson: "hostmaster.",
                serial: 1,
                refreshInterval: TimeSpan.FromMinutes(15),
                retryDelay: TimeSpan.FromMinutes(10),
                expireLimit: TimeSpan.FromDays(1),
                minimumTimeToLive: TimeSpan.FromHours(1));

            records.Add(soaRecord);

            // add mock NS record
            var nsRecord = new DnsNSRecord(this, domainName, DnsRecordClasses.IN, TimeSpan.FromHours(1), server.DomainName);

            records.Add(nsRecord);

            this.records = records;
        }
Beispiel #6
0
        internal PrimaryZone(DnsServer dnsServer, string name, DnsSOARecord soa, DnsNSRecord ns)
            : base(name)
        {
            _dnsServer = dnsServer;

            _entries[DnsResourceRecordType.SOA] = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) };
            _entries[DnsResourceRecordType.NS]  = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.NS, DnsClass.IN, soa.Refresh, ns) };

            _notifyTimer = new Timer(NotifyTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
        }
Beispiel #7
0
        internal AuthZoneInfo CreateInternalPrimaryZone(string domain, DnsSOARecord soaRecord, DnsNSRecord ns)
        {
            AuthZone authZone = new PrimaryZone(_dnsServer, domain, soaRecord, ns);

            if (_root.TryAdd(authZone))
            {
                return(new AuthZoneInfo(authZone));
            }

            return(null);
        }
Beispiel #8
0
        internal PrimaryZone(DnsServer dnsServer, string name, DnsSOARecord soa, DnsNSRecord ns)
            : base(name)
        {
            _dnsServer = dnsServer;
            _internal  = true;

            _zoneTransfer = AuthZoneTransfer.Deny;
            _notify       = AuthZoneNotify.None;

            _entries[DnsResourceRecordType.SOA] = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) };
            _entries[DnsResourceRecordType.NS]  = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.NS, DnsClass.IN, soa.Refresh, ns) };
        }
Beispiel #9
0
        public PrimaryZone(DnsServer dnsServer, string name, string primaryNameServer, bool @internal)
            : base(name)
        {
            _dnsServer = dnsServer;
            _internal  = @internal;

            DnsSOARecord soa = new DnsSOARecord(primaryNameServer, "hostadmin." + name, 1, 14400, 3600, 604800, 900);

            _entries[DnsResourceRecordType.SOA] = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) };
            _entries[DnsResourceRecordType.NS]  = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.NS, DnsClass.IN, soa.Refresh, new DnsNSRecord(soa.PrimaryNameServer)) };

            _notifyTimer = new Timer(NotifyTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
        }
Beispiel #10
0
        public Task InitializeAsync(IDnsServer dnsServer, string config)
        {
            _soaRecord = new DnsSOARecord(dnsServer.ServerDomain, "hostadmin." + dnsServer.ServerDomain, 1, 14400, 3600, 604800, 60);

            dynamic jsonConfig = JsonConvert.DeserializeObject(config);

            _enableBlocking         = jsonConfig.enableBlocking.Value;
            _allowTxtBlockingReport = jsonConfig.allowTxtBlockingReport.Value;

            _blockListZone = ReadJsonDomainArray(jsonConfig.blocked);

            return(Task.CompletedTask);
        }
Beispiel #11
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);
        }
Beispiel #12
0
        public SecondaryZone(DnsServer dnsServer, string name, string primaryNameServerAddresses = null)
            : base(name)
        {
            _dnsServer = dnsServer;

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

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

                dnsClient.Proxy      = _dnsServer.Proxy;
                dnsClient.PreferIPv6 = _dnsServer.PreferIPv6;
                dnsClient.Retries    = _dnsServer.Retries;
                dnsClient.Timeout    = _dnsServer.Timeout;

                soaResponse = dnsClient.Resolve(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(_name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) };

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

            _entries[DnsResourceRecordType.SOA] = soaRR;

            _isExpired    = true; //new secondary zone is considered expired till it refreshes
            _refreshTimer = new Timer(RefreshTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
        }
Beispiel #13
0
        protected void CleanupHistory(List <DnsResourceRecord> history)
        {
            DnsSOARecord soa    = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
            DateTime     expiry = DateTime.UtcNow.AddSeconds(-soa.Expire);
            int          index  = 0;

            while (index < history.Count)
            {
                //check difference sequence
                if (history[index].GetDeletedOn() > expiry)
                {
                    break; //found record to keep
                }
                //skip to next difference sequence
                index++;
                int soaCount = 1;

                while (index < history.Count)
                {
                    if (history[index].Type == DnsResourceRecordType.SOA)
                    {
                        soaCount++;

                        if (soaCount == 3)
                        {
                            break;
                        }
                    }

                    index++;
                }
            }

            if (index == history.Count)
            {
                //delete entire history
                history.Clear();
                return;
            }

            //remove expired records
            history.RemoveRange(0, index);
        }
Beispiel #14
0
        public void IncrementSoaSerial()
        {
            DnsResourceRecord record = _entries[DnsResourceRecordType.SOA][0];
            DnsSOARecord      soa    = record.RDATA as DnsSOARecord;

            uint serial = soa.Serial;

            if (serial < uint.MaxValue)
            {
                serial++;
            }
            else
            {
                serial = 0;
            }

            DnsResourceRecord newRecord = new DnsResourceRecord(record.Name, record.Type, record.Class, record.TtlValue, new DnsSOARecord(soa.PrimaryNameServer, soa.ResponsiblePerson, serial, soa.Refresh, soa.Retry, soa.Expire, soa.Minimum))
            {
                Tag = record.Tag
            };

            _entries[DnsResourceRecordType.SOA] = new DnsResourceRecord[] { newRecord };
        }
Beispiel #15
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);
            }
        }
Beispiel #16
0
        private async void RefreshTimerCallback(object state)
        {
            if (_disabled)
            {
                return;
            }

            try
            {
                _isExpired = DateTime.UtcNow > _expiry;

                //get primary name server addresses
                IReadOnlyList <NameServerAddress> primaryNameServers = await GetPrimaryNameServerAddressesAsync(_dnsServer);

                if (primaryNameServers.Count == 0)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server could not find primary name server IP addresses for stub zone: " + _name);
                    }

                    //set timer for retry
                    DnsSOARecord soa1 = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                    _refreshTimer.Change(soa1.Retry * 1000, Timeout.Infinite);
                    return;
                }

                //refresh zone
                if (await RefreshZoneAsync(primaryNameServers))
                {
                    //zone refreshed; set timer for refresh
                    DnsSOARecord latestSoa = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                    _refreshTimer.Change(latestSoa.Refresh * 1000, Timeout.Infinite);

                    _expiry    = DateTime.UtcNow.AddSeconds(latestSoa.Expire);
                    _isExpired = false;
                    _dnsServer.AuthZoneManager.SaveZoneFile(_name);
                    return;
                }

                //no response from any of the name servers; set timer for retry
                DnsSOARecord soa = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                _refreshTimer.Change(soa.Retry * 1000, Timeout.Infinite);
            }
            catch (Exception ex)
            {
                LogManager log = _dnsServer.LogManager;
                if (log != null)
                {
                    log.Write(ex);
                }

                //set timer for retry
                lock (_refreshTimerLock)
                {
                    if (_refreshTimer != null)
                    {
                        DnsSOARecord soa = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                        _refreshTimer.Change(soa.Retry * 1000, Timeout.Infinite);
                    }
                }
            }
        }
Beispiel #17
0
        private void UpdateServerDomain(string serverDomain)
        {
            ThreadPool.QueueUserWorkItem(delegate(object state)
            {
                //update authoritative zone SOA and NS records
                try
                {
                    List <AuthZoneInfo> zones = ListZones();

                    foreach (AuthZoneInfo zone in zones)
                    {
                        if (zone.Type != AuthZoneType.Primary)
                        {
                            continue;
                        }

                        DnsResourceRecord record = zone.GetRecords(DnsResourceRecordType.SOA)[0];
                        DnsSOARecord soa         = record.RDATA as DnsSOARecord;

                        if (soa.PrimaryNameServer.Equals(_serverDomain, StringComparison.OrdinalIgnoreCase))
                        {
                            string responsiblePerson = soa.ResponsiblePerson;
                            if (responsiblePerson.EndsWith(_serverDomain))
                            {
                                responsiblePerson = responsiblePerson.Replace(_serverDomain, serverDomain);
                            }

                            SetRecords(record.Name, record.Type, record.TtlValue, new DnsResourceRecordData[] { new DnsSOARecord(serverDomain, responsiblePerson, soa.Serial, soa.Refresh, soa.Retry, soa.Expire, soa.Minimum) });

                            //update NS records
                            IReadOnlyList <DnsResourceRecord> nsResourceRecords = zone.GetRecords(DnsResourceRecordType.NS);

                            foreach (DnsResourceRecord nsResourceRecord in nsResourceRecords)
                            {
                                if ((nsResourceRecord.RDATA as DnsNSRecord).NameServer.Equals(_serverDomain, StringComparison.OrdinalIgnoreCase))
                                {
                                    UpdateRecord(nsResourceRecord, new DnsResourceRecord(nsResourceRecord.Name, nsResourceRecord.Type, nsResourceRecord.Class, nsResourceRecord.TtlValue, new DnsNSRecord(serverDomain))
                                    {
                                        Tag = nsResourceRecord.Tag
                                    });
                                    break;
                                }
                            }

                            if (zone.Internal)
                            {
                                continue; //dont save internal zones to disk
                            }
                            try
                            {
                                SaveZoneFile(zone.Name);
                            }
                            catch (Exception ex)
                            {
                                LogManager log = _dnsServer.LogManager;
                                if (log != null)
                                {
                                    log.Write(ex);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write(ex);
                    }
                }

                //update server domain
                _serverDomain = serverDomain;
            });
        }
Beispiel #18
0
        private async void RefreshTimerCallback(object state)
        {
            try
            {
                if (_disabled && !_resync)
                {
                    return;
                }

                _isExpired = DateTime.UtcNow > _expiry;

                //get all name server addresses
                IReadOnlyList <NameServerAddress> nameServers = await GetAllNameServerAddressesAsync(_dnsServer);

                if (nameServers.Count == 0)
                {
                    LogManager log = _dnsServer.LogManager;
                    if (log != null)
                    {
                        log.Write("DNS Server could not find name server IP addresses for stub zone: " + (_name == "" ? "<root>" : _name));
                    }

                    //set timer for retry
                    DnsSOARecord soa1 = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                    ResetRefreshTimer(soa1.Retry * 1000);
                    return;
                }

                //refresh zone
                if (await RefreshZoneAsync(nameServers))
                {
                    //zone refreshed; set timer for refresh
                    DnsSOARecord latestSoa = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                    ResetRefreshTimer(latestSoa.Refresh * 1000);

                    _expiry    = DateTime.UtcNow.AddSeconds(latestSoa.Expire);
                    _isExpired = false;
                    _resync    = false;
                    _dnsServer.AuthZoneManager.SaveZoneFile(_name);
                    return;
                }

                //no response from any of the name servers; set timer for retry
                DnsSOARecord soa = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                ResetRefreshTimer(soa.Retry * 1000);
            }
            catch (Exception ex)
            {
                LogManager log = _dnsServer.LogManager;
                if (log != null)
                {
                    log.Write(ex);
                }

                //set timer for retry
                DnsSOARecord soa = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord;
                ResetRefreshTimer(soa.Retry * 1000);
            }
            finally
            {
                _refreshTimerTriggered = false;
            }
        }
Beispiel #19
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) });
                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];

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

                //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))
                    {
                        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);
            }
        }
Beispiel #20
0
        internal void CommitAndIncrementSerial(IReadOnlyList <DnsResourceRecord> deletedRecords = null, IReadOnlyList <DnsResourceRecord> addedRecords = null)
        {
            if (_internal)
            {
                return;
            }

            lock (_history)
            {
                DnsResourceRecord oldSoaRecord = _entries[DnsResourceRecordType.SOA][0];
                DnsResourceRecord newSoaRecord;
                {
                    DnsSOARecord soa = oldSoaRecord.RDATA as DnsSOARecord;

                    uint serial = soa.Serial;
                    if (serial < uint.MaxValue)
                    {
                        serial++;
                    }
                    else
                    {
                        serial = 1;
                    }

                    newSoaRecord = new DnsResourceRecord(oldSoaRecord.Name, oldSoaRecord.Type, oldSoaRecord.Class, oldSoaRecord.TtlValue, new DnsSOARecord(soa.PrimaryNameServer, soa.ResponsiblePerson, serial, soa.Refresh, soa.Retry, soa.Expire, soa.Minimum))
                    {
                        Tag = oldSoaRecord.Tag
                    };
                    oldSoaRecord.Tag = null; //remove RR info from old SOA to allow creating new RR info for it during SetDeletedOn()
                }

                //update SOA
                _entries[DnsResourceRecordType.SOA] = new DnsResourceRecord[] { newSoaRecord };

                //start commit
                oldSoaRecord.SetDeletedOn(DateTime.UtcNow);

                //write removed
                _history.Add(oldSoaRecord);

                if (deletedRecords is not null)
                {
                    foreach (DnsResourceRecord deletedRecord in deletedRecords)
                    {
                        if (deletedRecord.IsDisabled())
                        {
                            continue;
                        }

                        _history.Add(deletedRecord);

                        if (deletedRecord.Type == DnsResourceRecordType.NS)
                        {
                            _history.AddRange(deletedRecord.GetGlueRecords());
                        }
                    }
                }

                //write added
                _history.Add(newSoaRecord);

                if (addedRecords is not null)
                {
                    foreach (DnsResourceRecord addedRecord in addedRecords)
                    {
                        if (addedRecord.IsDisabled())
                        {
                            continue;
                        }

                        _history.Add(addedRecord);

                        if (addedRecord.Type == DnsResourceRecordType.NS)
                        {
                            _history.AddRange(addedRecord.GetGlueRecords());
                        }
                    }
                }

                //end commit

                CleanupHistory(_history);
            }
        }