public async Task InvokeAsync(HttpContext context) { if (context.Request.Path != _middlewareConfig.Path) { await _next(context); return; } if (context.Request.GetTypedHeaders().Accept.All(x => x.MediaType != DnsMessageType)) { context.Response.StatusCode = (int)HttpStatusCode.UnprocessableEntity; return; } var ms = await context.Request.BodyReader.ReadAsync(context.RequestAborted); var buffer = ms.Buffer.ToArray(); var header = DnsByteExtensions.FromBytes <DnsHeader>(buffer); var answer = await _dnsClient.Query(header, context.RequestAborted); context.Response.Headers.Add("Content-Type", new StringValues(DnsMessageType)); await context.Response.BodyWriter.WriteAsync(DnsByteExtensions.ToBytes(answer), context.RequestAborted); }
public void ReadQuery1Packet() { var header = DnsByteExtensions.FromBytes <DnsHeader>(SampleDnsPackets.Query1); Assert.Equal(DnsQueryClass.IN, header.QueryClass); Assert.Equal(DnsQueryType.A, header.QueryType); Assert.Equal("cognito-identity.us-east-1.amazonaws.com", header.Host); Assert.Equal(0, header.AnswerRecordCount); Assert.Equal(0, header.AdditionalRecordCount); Assert.Equal(1, header.QuestionCount); Assert.Equal(0, header.NameServerRecordCount); Assert.False(header.IsQueryResponse); Assert.False(header.Truncation); Assert.False(header.RecursionAvailable); Assert.True(header.RecusionDesired); Assert.Equal(DnsResponseCode.NoError, header.ResponseCode); var header2 = new DnsHeader { Id = header.Id, QueryClass = DnsQueryClass.IN, QueryType = DnsQueryType.A, RecusionDesired = true, Labels = header.Labels, QuestionCount = 1, }; var bytes = DnsByteExtensions.ToBytes(header2).ToArray(); Assert.Equal(SampleDnsPackets.Query1, bytes); }
public async Task <DnsAnswer> Query(DnsHeader query, CancellationToken token) { var raw = DnsByteExtensions.ToBytes(query).ToArray(); var payload = DnsByteExtensions.ToBytes((ushort)raw.Length).Concat(raw).ToArray(); var stream = _socket.GetStream(); await stream.WriteAsync(payload, 0, payload.Length, token); var buffer = new byte[4096]; var receive = await stream.ReadAsync(buffer, 0, buffer.Length, token); stream.Close(); var offset = 0; var responseLength = DnsByteExtensions.ReadUInt16(buffer, ref offset); var response = DnsByteExtensions.ReadBytes(buffer, responseLength, ref offset); if (response.Length != responseLength) { throw new InvalidOperationException(); } return(DnsByteExtensions.FromBytes <DnsAnswer>(response)); }
public void ReadQuery5Packet() { var header = DnsByteExtensions.FromBytes <DnsHeader>(SampleDnsPackets.Query5); Assert.Equal(DnsQueryClass.IN, header.QueryClass); Assert.Equal(DnsQueryType.A, header.QueryType); Assert.Equal("roaming.officeapps.live.com", header.Host); Assert.Equal(0, header.AnswerRecordCount); Assert.Equal(0, header.AdditionalRecordCount); Assert.Equal(1, header.QuestionCount); Assert.Equal(0, header.NameServerRecordCount); }
public void ReadQuery4Packet() { var header = DnsByteExtensions.FromBytes <DnsHeader>(SampleDnsPackets.Query4); Assert.Equal(DnsQueryClass.IN, header.QueryClass); Assert.Equal(DnsQueryType.AAAA, header.QueryType); Assert.Equal("h3.shared.global.fastly.net", header.Host); Assert.Equal(0, header.AnswerRecordCount); Assert.Equal(0, header.AdditionalRecordCount); Assert.Equal(1, header.QuestionCount); Assert.Equal(0, header.NameServerRecordCount); }
public void ReadQuery2Packet() { var header = DnsByteExtensions.FromBytes <DnsHeader>(SampleDnsPackets.Query2); Assert.Equal(DnsQueryClass.IN, header.QueryClass); Assert.Equal(DnsQueryType.A, header.QueryType); Assert.Equal("polling.bbc.co.uk", header.Host); Assert.Equal(0, header.AnswerRecordCount); Assert.Equal(0, header.AdditionalRecordCount); Assert.Equal(1, header.QuestionCount); Assert.Equal(0, header.NameServerRecordCount); }
public void TestDnsHeaderIsQueryResponse() { foreach (var answer in SampleDnsPackets.Answers) { var header = DnsByteExtensions.FromBytes <DnsHeader>(answer); Assert.True(header.IsQueryResponse); } foreach (var query in SampleDnsPackets.Queries) { var header = DnsByteExtensions.FromBytes <DnsHeader>(query); Assert.False(header.IsQueryResponse); } }
public void ReadAnswer4() { var message = DnsByteExtensions.FromBytes <DnsAnswer>(SampleDnsPackets.Answer4); Assert.Equal(DnsQueryClass.IN, message.Header.QueryClass); Assert.Equal(DnsQueryType.A, message.Header.QueryType); Assert.Equal(5, message.Header.AnswerRecordCount); Assert.Equal(0, message.Header.AdditionalRecordCount); Assert.Equal(1, message.Header.QuestionCount); Assert.Equal(5, message.Answers.Count); var record1 = message.Answers[0]; Assert.Equal(DnsQueryType.CNAME, record1.Type); Assert.Equal(DnsQueryClass.IN, record1.Class); Assert.Equal("alanedwardes.testing.alanedwardes.com", record1.Host); Assert.Equal("alanedwardes.com", ((DnsTextResource)record1.Resource).Text); Assert.Equal(TimeSpan.Parse("00:05:00"), record1.TimeToLive); var record2 = message.Answers[1]; Assert.Equal(DnsQueryType.A, record2.Type); Assert.Equal(DnsQueryClass.IN, record2.Class); Assert.Equal(IPAddress.Parse("143.204.191.46"), ((DnsIpAddressResource)record2.Resource).IPAddress); Assert.Equal(TimeSpan.Parse("00:01:00"), record2.TimeToLive); var record3 = message.Answers[2]; Assert.Equal(DnsQueryType.A, record3.Type); Assert.Equal(DnsQueryClass.IN, record3.Class); Assert.Equal("alanedwardes.com", record3.Host); Assert.Equal(IPAddress.Parse("143.204.191.37"), ((DnsIpAddressResource)record3.Resource).IPAddress); Assert.Equal(TimeSpan.Parse("00:01:00"), record3.TimeToLive); var record4 = message.Answers[3]; Assert.Equal(DnsQueryType.A, record4.Type); Assert.Equal(DnsQueryClass.IN, record4.Class); Assert.Equal("alanedwardes.com", record4.Host); Assert.Equal(IPAddress.Parse("143.204.191.71"), ((DnsIpAddressResource)record4.Resource).IPAddress); Assert.Equal(TimeSpan.Parse("00:01:00"), record4.TimeToLive); var record5 = message.Answers[4]; Assert.Equal(DnsQueryType.A, record5.Type); Assert.Equal(DnsQueryClass.IN, record5.Class); Assert.Equal("alanedwardes.com", record5.Host); Assert.Equal(IPAddress.Parse("143.204.191.110"), ((DnsIpAddressResource)record5.Resource).IPAddress); Assert.Equal(TimeSpan.Parse("00:01:00"), record5.TimeToLive); }
/// <inheritdoc/> public async Task <DnsAnswer> Query(DnsHeader query, CancellationToken token) { string cacheKey = GetCacheKey(query); DnsAnswer answer; var cacheEntry = (DnsCacheEntry)_objectCache.Get(cacheKey); if (cacheEntry != null) { _logger.LogTrace("Returned cached DNS result for {Domain} (expires in: {ExpiryTime})", query.Host, cacheEntry.Expires); answer = DnsByteExtensions.FromBytes <DnsAnswer>(cacheEntry.Data); // Replace the ID answer.Header.Id = query.Id; // Adjust the TTLs to be correct foreach (var record in answer.Answers) { record.TimeToLive -= cacheEntry.Age; } return(answer); } answer = await _dnsClient.Query(new DnsHeader { Id = query.Id, Host = query.Host, IsQueryResponse = false, RecusionDesired = query.RecusionDesired, QueryClass = query.QueryClass, QueryType = query.QueryType, QuestionCount = query.QuestionCount }, token); _logger.LogTrace("Returned fresh DNS result for {Domain}", query.Host); if (answer.Answers.Count > 0) { cacheEntry = new DnsCacheEntry(answer); _objectCache.Add(cacheKey, cacheEntry, new CacheItemPolicy { AbsoluteExpiration = cacheEntry.Expiry }); } return(answer); }
/// <inheritdoc/> public async Task <DnsAnswer> Query(DnsHeader query, CancellationToken token) { var raw = DnsByteExtensions.ToBytes(query).ToArray(); var completionSource = _pending.GetOrAdd(ToMessageId(query), key => SendQueryInternal(key, raw, token)); var result = await completionSource.Task; var answer = DnsByteExtensions.FromBytes <DnsAnswer>(result); // Copy the same ID from the request answer.Header.Id = query.Id; return(answer); }
public void ReadAnswer3() { var message = DnsByteExtensions.FromBytes <DnsAnswer>(SampleDnsPackets.Answer3); Assert.Equal(DnsQueryClass.IN, message.Header.QueryClass); Assert.Equal(DnsQueryType.A, message.Header.QueryType); Assert.Equal(1, message.Header.AnswerRecordCount); Assert.Equal(0, message.Header.AdditionalRecordCount); Assert.Equal(1, message.Header.QuestionCount); var record = Assert.Single(message.Answers); Assert.Equal(DnsQueryType.A, record.Type); Assert.Equal(DnsQueryClass.IN, record.Class); Assert.Equal("google.com", record.Host); Assert.Equal(IPAddress.Parse("216.58.210.206"), ((DnsIpAddressResource)record.Resource).IPAddress); Assert.Equal(TimeSpan.Parse("00:04:28"), record.TimeToLive); }
private void Receive(byte[] buffer) { DnsAnswer answer; try { answer = DnsByteExtensions.FromBytes <DnsAnswer>(buffer); } catch (Exception e) { _logger.LogCritical(e, "Received bad DNS response from {0}: {1}", _socket.Client.RemoteEndPoint.ToString(), buffer); return; } if (_pending.TryRemove(ToMessageId(answer.Header), out TaskCompletionSource <byte[]> completionSource)) { completionSource.SetResult(buffer); } }
private async void Respond(UdpReceiveResult query, CancellationToken token) { var stopwatch = Stopwatch.StartNew(); DnsHeader message; try { message = DnsByteExtensions.FromBytes <DnsHeader>(query.Buffer); } catch (Exception e) { _logger.LogCritical(e, "Unable to parse incoming packet: {0}", DnsByteExtensions.ToDebugString(query.Buffer)); return; } DnsAnswer answer; try { answer = await _dnsClient.Query(message, token); } catch (Exception e) { _logger.LogCritical(e, "Unable to resolve {0}", message); return; } var answerBytes = DnsByteExtensions.ToBytes(answer).ToArray(); try { await _listener.SendAsync(answerBytes, answerBytes.Length, query.RemoteEndPoint); } catch (Exception e) { _logger.LogCritical(e, "Unable to send back response to {0}", query.RemoteEndPoint); return; } _logger.LogTrace("Responded to DNS request for {Domain} in {ResponseTime}", message.Host, stopwatch.Elapsed.TotalSeconds); }
public void ReadAnswer1() { var message = DnsByteExtensions.FromBytes <DnsAnswer>(SampleDnsPackets.Answer1); Assert.Equal(DnsQueryClass.IN, message.Header.QueryClass); Assert.Equal(DnsQueryType.PTR, message.Header.QueryType); Assert.Equal("1.0.0.127.in-addr.arpa", message.Header.Host); Assert.Equal(0, message.Header.AnswerRecordCount); Assert.Equal(0, message.Header.AdditionalRecordCount); Assert.Equal(1, message.Header.QuestionCount); Assert.Equal(1, message.Header.NameServerRecordCount); var record = message.Answers.Single(); Assert.Equal(DnsQueryType.SOA, record.Type); Assert.Equal(DnsQueryClass.IN, record.Class); Assert.Equal("in-addr.arpa", record.Host); var soaData = (DnsSoaResource)record.Resource; Assert.Equal("b.in-addr-servers.arpa", soaData.MName); Assert.Equal("nstld.iana.org", soaData.RName); Assert.Equal(TimeSpan.Parse("00:36:32"), record.TimeToLive); }
public void TestReadAnswers(byte[] answerBytes) => DnsByteExtensions.FromBytes <DnsAnswer>(answerBytes);
public void TestDnsHeaderIsNxDomainResponse() { var header = DnsByteExtensions.FromBytes <DnsHeader>(SampleDnsPackets.Answer1); Assert.Equal(DnsResponseCode.NXDomain, header.ResponseCode); }
public void ReadAnswer2() { var message = DnsByteExtensions.FromBytes <DnsAnswer>(SampleDnsPackets.Answer2); Assert.Equal(DnsQueryClass.IN, message.Header.QueryClass); Assert.Equal(DnsQueryType.A, message.Header.QueryType); Assert.Equal("alanedwardes-my.sharepoint.com", message.Header.Host); Assert.Equal(7, message.Header.AnswerRecordCount); Assert.Equal(0, message.Header.AdditionalRecordCount); Assert.Equal(1, message.Header.QuestionCount); Assert.Equal(0, message.Header.NameServerRecordCount); Assert.Equal(7, message.Answers.Count); var record1 = message.Answers[0]; Assert.Equal(DnsQueryType.CNAME, record1.Type); Assert.Equal(DnsQueryClass.IN, record1.Class); Assert.Equal("alanedwardes-my.sharepoint.com", record1.Host); Assert.Equal(TimeSpan.Parse("01:00:00"), record1.TimeToLive); Assert.Equal("alanedwardes.sharepoint.com", ((DnsTextResource)record1.Resource).Text); var record2 = message.Answers[1]; Assert.Equal(DnsQueryType.CNAME, record2.Type); Assert.Equal(DnsQueryClass.IN, record2.Class); Assert.Equal("alanedwardes.sharepoint.com", record2.Host); Assert.Equal(TimeSpan.Parse("01:00:00"), record2.TimeToLive); Assert.Equal("302-ipv4e.clump.dprodmgd104.aa-rt.sharepoint.com", ((DnsTextResource)record2.Resource).Text); var record3 = message.Answers[2]; Assert.Equal(DnsQueryType.CNAME, record3.Type); Assert.Equal(DnsQueryClass.IN, record3.Class); Assert.Equal("302-ipv4e.clump.dprodmgd104.aa-rt.sharepoint.com", record3.Host); Assert.Equal(TimeSpan.Parse("00:00:30"), record3.TimeToLive); Assert.Equal("187170-ipv4e.farm.dprodmgd104.aa-rt.sharepoint.com", ((DnsTextResource)record3.Resource).Text); var record4 = message.Answers[3]; Assert.Equal(DnsQueryType.CNAME, record4.Type); Assert.Equal(DnsQueryClass.IN, record4.Class); Assert.Equal("187170-ipv4e.farm.dprodmgd104.aa-rt.sharepoint.com", record4.Host); Assert.Equal(TimeSpan.Parse("00:01:00"), record4.TimeToLive); Assert.Equal("187170-ipv4e.farm.dprodmgd104.sharepointonline.com.akadns.net", ((DnsTextResource)record4.Resource).Text); var record5 = message.Answers[4]; Assert.Equal(DnsQueryType.CNAME, record5.Type); Assert.Equal(DnsQueryClass.IN, record5.Class); Assert.Equal("187170-ipv4e.farm.dprodmgd104.sharepointonline.com.akadns.net", record5.Host); Assert.Equal(TimeSpan.Parse("00:05:00"), record5.TimeToLive); Assert.Equal("187170-ipv4.farm.dprodmgd104.aa-rt.sharepoint.com.spo-0004.spo-msedge.net", ((DnsTextResource)record5.Resource).Text); var record6 = message.Answers[5]; Assert.Equal(DnsQueryType.CNAME, record6.Type); Assert.Equal(DnsQueryClass.IN, record6.Class); Assert.Equal("187170-ipv4.farm.dprodmgd104.aa-rt.sharepoint.com.spo-0004.spo-msedge.net", record6.Host); Assert.Equal(TimeSpan.Parse("00:04:00"), record6.TimeToLive); var record7 = message.Answers[6]; Assert.Equal(DnsQueryType.A, record7.Type); Assert.Equal(DnsQueryClass.IN, record7.Class); Assert.Equal("spo-0004.spo-msedge.net", record7.Host); Assert.Equal(IPAddress.Parse("13.107.136.9"), ((DnsIpAddressResource)record7.Resource).IPAddress); Assert.Equal(TimeSpan.Parse("00:04:00"), record7.TimeToLive); }
public void TestRoundTripAnswers(byte[] answerBytes) { var answer = DnsByteExtensions.FromBytes <DnsAnswer>(answerBytes); Assert.Equal(answer, DnsByteExtensions.FromBytes <DnsAnswer>(DnsByteExtensions.ToBytes(answer).ToArray())); }
public void TestRoundTripQueries(byte[] queryBytes) { var query = DnsByteExtensions.FromBytes <DnsHeader>(queryBytes); Assert.Equal(query, DnsByteExtensions.FromBytes <DnsHeader>(DnsByteExtensions.ToBytes(query).ToArray())); }
public void TestReadQueries(byte[] queryBytes) => DnsByteExtensions.FromBytes <DnsHeader>(queryBytes);