Пример #1
0
        private void ConfigureService()
        {
            _masterFile = new MasterFile();
            var soaoptions = new StartOfAuthorityResourceRecord.Options()
            {
                SerialNumber      = GenerateSerialNumber(),
                RefreshInterval   = new TimeSpan(0, 0, _options.Value.RefreshInterval),
                RetryInterval     = new TimeSpan(0, 0, _options.Value.RetryInterval),
                ExpireInterval    = new TimeSpan(0, 0, _options.Value.ExpireInterval),
                MinimumTimeToLive = new TimeSpan(0, 0, _options.Value.MinTTL)
            };
            var domain = new Domain(_options.Value.Domain);
            var soa    = new StartOfAuthorityResourceRecord(
                domain, domain, domain, soaoptions, new TimeSpan(0, 0, _options.Value.TTL));

            _masterFile.Add(soa);
            var record = new IPAddressResourceRecord(
                new Domain(GetRecordFqdn()), IPAddress.Parse(_options.Value.TargetNormal), new TimeSpan(0, 0, _options.Value.RecordTtl));

            _masterFile.Add(record);
            _server            = new DnsServer(_masterFile, _options.Value.Forwarder);
            _server.Listening += ServerListening;
            _server.Responded += ServerResponded;
            _server.Errored   += ServerErrored;
        }
        public Task <IResponse> Resolve(IRequest request)
        {
            IResponse response = Response.FromRequest(request);

            response.AuthorativeServer = true;

            foreach (Question question in response.Questions)
            {
                if (question.Type == RecordType.A)
                {
                    string requestDomain = question.Name.ToString().ToLower();
                    string emailDomain   = GetEmailDomain(requestDomain);

                    RequestReceived?.Invoke(this, new RequestEventArgs(response.Id, requestDomain, emailDomain));

                    if (emailDomain != null)
                    {
                        var(isValid, ttl) = GetEmailDomainState(emailDomain);

                        if (isValid)
                        {
                            var soaRecord = new StartOfAuthorityResourceRecord(_dnsServerDomain, _dnsServerDomain, _responsiblePersonDomain, _serial,
                                                                               TimeSpan.FromDays(2), TimeSpan.FromDays(1), TimeSpan.FromDays(30), ttl, TimeSpan.FromDays(14));

                            response.AuthorityRecords.Add(soaRecord);
                            response.ResponseCode = ResponseCode.NameError;

                            ResponseSent?.Invoke(this, new ResponseEventArgs(response.Id, requestDomain, emailDomain, ResponseResult.Valid, ttl));
                        }
                        else
                        {
                            var record = new IPAddressResourceRecord(question.Name, s_loopbackIpAddress, ttl);
                            response.AnswerRecords.Add(record);

                            ResponseSent?.Invoke(this, new ResponseEventArgs(response.Id, requestDomain, emailDomain, ResponseResult.Invalid, ttl));
                        }
                    }
                    else
                    {
                        // Invalid domain name request, cache for 1000 days
                        var ttl       = TimeSpan.FromDays(1000);
                        var soaRecord = new StartOfAuthorityResourceRecord(question.Name, _dnsServerDomain, _responsiblePersonDomain, _serial,
                                                                           TimeSpan.FromDays(2), TimeSpan.FromDays(1), TimeSpan.FromDays(30), ttl, ttl);

                        response.AuthorityRecords.Add(soaRecord);
                        response.ResponseCode = ResponseCode.FormatError;

                        ResponseSent?.Invoke(this, new ResponseEventArgs(response.Id, requestDomain, emailDomain, ResponseResult.Error, ttl));
                    }
                }
            }

            return(Task.FromResult(response));
        }
