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)); }
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); } }
/// <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) } }); }
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); }
// 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); } }