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); }
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); } }
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); } } }
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); }
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")))); }
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); } }
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); }
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); }
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; }
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); }
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); }
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); }
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); } }
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); }
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); } }
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 + "}"); } } }); }
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); } } }
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; } }