public void SetResponse(DnsDatagram response, NameServerAddress server, DnsTransportProtocol protocol) { if (_isZoneTransferRequest) { if (_firstResponse is null) { _firstResponse = response; } else { _lastResponse.NextDatagram = response; } _lastResponse = response; if ((_lastResponse.Answer.Count == 0) || (_lastResponse.Answer[_lastResponse.Answer.Count - 1].Type == DnsResourceRecordType.SOA)) { //found last response _stopwatch.Stop(); _firstResponse.SetMetadata(server, protocol, _stopwatch.Elapsed.TotalMilliseconds); _responseTask.TrySetResult(_firstResponse); } } else { _stopwatch.Stop(); response.SetMetadata(server, protocol, _stopwatch.Elapsed.TotalMilliseconds); _responseTask.TrySetResult(response); } }
public DnsForwarderRecord(DnsTransportProtocol protocol, string forwarder) { _protocol = protocol; _forwarder = forwarder; _nameServer = new NameServerAddress(_forwarder, _protocol); }
public Startup(IConfiguration configuration) { Configuration = configuration; DnsTransportProtocol protocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), Configuration.GetValue <string>("dnsServerProtocol"), true); _dnsServer = new NameServerAddress(Configuration.GetValue <string>("dnsServer"), protocol); _timeout = Configuration.GetValue <int>("dnsTimeout"); _debug = Configuration.GetValue <bool>("debug"); }
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 UdpClientConnection(NameServerAddress server, NetProxy proxy) : base(DnsTransportProtocol.Udp, server, proxy) { if (proxy != null) { if (proxy.Type == NetProxyType.Http) { throw new NotSupportedException("DnsClient cannot use HTTP proxy with UDP protocol."); } } _timeout = 2000; }
private void NotifyNameServer(NameServerAddress nameServer) { //use notify list to prevent multiple threads from notifying the same name server lock (_notifyList) { if (_notifyList.Contains(nameServer)) { return; //already notifying the name server in another thread } _notifyList.Add(nameServer); } _ = NotifyNameServerAsync(nameServer); }
public HttpsClientConnection(NameServerAddress server, NetProxy proxy) : base(DnsTransportProtocol.Https, server, proxy) { if (proxy == null) { _httpClient = new HttpClient(); } else { SocketsHttpHandler handler = new SocketsHttpHandler(); handler.Proxy = proxy; _httpClient = new HttpClient(handler); } _httpClient.DefaultRequestHeaders.Add("accept", "application/dns-message"); _httpClient.DefaultRequestHeaders.Add("host", _server.DnsOverHttpEndPoint.Host + ":" + _server.DnsOverHttpEndPoint.Port); _httpClient.DefaultRequestHeaders.Add("user-agent", "DoH client"); }
/// <summary>开始</summary> /// <returns></returns> public virtual Boolean Start() { if (Active) { return(true); } if (NameServerAddress.IsNullOrEmpty()) { // 获取阿里云ONS的名称服务器地址 var addr = Server; if (!addr.IsNullOrEmpty() && addr.StartsWithIgnoreCase("http")) { var http = new TinyHttpClient(); var html = http.GetStringAsync(addr).Result; if (!html.IsNullOrWhiteSpace()) { NameServerAddress = html.Trim(); } } } var client = new NameClient(ClientId, this) { Name = "Name", Log = Log }; client.Start(); var rs = client.GetRouteInfo(Topic); foreach (var item in rs) { XTrace.WriteLine("发现Broker[{0}]: {1}", item.Name, item.Addresses.Join()); } _NameServer = client; return(Active = true); }
protected override void Parse(Stream s) { int b = s.ReadByte(); if (b < 0) { throw new EndOfStreamException(); } _protocol = (DnsTransportProtocol)b; b = s.ReadByte(); if (b < 0) { throw new EndOfStreamException(); } _forwarder = Encoding.ASCII.GetString(s.ReadBytes(b)); _nameServer = new NameServerAddress(_forwarder, _protocol); }
public DnsResourceRecordInfo(BinaryReader bR, bool isSoa) { byte version = bR.ReadByte(); switch (version) { case 1: _disabled = bR.ReadBoolean(); break; case 2: case 3: case 4: case 5: case 6: case 7: _disabled = bR.ReadBoolean(); if ((version < 5) && isSoa) { //read old glue records as NameServerAddress in case of SOA record int count = bR.ReadByte(); if (count > 0) { NameServerAddress[] primaryNameServers = new NameServerAddress[count]; for (int i = 0; i < primaryNameServers.Length; i++) { DnsResourceRecord glueRecord = new DnsResourceRecord(bR.BaseStream); IPAddress address; switch (glueRecord.Type) { case DnsResourceRecordType.A: address = (glueRecord.RDATA as DnsARecordData).Address; break; case DnsResourceRecordType.AAAA: address = (glueRecord.RDATA as DnsAAAARecordData).Address; break; default: continue; } primaryNameServers[i] = new NameServerAddress(address); } _primaryNameServers = primaryNameServers; } } else { int count = bR.ReadByte(); if (count > 0) { DnsResourceRecord[] glueRecords = new DnsResourceRecord[count]; for (int i = 0; i < glueRecords.Length; i++) { glueRecords[i] = new DnsResourceRecord(bR.BaseStream); } _glueRecords = glueRecords; } } if (version >= 3) { _comments = bR.ReadShortString(); } if (version >= 4) { _deletedOn = bR.ReadDateTime(); } if (version >= 5) { int count = bR.ReadByte(); if (count > 0) { NameServerAddress[] primaryNameServers = new NameServerAddress[count]; for (int i = 0; i < primaryNameServers.Length; i++) { primaryNameServers[i] = new NameServerAddress(bR); } _primaryNameServers = primaryNameServers; } } if (version >= 7) { _zoneTransferProtocol = (DnsTransportProtocol)bR.ReadByte(); _tsigKeyName = bR.ReadShortString(); } else if (version >= 6) { _zoneTransferProtocol = (DnsTransportProtocol)bR.ReadByte(); _tsigKeyName = bR.ReadShortString(); _ = bR.ReadShortString(); //_tsigSharedSecret (obsolete) _ = bR.ReadShortString(); //_tsigAlgorithm (obsolete) } break; default: throw new InvalidDataException("DnsResourceRecordInfo format version not supported."); } }
public Startup(IConfiguration configuration) { Configuration = configuration; _dnsServer = new NameServerAddress(Configuration.GetValue <string>("DnsServer")); }
protected TcpClientConnection(DnsTransportProtocol protocol, NameServerAddress server, NetProxy proxy) : base(protocol, server, proxy) { }
public TcpClientConnection(NameServerAddress server, NetProxy proxy) : base(DnsTransportProtocol.Tcp, server, proxy) { _timeout = 2000; }
private void NotifyNameServer(NameServerAddress nameServer) { //use notify list to prevent multiple threads from notifying the same name server lock (_notifyList) { if (_notifyList.Contains(nameServer)) { return; //already notifying the name server in another thread } _notifyList.Add(nameServer); } ThreadPool.QueueUserWorkItem(delegate(object state) { 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 = client.Resolve(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 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 + "}"); } } }); }
protected void Page_Load(object sender, EventArgs e) { try { string server = Request.QueryString["server"]; string domain = Request.QueryString["domain"]; DnsResourceRecordType type = (DnsResourceRecordType)Enum.Parse(typeof(DnsResourceRecordType), Request.QueryString["type"]); DnsDatagram dnsResponse; if (server == "root-servers") { dnsResponse = DnsClient.ResolveViaRootNameServers(domain, type, new SimpleDnsCache(), null, PREFER_IPv6, TCP, RETRIES, MAX_STACK_COUNT); } else { NameServerAddress[] nameServers; if (IPAddress.TryParse(server, out IPAddress serverIP)) { string serverDomain = null; try { serverDomain = (new DnsClient() { PreferIPv6 = PREFER_IPv6, Tcp = TCP, Retries = RETRIES }).ResolvePTR(serverIP); } catch { } nameServers = new NameServerAddress[] { new NameServerAddress(serverDomain, serverIP) }; } else { IPAddress[] serverIPs = (new DnsClient() { PreferIPv6 = PREFER_IPv6, Tcp = TCP, Retries = RETRIES }).ResolveIP(server, PREFER_IPv6); nameServers = new NameServerAddress[serverIPs.Length]; for (int i = 0; i < serverIPs.Length; i++) { nameServers[i] = new NameServerAddress(server, serverIPs[i]); } } dnsResponse = (new DnsClient(nameServers) { PreferIPv6 = PREFER_IPv6, Tcp = TCP, Retries = RETRIES }).Resolve(domain, type); } string jsonResponse = JsonConvert.SerializeObject(dnsResponse, new StringEnumConverter()); Response.AddHeader("Content-Type", "application/json; charset=utf-8"); Response.Write("{\"status\":\"ok\", \"response\":" + jsonResponse + "}"); } catch (Exception ex) { string jsonResponse = JsonConvert.SerializeObject(ex); Response.AddHeader("Content-Type", "application/json; charset=utf-8"); Response.Write("{\"status\":\"error\", \"response\":" + jsonResponse + "}"); } }
public HttpsJsonClientConnection(NameServerAddress server, NetProxy proxy) : base(DnsTransportProtocol.HttpsJson, server, proxy) { _timeout = 5000; }
public void Configure(IApplicationBuilder app, IHostingEnvironment 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) => { await Task.Run(() => { 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); if (domain.EndsWith(".")) { domain = domain.Substring(0, domain.Length - 1); } bool preferIpv6 = Configuration.GetValue <bool>("PreferIpv6"); int retries = Configuration.GetValue <int>("Retries"); int timeout = Configuration.GetValue <int>("Timeout"); DnsDatagram dnsResponse; if (server == "recursive-resolver") { bool useTcp = Configuration.GetValue <bool>("UseTcpForRecursion"); DnsQuestionRecord question; if (type == DnsResourceRecordType.PTR) { question = new DnsQuestionRecord(IPAddress.Parse(domain), DnsClass.IN); } else { question = new DnsQuestionRecord(domain, type, DnsClass.IN); } dnsResponse = DnsClient.RecursiveResolve(question, null, null, null, preferIpv6, retries, timeout, useTcp); } else { DnsTransportProtocol protocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), Request.Query["protocol"], true); NameServerAddress nameServer = new NameServerAddress(server); if (nameServer.IPEndPoint == null) { nameServer.ResolveIPAddress(null, null, preferIpv6); } else if (nameServer.DomainEndPoint == null) { try { nameServer.ResolveDomainName(null, null, preferIpv6); } catch { } } DnsClient dnsClient = new DnsClient(nameServer); dnsClient.PreferIPv6 = preferIpv6; dnsClient.Protocol = protocol; dnsClient.Retries = retries; dnsClient.Timeout = timeout; dnsResponse = dnsClient.Resolve(domain, type); if (dnsResponse.Header.Truncation && (dnsClient.Protocol == DnsTransportProtocol.Udp)) { dnsClient.Protocol = DnsTransportProtocol.Tcp; dnsResponse = dnsClient.Resolve(domain, type); } } string jsonResponse = JsonConvert.SerializeObject(dnsResponse, new StringEnumConverter()); Response.Headers.Add("Content-Type", "application/json; charset=utf-8"); Response.WriteAsync("{\"status\":\"ok\", \"response\":" + jsonResponse + "}"); } catch (Exception ex) { string jsonResponse = JsonConvert.SerializeObject(ex); Response.Headers.Add("Content-Type", "application/json; charset=utf-8"); Response.WriteAsync("{\"status\":\"error\", \"response\":" + jsonResponse + "}"); } } }); }); }
protected DnsClientConnection(DnsTransportProtocol protocol, NameServerAddress server, NetProxy proxy) { _protocol = protocol; _server = server; _proxy = proxy; }
public static DnsClientConnection GetConnection(NameServerAddress server, NetProxy proxy) { switch (server.Protocol) { case DnsTransportProtocol.Udp: return(new UdpClientConnection(server, proxy)); case DnsTransportProtocol.Tcp: { ConcurrentDictionary <NetProxy, TcpClientConnection> existingTcpConnection = _existingTcpConnections.GetOrAdd(server, delegate(NameServerAddress nameServer) { return(new ConcurrentDictionary <NetProxy, TcpClientConnection>()); }); NetProxy proxyKey = proxy; if (proxyKey == null) { proxyKey = NetProxy.NONE; } return(existingTcpConnection.GetOrAdd(proxyKey, delegate(NetProxy netProxyKey) { TcpClientConnection connection = new TcpClientConnection(server, proxy); connection.Pooled = true; return connection; })); } case DnsTransportProtocol.Tls: { ConcurrentDictionary <NetProxy, TlsClientConnection> existingTlsConnection = _existingTlsConnections.GetOrAdd(server, delegate(NameServerAddress nameServer) { return(new ConcurrentDictionary <NetProxy, TlsClientConnection>()); }); NetProxy proxyKey = proxy; if (proxyKey == null) { proxyKey = NetProxy.NONE; } return(existingTlsConnection.GetOrAdd(proxyKey, delegate(NetProxy netProxyKey) { TlsClientConnection connection = new TlsClientConnection(server, proxy); connection.Pooled = true; return connection; })); } case DnsTransportProtocol.Https: { ConcurrentDictionary <NetProxy, HttpsClientConnection> existingHttpsConnection = _existingHttpsConnections.GetOrAdd(server, delegate(NameServerAddress nameServer) { return(new ConcurrentDictionary <NetProxy, HttpsClientConnection>()); }); NetProxy proxyKey = proxy; if (proxyKey == null) { proxyKey = NetProxy.NONE; } return(existingHttpsConnection.GetOrAdd(proxyKey, delegate(NetProxy netProxyKey) { HttpsClientConnection connection = new HttpsClientConnection(server, proxy); connection.Pooled = true; return connection; })); } case DnsTransportProtocol.HttpsJson: { ConcurrentDictionary <NetProxy, HttpsJsonClientConnection> existingHttpsJsonConnection = _existingHttpsJsonConnections.GetOrAdd(server, delegate(NameServerAddress nameServer) { return(new ConcurrentDictionary <NetProxy, HttpsJsonClientConnection>()); }); NetProxy proxyKey = proxy; if (proxyKey == null) { proxyKey = NetProxy.NONE; } return(existingHttpsJsonConnection.GetOrAdd(proxyKey, delegate(NetProxy netProxyKey) { HttpsJsonClientConnection connection = new HttpsJsonClientConnection(server, proxy); connection.Pooled = true; return connection; })); } default: throw new NotSupportedException("DnsClient protocol not supported: " + server.Protocol.ToString()); } }
public UdpClientConnection(NameServerAddress server, NetProxy proxy) : base(DnsTransportProtocol.Udp, server, proxy) { }
private DnsDatagram ProcessAuthoritativeQuery(DnsDatagram request, bool isRecursionAllowed) { DnsDatagram response = _authoritativeZoneRoot.Query(request); if (response.Header.RCODE == DnsResponseCode.NoError) { if (response.Answer.Length > 0) { DnsResourceRecordType questionType = request.Question[0].Type; DnsResourceRecord lastRR = response.Answer[response.Answer.Length - 1]; if ((lastRR.Type != questionType) && (lastRR.Type == DnsResourceRecordType.CNAME) && (questionType != DnsResourceRecordType.ANY)) { List <DnsResourceRecord> responseAnswer = new List <DnsResourceRecord>(); responseAnswer.AddRange(response.Answer); DnsDatagram lastResponse; while (true) { DnsDatagram cnameRequest = new DnsDatagram(new DnsHeader(0, false, DnsOpcode.StandardQuery, false, false, request.Header.RecursionDesired, false, false, false, DnsResponseCode.NoError, 1, 0, 0, 0), new DnsQuestionRecord[] { new DnsQuestionRecord((lastRR.RDATA as DnsCNAMERecord).CNAMEDomainName, questionType, DnsClass.IN) }, null, null, null); lastResponse = _authoritativeZoneRoot.Query(cnameRequest); if (lastResponse.Header.RCODE == DnsResponseCode.Refused) { if (!cnameRequest.Header.RecursionDesired || !isRecursionAllowed) { break; } lastResponse = ProcessRecursiveQuery(cnameRequest); } if ((lastResponse.Header.RCODE != DnsResponseCode.NoError) || (lastResponse.Answer.Length == 0)) { break; } responseAnswer.AddRange(lastResponse.Answer); lastRR = lastResponse.Answer[lastResponse.Answer.Length - 1]; if (lastRR.Type != DnsResourceRecordType.CNAME) { break; } } DnsResponseCode rcode; DnsResourceRecord[] authority; DnsResourceRecord[] additional; if (lastResponse.Header.RCODE == DnsResponseCode.Refused) { rcode = DnsResponseCode.NoError; authority = new DnsResourceRecord[] { }; additional = new DnsResourceRecord[] { }; } else { rcode = lastResponse.Header.RCODE; if (lastResponse.Header.AuthoritativeAnswer) { authority = lastResponse.Authority; additional = lastResponse.Additional; } else { if ((lastResponse.Authority.Length > 0) && (lastResponse.Authority[0].Type == DnsResourceRecordType.SOA)) { authority = lastResponse.Authority; } else { authority = new DnsResourceRecord[] { } }; additional = new DnsResourceRecord[] { }; } } return(new DnsDatagram(new DnsHeader(request.Header.Identifier, true, DnsOpcode.StandardQuery, lastResponse.Header.AuthoritativeAnswer, false, request.Header.RecursionDesired, isRecursionAllowed, false, false, rcode, 1, (ushort)responseAnswer.Count, (ushort)authority.Length, (ushort)additional.Length), request.Question, responseAnswer.ToArray(), authority, additional)); } } else if ((response.Authority.Length > 0) && (response.Authority[0].Type == DnsResourceRecordType.NS) && isRecursionAllowed) { if (_forwarders != null) { return(ProcessRecursiveQuery(request)); //do recursive resolution using forwarders } //do recursive resolution using response authority name servers NameServerAddress[] nameServers = NameServerAddress.GetNameServersFromResponse(response, _preferIPv6, false); return(ProcessRecursiveQuery(request, nameServers)); } } return(response); }
public void Init(HttpApplication context) { _dnsServer = new NameServerAddress(Properties.Settings.Default.DnsServer); context.BeginRequest += delegate(object sender, EventArgs e) { HttpRequest Request = context.Request; HttpResponse Response = context.Response; if (Request.Path == "/dns-query") { if (!Request.AcceptTypes.Contains("application/dns-message")) { throw new NotSupportedException("DoH request type not supported."); } try { DnsDatagram request; switch (Request.HttpMethod) { case "GET": string strRequest = Request.QueryString["dns"]; if (string.IsNullOrEmpty(strRequest)) { throw new ArgumentNullException("dns"); } //convert from base64url to base64 strRequest = strRequest.Replace('-', '+'); strRequest = strRequest.Replace('_', '/'); //add padding int x = strRequest.Length % 4; if (x > 0) { strRequest = strRequest.PadRight(strRequest.Length - x + 4, '='); } request = new DnsDatagram(new MemoryStream(Convert.FromBase64String(strRequest))); break; case "POST": if (Request.ContentType != "application/dns-message") { throw new NotSupportedException("DNS request type not supported: " + Request.ContentType); } request = new DnsDatagram(Request.InputStream); break; default: throw new NotSupportedException("DoH request type not supported.");; } DnsClientConnection connection = DnsClientConnection.GetConnection((DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), Properties.Settings.Default.DnsServerProtocol, true), _dnsServer, null); connection.Timeout = Properties.Settings.Default.DnsTimeout; ushort originalRequestId = request.Header.Identifier; DnsDatagram response = connection.Query(request); if (response == null) { Response.StatusCode = (int)HttpStatusCode.GatewayTimeout; Response.Write("<p>DNS query timed out.</p>"); } else { response.Header.SetIdentifier(originalRequestId); //set id since dns connection may change it if 2 clients have same id Response.ContentType = "application/dns-message"; using (MemoryStream mS = new MemoryStream()) { response.WriteTo(mS); mS.WriteTo(Response.OutputStream); } } } catch (Exception ex) { Response.Clear(); Response.StatusCode = (int)HttpStatusCode.InternalServerError; Response.Write("<p>" + ex.ToString() + "</p>"); } } else { Response.StatusCode = (int)HttpStatusCode.NotFound; Response.Write("<h1>404 Not Found</h1>"); } Response.End(); }; }