Пример #3
0
        public void WhenSave_AndMasterListContainsStartOfAuthorityResourceRecord_ThenEntryIsSaved()
        {
            // Arrange
            var  domain            = new Domain("stratis.test.com");
            var  masterDomain      = new Domain("master.test.com");
            var  responsibleDomain = new Domain("responsible.test.com");
            long serialNumber      = 12121212;
            var  refreshInterval   = new TimeSpan(1111111111);
            var  retryInterval     = new TimeSpan(2222222222);
            var  expireInterval    = new TimeSpan(3333333333);
            var  minimumTimeToLive = new TimeSpan(4444444444);

            var testResourceRecord =
                new StartOfAuthorityResourceRecord(
                    domain,
                    masterDomain,
                    responsibleDomain,
                    serialNumber,
                    refreshInterval,
                    retryInterval,
                    expireInterval,
                    minimumTimeToLive);

            var masterFile = new DnsSeedMasterFile(new List <IResourceRecord> {
                testResourceRecord
            });

            using (var stream = new MemoryStream())
            {
                // Act.
                masterFile.Save(stream);

                // Assert.
                stream.Should().NotBeNull();
                IList <IResourceRecord> resourceRecords = this.ReadResourceRecords(stream);
                resourceRecords.Should().NotBeNull();
                resourceRecords.Should().NotBeNullOrEmpty();

                IList <StartOfAuthorityResourceRecord> startOfAuthorityResourceRecord = resourceRecords.OfType <StartOfAuthorityResourceRecord>().ToList();
                startOfAuthorityResourceRecord.Should().HaveCount(1);
                startOfAuthorityResourceRecord[0].Name.ToString().Should().Be(domain.ToString());
                startOfAuthorityResourceRecord[0].MasterDomainName.ToString().Should().Be(masterDomain.ToString());
                startOfAuthorityResourceRecord[0].ResponsibleDomainName.ToString().Should().Be(responsibleDomain.ToString());
                startOfAuthorityResourceRecord[0].SerialNumber.Should().Be(serialNumber);
                startOfAuthorityResourceRecord[0].RefreshInterval.Should().Be(refreshInterval);
                startOfAuthorityResourceRecord[0].RetryInterval.Should().Be(retryInterval);
                startOfAuthorityResourceRecord[0].ExpireInterval.Should().Be(expireInterval);
                startOfAuthorityResourceRecord[0].MinimumTimeToLive.Should().Be(minimumTimeToLive);
            }
        }
Пример #4
0
 /// <summary>
 /// Writes a <see cref="StartOfAuthorityResourceRecord"/> to JSON.
 /// </summary>
 /// <param name="resourceRecord">The <see cref="StartOfAuthorityResourceRecord"/> to write.</param>
 /// <returns>The written JSON.</returns>
 private JObject WriteStartOfAuthorityResourceRecordJson(StartOfAuthorityResourceRecord resourceRecord, JsonSerializer serializer)
 {
     return(new JObject
     {
         { TypeFieldName, resourceRecord.GetType().Name },
         { NameFieldName, resourceRecord.Name.ToString() },
         { MasterDomainNameFieldName, resourceRecord.MasterDomainName.ToString() },
         { ResponsibleDomainNameFieldName, resourceRecord.ResponsibleDomainName.ToString() },
         { SerialNumberFieldName, resourceRecord.SerialNumber },
         { RefreshIntervalFieldName, JToken.FromObject(resourceRecord.RefreshInterval, serializer) },
         { RetryIntervalFieldName, JToken.FromObject(resourceRecord.RetryInterval, serializer) },
         { ExpireIntervalFieldName, JToken.FromObject(resourceRecord.ExpireInterval, serializer) },
         { MinimumTimeToLiveFieldName, JToken.FromObject(resourceRecord.MinimumTimeToLive, serializer) }
     });
 }
Пример #5
0
        public void WhenLoad_AndStreamContainsStartOfAuthorityResourceRecord_ThenEntryIsPopulated()
        {
            // Arrange
            var  domain            = new Domain("stratis.test.com");
            var  masterDomain      = new Domain("master.test.com");
            var  responsibleDomain = new Domain("responsible.test.com");
            long serialNumber      = 12121212;
            var  refreshInterval   = new TimeSpan(1111111111);
            var  retryInterval     = new TimeSpan(2222222222);
            var  expireInterval    = new TimeSpan(3333333333);
            var  minimumTimeToLive = new TimeSpan(4444444444);

            var testResourceRecord =
                new StartOfAuthorityResourceRecord(
                    domain,
                    masterDomain,
                    responsibleDomain,
                    serialNumber,
                    refreshInterval,
                    retryInterval,
                    expireInterval,
                    minimumTimeToLive);

            var question = new Question(domain, RecordType.SOA);

            // Act.
            IList <IResourceRecord> resourceRecords = this.WhenLoad_AndStreamContainsEntry_ThenEntryIsPopulated(testResourceRecord, question);

            // Assert.
            resourceRecords.Should().NotBeNull();
            resourceRecords.Should().NotBeNullOrEmpty();

            IList <StartOfAuthorityResourceRecord> startOfAuthorityResourceRecord = resourceRecords.OfType <StartOfAuthorityResourceRecord>().ToList();

            startOfAuthorityResourceRecord.Should().HaveCount(1);
            startOfAuthorityResourceRecord[0].Name.ToString().Should().Be(domain.ToString());
            startOfAuthorityResourceRecord[0].MasterDomainName.ToString().Should().Be(masterDomain.ToString());
            startOfAuthorityResourceRecord[0].ResponsibleDomainName.ToString().Should().Be(responsibleDomain.ToString());
            startOfAuthorityResourceRecord[0].SerialNumber.Should().Be(serialNumber);
            startOfAuthorityResourceRecord[0].RefreshInterval.Should().Be(refreshInterval);
            startOfAuthorityResourceRecord[0].RetryInterval.Should().Be(retryInterval);
            startOfAuthorityResourceRecord[0].ExpireInterval.Should().Be(expireInterval);
            startOfAuthorityResourceRecord[0].MinimumTimeToLive.Should().Be(minimumTimeToLive);
        }
