static void Main(string[] args) { using (var dnsServer = new DnsServer(IPAddress.Any, 10, 10)) { DNSEncoder.Init(); var client = new QuicClient(); var connection = client.Connect("127.0.0.1", 11000); var stream = connection.CreateStream(QuickNet.Utilities.StreamType.ClientBidirectional); async Task OnDnsServerOnQueryReceived(object sender, QueryReceivedEventArgs e) { if (!(e.Query is DnsMessage query)) { return; } await Task.Run(() => { stream.Send(DNSEncoder.Encode(query)); e.Response = DnsMessage.Parse(stream.Receive()); }); } dnsServer.QueryReceived += OnDnsServerOnQueryReceived; dnsServer.Start(); Console.WriteLine(@"-------ARASHI Q DNS------"); Console.WriteLine(@"-------DOTNET ALPHA------"); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(@"ArashiDNS Server Running"); Console.WriteLine(@"Press any key to stop dns server"); Console.WriteLine("------------------------"); Console.ReadLine(); Console.WriteLine("------------------------"); } }
static void Main(string[] args) { DNSEncoder.Init(); var listener = new QuicListener(11000); listener.Start(); while (true) { var client = listener.AcceptQuicClient(); client.OnDataReceived += c => { var msg = c.Data; using (var bgWorker = new BackgroundWorker()) { bgWorker.DoWork += (sender, eventArgs) => { var dnsQMsg = DnsMessage.Parse(msg); var dnsRMsg = new DnsClient(IPAddress.Parse("8.8.8.8"), 1000).SendMessage(dnsQMsg); c.Send(DNSEncoder.Encode(dnsRMsg)); Console.ForegroundColor = ConsoleColor.Cyan; dnsQMsg.Questions.ForEach(o => Console.WriteLine("Qu:" + o)); Console.ForegroundColor = ConsoleColor.Green; dnsRMsg.AnswerRecords.ForEach(o => Console.WriteLine("An:" + o)); Console.ForegroundColor = ConsoleColor.DarkGreen; dnsRMsg.AuthorityRecords.ForEach(o => Console.WriteLine("Au:" + o)); Console.ForegroundColor = ConsoleColor.Green; }; bgWorker.RunWorkerAsync(); } }; } }
public static (List <DnsRecordBase> list, ReturnCode statusCode) ResolveOverHttpsByDnsMsg(string clientIpAddress, string domainName, string dohUrl, bool proxyEnable = false, IWebProxy wProxy = null, RecordType type = RecordType.A) { DnsMessage dnsMsg; var dnsBase64String = Convert.ToBase64String(MyDnsSend.GetQuestionData(domainName.TrimEnd('.'), type)).TrimEnd('=') .Replace('+', '-').Replace('/', '_'); try { var dnsDataBytes = MyCurl.GetData( $"{dohUrl}?ct=application/dns-message&dns={dnsBase64String}", DnsSettings.Http2Enable, proxyEnable, wProxy, DnsSettings.AllowAutoRedirect); dnsMsg = DnsMessage.Parse(dnsDataBytes); if (DnsSettings.Ipv4Disable || DnsSettings.Ipv6Disable) { foreach (var item in dnsMsg.AnswerRecords.ToArray()) { if (item.RecordType == RecordType.A && DnsSettings.Ipv4Disable) { dnsMsg.AnswerRecords.Remove(item); } if (item.RecordType == RecordType.Aaaa && DnsSettings.Ipv6Disable) { dnsMsg.AnswerRecords.Remove(item); } } } } catch (WebException e) { HttpWebResponse response = (HttpWebResponse)e.Response; try { BackgroundLog( $@"| - Catch WebException : {Convert.ToInt32(response.StatusCode)} {response.StatusCode} | {domainName} | {dohUrl} | {dnsBase64String}"); if (response.StatusCode == HttpStatusCode.BadRequest) { DnsSettings.DnsMsgEnable = false; return(ResolveOverHttpsByDnsJson(clientIpAddress, domainName, DnsSettings.SecondHttpsDnsUrl, proxyEnable, wProxy, type)); } } catch (Exception exception) { BackgroundLog( $@"| - Catch WebException : {exception.Message} | {domainName} | {dohUrl} | {dnsBase64String}"); } if (dohUrl != DnsSettings.HttpsDnsUrl) { return(new List <DnsRecordBase>(), ReturnCode.ServerFailure); } BackgroundLog($@"| -- SecondDoH : {DnsSettings.SecondHttpsDnsUrl}"); return(ResolveOverHttpsByDnsMsg(clientIpAddress, domainName, DnsSettings.SecondHttpsDnsUrl, proxyEnable, wProxy, type)); } return(dnsMsg.AnswerRecords, dnsMsg.ReturnCode); }
public static void DnsQueryRoute(IEndpointRouteBuilder endpoints) { endpoints.Map(Config.QueryPerfix, async context => { var queryDictionary = context.Request.Query; if (context.Request.Method == "POST") { await ReturnContext(context, true, DnsQuery(DnsMessage.Parse((await context.Request.BodyReader.ReadAsync()).Buffer.ToArray()), context)); } else if (queryDictionary.ContainsKey("dns")) { await ReturnContext(context, true, DnsQuery(DNSGet.FromWebBase64(context), context)); } else if (queryDictionary.ContainsKey("name")) { await ReturnContext(context, false, DnsQuery(DNSGet.FromQueryContext(context, EcsDefaultMask: Config.EcsDefaultMask), context)); } else { await context.WriteResponseAsync(Startup.IndexStr, type: "text/html"); } }); }
private static (List <DnsRecordBase> list, ReturnCode statusCode) ResolveOverHttpsByDnsMsg(string clientIpAddress, string domainName, string dohUrl, bool proxyEnable = false, IWebProxy wProxy = null, RecordType type = RecordType.A) { DnsMessage dnsMsg; MWebClient mWebClient = new MWebClient { Headers = { ["User-Agent"] = "AuroraDNSC/0.1" } }; if (proxyEnable) { mWebClient.Proxy = wProxy; } var dnsBase64String = Convert.ToBase64String(MyDnsSend.GetQuestionData(domainName.TrimEnd('.'), type)).TrimEnd('=') .Replace('+', '-').Replace('/', '_'); try { var dnsDataBytes = mWebClient.DownloadData( $"{dohUrl}?ct=application/dns-message&dns={dnsBase64String}&edns_client_subnet={clientIpAddress}"); dnsMsg = DnsMessage.Parse(dnsDataBytes); } catch (WebException e) { HttpWebResponse response = (HttpWebResponse)e.Response; try { BackgroundLog($@"| - Catch WebException : {Convert.ToInt32(response.StatusCode)} {response.StatusCode} | {domainName} | {dohUrl} | {dnsBase64String}"); if (response.StatusCode == HttpStatusCode.BadRequest) { DnsSettings.DnsMsgEnable = false; return(ResolveOverHttpsByDnsJson(clientIpAddress, domainName, DnsSettings.SecondHttpsDnsUrl, proxyEnable, wProxy, type)); } } catch (Exception exception) { BackgroundLog($@"| - Catch WebException : {exception.Message} | {domainName} | {dohUrl} | {dnsBase64String}"); } if (dohUrl != DnsSettings.HttpsDnsUrl) { return(new List <DnsRecordBase>(), ReturnCode.ServerFailure); } BackgroundLog($@"| -- SecondDoH : {DnsSettings.SecondHttpsDnsUrl}"); return(ResolveOverHttpsByDnsMsg(clientIpAddress, domainName, DnsSettings.SecondHttpsDnsUrl, proxyEnable, wProxy, type)); } return(dnsMsg.AnswerRecords, dnsMsg.ReturnCode); }
static void Main() { var dnsQMsg = new DnsMessage(); dnsQMsg.Questions.Add(new DnsQuestion(DomainName.Parse("pixiv.net"), RecordType.A, RecordClass.INet)); dnsQMsg.IsEDnsEnabled = true; dnsQMsg.EDnsOptions.Options.Add(new ClientSubnetOption(24, IPAddress.Parse("0.0.0.0"))); //dnsQMsg.Encode(false, out var bytes); var args = new object[] { false, null }; var mms = dnsQMsg.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); foreach (var mm in mms) { if (mm.ToString() == "Int32 Encode(Boolean, Byte[] ByRef)") { mm.Invoke(dnsQMsg, args); } } if ((args[1] as byte[])[2] == 0) { (args[1] as byte[])[2] = 1; } //var ibyte = MyDnsSend.GetQuestionData(DomainName.Parse("baidu.com").ToString().TrimEnd('.'), RecordType.A); //Console.WriteLine(ibyte); var dnsBase64String = Convert.ToBase64String((byte[])args[1]).TrimEnd('=') .Replace('+', '-').Replace('/', '_'); Console.WriteLine(dnsBase64String); var dnsMsg = DnsMessage.Parse(new WebClient().DownloadData("https://doh1.blahdns.com/dns-query?dns=" + dnsBase64String)); Console.WriteLine(dnsMsg.ReturnCode); foreach (var item in dnsMsg.AnswerRecords) { Console.WriteLine(item); } Console.ReadKey(); }
public async Task <List <string> > ResolveTxtAsync(string domain) { var message = new TxtMessage(domain).ToBase64String(); var result = await _httpClient.GetAsync($"{_providerUrl}?dns={message}"); var content = await result.Content.ReadAsByteArrayAsync(); var messageResult = DnsMessage.Parse(content); var list = new List <string>(); foreach (var record in messageResult.AnswerRecords) { if (record is TxtRecord txt) { list.Add(txt.TextData); } } return(list); }
public static async Task <DnsMessage> FromPostByteAsync(HttpContext context, bool ActiveEcs = true, byte EcsDefaultMask = 24) { var msg = DnsMessage.Parse((await context.Request.BodyReader.ReadAsync()).Buffer.ToArray()); if (!Config.EcsEnable || !ActiveEcs || context.Request.Query.ContainsKey("no-ecs")) { return(msg); } if (IsEcsEnable(msg)) { return(msg); } if (!msg.IsEDnsEnabled) { msg.IsEDnsEnabled = true; } msg.EDnsOptions.Options.Add(new ClientSubnetOption(EcsDefaultMask, IPNetwork.Parse(RealIP.Get(context).ToString(), EcsDefaultMask).Network)); return(msg); }
static void Main(string[] args) { DNSEncoder.Init(); var server = new WebSocketServer("ws://0.0.0.0:3030"); server.ListenerSocket.NoDelay = true; server.Start(ws => { ws.OnOpen = () => Console.WriteLine(ws.ConnectionInfo.ClientIpAddress + ":Open!"); ws.OnClose = () => Console.WriteLine(ws.ConnectionInfo.ClientIpAddress + ":Close!"); ws.OnBinary = msg => { using (var bgWorker = new BackgroundWorker()) { bgWorker.DoWork += (sender, eventArgs) => { var dnsQMsg = DnsMessage.Parse(msg); var dnsRMsg = new DnsClient(IPAddress.Parse("8.8.8.8"), 1000).SendMessage(dnsQMsg); ws.Send(DNSEncoder.Encode(dnsRMsg)); Console.ForegroundColor = ConsoleColor.Cyan; dnsQMsg.Questions.ForEach(o => Console.WriteLine("Qu:" + o)); Console.ForegroundColor = ConsoleColor.Green; dnsRMsg.AnswerRecords.ForEach(o => Console.WriteLine("An:" + o)); Console.ForegroundColor = ConsoleColor.DarkGreen; dnsRMsg.AuthorityRecords.ForEach(o => Console.WriteLine("Au:" + o)); Console.ForegroundColor = ConsoleColor.Green; }; bgWorker.RunWorkerAsync(); } }; }); Console.ReadLine(); }
public bool Start() { var endPoint = Utils.CreateIpEndPoint(_listenOn, 53); _stopTokenSource = new CancellationTokenSource(); _transactionClients = new ConcurrentDictionary <ushort, IPEndPoint>(); _transactionTimeoutCancellationTokenSources = new ConcurrentDictionary <ushort, CancellationTokenSource>(); try { _udpListener = new UdpClient(endPoint); _udpForwarder = new UdpClient(0); } catch (SocketException e) { Logger.Error("[Listener] Failed to start DNSAgent:\n{0}", e); Stop(); return(false); } _listeningTask = Task.Run(async() => { while (!_stopTokenSource.IsCancellationRequested) { try { var query = await _udpListener.ReceiveAsync(); ProcessMessageAsync(query); } catch (SocketException e) { if (e.SocketErrorCode != SocketError.ConnectionReset) { Logger.Error("[Listener.Receive] Unexpected socket error:\n{0}", e); } } catch (AggregateException e) { var socketException = e.InnerException as SocketException; if (socketException != null) { if (socketException.SocketErrorCode != SocketError.ConnectionReset) { Logger.Error("[Listener.Receive] Unexpected socket error:\n{0}", e); } } else { Logger.Error("[Listener] Unexpected exception:\n{0}", e); } } catch (ObjectDisposedException) { } // Force closing _udpListener will cause this exception catch (Exception e) { Logger.Error("[Listener] Unexpected exception:\n{0}", e); } } }, _stopTokenSource.Token); _forwardingTask = Task.Run(async() => { while (!_stopTokenSource.IsCancellationRequested) { try { var query = await _udpForwarder.ReceiveAsync(); DnsMessage message; try { message = DnsMessage.Parse(query.Buffer); } catch (Exception) { throw new ParsingException(); } if (!_transactionClients.ContainsKey(message.TransactionID)) { continue; } IPEndPoint remoteEndPoint; CancellationTokenSource ignore; _transactionClients.TryRemove(message.TransactionID, out remoteEndPoint); _transactionTimeoutCancellationTokenSources.TryRemove(message.TransactionID, out ignore); await _udpListener.SendAsync(query.Buffer, query.Buffer.Length, remoteEndPoint); // Update cache if (Options.CacheResponse) { Cache.Update(message.Questions[0], message, Options.CacheAge); } } catch (ParsingException) { } catch (SocketException e) { if (e.SocketErrorCode != SocketError.ConnectionReset) { Logger.Error("[Forwarder.Send] Name server unreachable."); } else { Logger.Error("[Forwarder.Receive] Unexpected socket error:\n{0}", e); } } catch (ObjectDisposedException) { } // Force closing _udpListener will cause this exception catch (Exception e) { Logger.Error("[Forwarder] Unexpected exception:\n{0}", e); } } }, _stopTokenSource.Token); Logger.Info("Listening on {0}...", endPoint); OnStarted(); return(true); }
private async void ProcessMessageAsync(UdpReceiveResult udpMessage) { await Task.Run(async() => { try { DnsMessage message; DnsQuestion question; var respondedFromCache = false; try { message = DnsMessage.Parse(udpMessage.Buffer); question = message.Questions[0]; } catch (Exception) { throw new ParsingException(); } // Check for authorized subnet access if (_networkWhitelist != null) { if (_networkWhitelist.All(pair => !pair.Key.GetNetworkAddress(pair.Value) .Equals(udpMessage.RemoteEndPoint.Address.GetNetworkAddress(pair.Value)))) { Logger.Info("-> {0} is not authorized, who requested {1}.", udpMessage.RemoteEndPoint.Address, question); message.ReturnCode = ReturnCode.Refused; message.IsQuery = false; } } Logger.Info("-> {0} requested {1} (#{2}, {3}).", udpMessage.RemoteEndPoint.Address, question.Name, message.TransactionID, question.RecordType); // Query cache if (Options.CacheResponse) { if (Cache.ContainsKey(question.Name) && Cache[question.Name].ContainsKey(question.RecordType)) { var entry = Cache[question.Name][question.RecordType]; if (!entry.IsExpired) { var cachedMessage = entry.Message; Logger.Info("-> #{0} {2} served from cache.", message.TransactionID, cachedMessage.TransactionID, question.Name); cachedMessage.TransactionID = message.TransactionID; // Update transaction ID cachedMessage.TSigOptions = message.TSigOptions; // Update TSig options message = cachedMessage; respondedFromCache = true; } } } var targetNameServer = Options.DefaultNameServer; var useHttpQuery = Options.UseHttpQuery; var queryTimeout = Options.QueryTimeout; var useCompressionMutation = Options.CompressionMutation; // Match rules if (message.IsQuery && (question.RecordType == RecordType.A || question.RecordType == RecordType.Aaaa || question.RecordType == RecordType.Ptr)) { for (var i = Rules.Count - 1; i >= 0; i--) { var match = Regex.Match(question.Name, Rules[i].Pattern); if (!match.Success) { continue; } // Domain name matched var recordType = question.RecordType; if (Rules[i].ForceAAAA != null && Rules[i].ForceAAAA.Value) // RecordType override { recordType = RecordType.Aaaa; } if (Rules[i].NameServer != null) // Name server override { targetNameServer = Rules[i].NameServer; } if (Rules[i].UseHttpQuery != null) // HTTP query override { useHttpQuery = Rules[i].UseHttpQuery.Value; } if (Rules[i].QueryTimeout != null) // Query timeout override { queryTimeout = Rules[i].QueryTimeout.Value; } if (Rules[i].CompressionMutation != null) // Compression pointer mutation override { useCompressionMutation = Rules[i].CompressionMutation.Value; } if (Rules[i].Address != null) { IPAddress ip; IPAddress.TryParse(Rules[i].Address, out ip); if (ip == null) // Invalid IP, may be a domain name { var address = string.Format(Rules[i].Address, match.Groups.Cast <object>().ToArray()); if (recordType == RecordType.A && useHttpQuery) { await ResolveWithHttp(targetNameServer, address, queryTimeout, message); } else if (recordType == RecordType.Ptr) { var answerRecord = new PtrRecord(question.Name, 600, Rules[i].Address); message.AnswerRecords.Add(answerRecord); message.ReturnCode = ReturnCode.NoError; message.IsQuery = false; } else { var serverEndpoint = Utils.CreateIpEndPoint(targetNameServer, 53); var dnsClient = new DnsClient(serverEndpoint.Address, queryTimeout, serverEndpoint.Port); var response = await Task <DnsMessage> .Factory.FromAsync(dnsClient.BeginResolve, dnsClient.EndResolve, address, recordType, question.RecordClass, null); if (response == null) { Logger.Warning($"Remote resolve failed for {address}."); return; } foreach (var answerRecord in response.AnswerRecords) { answerRecord.Name = question.Name; message.AnswerRecords.Add(answerRecord); } message.ReturnCode = response.ReturnCode; message.IsQuery = false; } } else { if (recordType == RecordType.A && ip.AddressFamily == AddressFamily.InterNetwork) { message.AnswerRecords.Add(new ARecord(question.Name, 600, ip)); } else if (recordType == RecordType.Aaaa && ip.AddressFamily == AddressFamily.InterNetworkV6) { message.AnswerRecords.Add(new AaaaRecord(question.Name, 600, ip)); } else // Type mismatch { continue; } message.ReturnCode = ReturnCode.NoError; message.IsQuery = false; } } break; } } // TODO: Consider how to integrate System.Net.Dns with this project. // Using System.Net.Dns to forward query if compression mutation is disabled //if (message.IsQuery && !useCompressionMutation && // (question.RecordType == RecordType.A || question.RecordType == RecordType.Aaaa)) //{ // var dnsResponse = await Dns.GetHostAddressesAsync(question.Name); // if (question.RecordType == RecordType.A) // { // message.AnswerRecords.AddRange(dnsResponse.Where( // ip => ip.AddressFamily == AddressFamily.InterNetwork).Select( // ip => new ARecord(question.Name, 0, ip))); // else if (question.RecordType == RecordType.Aaaa) // { // message.AnswerRecords.AddRange(dnsResponse.Where( // ip => ip.AddressFamily == AddressFamily.InterNetworkV6).Select( // ip => new AaaaRecord(question.Name, 0, ip))); // } // message.ReturnCode = ReturnCode.NoError; // message.IsQuery = false; //} if (message.IsQuery && question.RecordType == RecordType.A && useHttpQuery) { await ResolveWithHttp(targetNameServer, question.Name, queryTimeout, message); } if (message.IsQuery) { // Use internal forwarder to forward query to another name server await ForwardMessage(message, udpMessage, Utils.CreateIpEndPoint(targetNameServer, 53), queryTimeout, useCompressionMutation); } else { // Already answered, directly return to the client byte[] responseBuffer; message.Encode(false, out responseBuffer); if (responseBuffer != null) { await _udpListener.SendAsync(responseBuffer, responseBuffer.Length, udpMessage.RemoteEndPoint); // Update cache if (Options.CacheResponse && !respondedFromCache) { Cache.Update(question, message, Options.CacheAge); } } } } catch (ParsingException) { } catch (SocketException e) { Logger.Error("[Listener.Send] Unexpected socket error:\n{0}", e); } catch (Exception e) { Logger.Error("[Processor] Unexpected exception:\n{0}", e); } }); }
public static DnsMessage FromWebBase64(string base64) => DnsMessage.Parse(DecodeWebBase64(base64));
void ForwardingTask_Run() { while (!_stopTokenSource.IsCancellationRequested) { try { IPEndPoint receivepoint = new IPEndPoint(IPAddress.Broadcast, _IPEndPoint.Port); byte[] buf = _UdpForwarder.Receive(ref receivepoint); /*var query = await _udpForwarder.ReceiveAsync();*/ DnsMessage message; try { message = DnsMessage.Parse(buf); } catch (Exception) { throw new ParsingException(); } if (!_transactionClients.ContainsKey(message.TransactionID)) { continue; } IPEndPoint remoteEndPoint; MrTe.Threading.Tasks.CancellationTokenSource ignore; /* * _transactionClients.TryRemove(message.TransactionID, out remoteEndPoint); * _transactionTimeoutCancellationTokenSources.TryRemove(message.TransactionID, out ignore); * await _udpListener.SendAsync(query.Buffer, query.Buffer.Length, remoteEndPoint); */ remoteEndPoint = _transactionClients[message.TransactionID]; ignore = _transactionTimeoutCancellationTokenSources[message.TransactionID]; _UdpListener.Send(buf, buf.Length, remoteEndPoint); // Update cache if (Options.CacheResponse) { Cache.Update(message.Questions[0], message, Options.CacheAge); } _transactionClients.Remove(message.TransactionID); _transactionTimeoutCancellationTokenSources.Remove(message.TransactionID); } catch (ParsingException) { } catch (SocketException e) { if (e.SocketErrorCode != SocketError.ConnectionReset) { Logger.Error("[Forwarder.Send] Name server unreachable."); } else { Logger.Error("[Forwarder.Receive] Unexpected socket error:\n{0}", e); } } catch (ObjectDisposedException) { } // Force closing _udpListener will cause this exception catch (Exception e) { Logger.Error("[Forwarder] Unexpected exception:\n{0}", e); } } }
static void Main(string[] args) { var dict = new Dictionary <BackgroundWorker, ClientWebSocket>(); using (DnsServer dnsServer = new DnsServer(IPAddress.Any, 10, 10)) { DNSEncoder.Init(); for (var i = 0; i < 3; i++) { dict.Add(new BackgroundWorker(), new ClientWebSocket()); } foreach (var item in dict) { item.Value.ConnectAsync(new Uri("ws://127.0.0.1:3030"), CancellationToken.None).Wait(); } async Task OnDnsServerOnQueryReceived(object sender, QueryReceivedEventArgs e) { if (!(e.Query is DnsMessage query)) { return; } await Task.Run(() => { try { foreach (var item in dict.Where(item => !item.Key.IsBusy)) { var worker = item.Key; worker.DoWork += (o, eventArgs) => { var ws = item.Value; if (ws.State == WebSocketState.Aborted) { ws.Dispose(); ws = new ClientWebSocket(); ws.ConnectAsync(new Uri("ws://127.0.0.1:3030"), CancellationToken.None) .Wait(); } if (ws.State == WebSocketState.Closed) { ws.ConnectAsync(new Uri("ws://127.0.0.1:3030"), CancellationToken.None) .Wait(); } ws.SendAsync(new ArraySegment <byte>(DNSEncoder.Encode(query)), WebSocketMessageType.Binary, true, CancellationToken.None).Wait(); var dnsBytes = new byte[500]; ws.ReceiveAsync(new ArraySegment <byte>(dnsBytes), CancellationToken.None) .Wait(); var dnsRMsg = DnsMessage.Parse(dnsBytes); e.Response = dnsRMsg; using (var bgw = new BackgroundWorker()) { bgw.DoWork += (i, a) => { dnsRMsg.AnswerRecords.ForEach(Console.WriteLine); dnsRMsg.AuthorityRecords.ForEach(Console.WriteLine); }; bgw.RunWorkerAsync(); } }; item.Key.RunWorkerAsync(); while (true) { if (item.Key.IsBusy) { continue; } item.Key.Dispose(); dict.Remove(item.Key); dict.Add(new BackgroundWorker(), item.Value); break; } break; } } catch (Exception exception) { Console.WriteLine(exception); throw; } }); } dnsServer.QueryReceived += OnDnsServerOnQueryReceived; dnsServer.Start(); Console.WriteLine(@"-------ARASHI DNS------"); Console.WriteLine(@"-------DOTNET ALPHA------"); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(@"ArashiDNS Server Running"); Console.WriteLine(@"Press any key to stop dns server"); Console.WriteLine("------------------------"); Console.ReadLine(); Console.WriteLine("------------------------"); foreach (var item in dict) { item.Value.CloseAsync(WebSocketCloseStatus.Empty, string.Empty, CancellationToken.None).Wait(); } } }