Пример #6
0
        // A request resolver that resolves all dns queries to localhost
        public async Task <IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default)
        {
            try
            {
                IResponse response = Response.FromRequest(request);

                foreach (Question question in response.Questions)
                {
                    if (question.Type == RecordType.SOA || question.Type == RecordType.NS)
                    {
                        var record = new StartOfAuthorityResourceRecord(question.Name, _nsDomains[0], _email,
                                                                        _timeStamp, _ttl, _ttl, _ttl, _ttl, _ttl);
                        response.AuthorityRecords.Add(record);

                        if (question.Type == RecordType.NS)
                        {
                            foreach (var t in _nsDomains)
                            {
                                response.AnswerRecords.Add(new NameServerResourceRecord(question.Name, t, _ttl));
                            }
                        }
                    }

                    if (question.Type == RecordType.TXT)
                    {
                        if (!string.IsNullOrEmpty(_txtUrl))
                        {
                            var httpClient = _clientFactory.CreateClient();
                            // var requestMessage = new HttpRequestMessage(HttpMethod.Get, _txtUrl);
                            var txtResponse = await httpClient.GetAsync(_txtUrl, cancellationToken);

                            List <KeyValue> txtValues = null;
                            if (txtResponse.IsSuccessStatusCode)
                            {
                                // var jsonString = await txtResponse.Content.ReadAsStringAsync();
                                txtValues = await JsonSerializer.DeserializeAsync <List <KeyValue> >(await txtResponse.Content.ReadAsStreamAsync(), cancellationToken : cancellationToken);
                            }

                            if (txtValues != null)
                            {
                                foreach (var keyValue in txtValues)
                                {
                                    if (question.Name.ToString().ToLower().EndsWith(keyValue.key))
                                    {
                                        IList <CharacterString> characterStrings = new List <CharacterString> {
                                            new CharacterString(keyValue.value)
                                        };
                                        response.AnswerRecords.Add(new TextResourceRecord(question.Name, characterStrings, _ttl));
                                    }
                                    else
                                    {
                                        response.AnswerRecords.Add(new TextResourceRecord(question.Name, keyValue.key, keyValue.value, _ttl));
                                    }
                                }
                            }
                        }
                    }

                    var name = question.Name.ToString().ToLower().Split('.');

                    //check the base domain is the same.
                    if (name.Length >= _rootDomainComponents.Length && name
                        .Skip(name.Length - _rootDomainComponents.Length).SequenceEqual(_rootDomainComponents))
                    {
                        // match any static A records.
                        var key = string.Join('.', name.Take(name.Length - _rootDomainComponents.Length));
                        if (_ipAddressRecords.TryGetValue(key, out var ipAddress))
                        {
                            response.AnswerRecords.Add(new IPAddressResourceRecord(question.Name, ipAddress, _ttl));
                        }

                        // query the domain to determine ip.  Format 1-2-3-4.hash.dexih.com
                        var domain = question.Name.ToString().Split(".");
                        if (domain.Length == 4)
                        {
                            if (IPAddress.TryParse(domain[0].Replace('-', '.'), out var iPAddress))
                            {
                                var record = new IPAddressResourceRecord(question.Name, iPAddress, _ttl);
                                response.AnswerRecords.Add(record);
                            }
                        }
                    }
                }

                return(response);
            }
            catch (Exception e)
            {
                _logger?.LogError(e, $"The following error was encountered: {e.Message}.");
                var response = new Response {
                    ResponseCode = ResponseCode.NoError
                };
                return(response);
            }
        }