diff --git a/EonaCat.DnsTester/EonaCat.DnsTester.csproj b/EonaCat.DnsTester/EonaCat.DnsTester.csproj index 7924cc3..85bf5a6 100644 --- a/EonaCat.DnsTester/EonaCat.DnsTester.csproj +++ b/EonaCat.DnsTester/EonaCat.DnsTester.csproj @@ -1,99 +1,17 @@ - - - + + - Debug - AnyCPU - {CAA93B33-C1F4-46AE-ABD8-3802BCB6CB5F} WinExe + net6.0-windows + true + false + EonaCat.DnsTester EonaCat.DnsTester - v4.8 - 512 - true - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - EonaCat.ico - - - - - - - - - - - - - - - - - - - - - Form - - - MainForm.cs - - - - - MainForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - + - - Always - - \ No newline at end of file diff --git a/EonaCat.DnsTester/Helpers/DnsHelper.cs b/EonaCat.DnsTester/Helpers/DnsHelper.cs new file mode 100644 index 0000000..5d5cbe7 --- /dev/null +++ b/EonaCat.DnsTester/Helpers/DnsHelper.cs @@ -0,0 +1,118 @@ +using Microsoft.VisualBasic.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace EonaCat.DnsTester.Helpers +{ + internal class DnsHelper + { + public static event EventHandler Log; + + public static void ProcessDns(string startOfUrl, string domain, int urlsTotal, Socket dnsSocket, byte[] bytesSend, + long startTime, int totalDnsToUse, ListView result) + { + var bytesReceived = new byte[512]; + var totalReceived = 0; + + // wait for a response up to timeout + while (totalReceived < urlsTotal * totalDnsToUse) + { + dnsSocket.Receive(bytesReceived); + + // Check if the error is ours + if ((bytesReceived[0] != bytesSend[0] || bytesReceived[1] != 0x31) && + bytesReceived[1] != 0x32) + continue; + + if (bytesReceived[2] != 0x81 || bytesReceived[3] != 0x80) continue; + + // Get the time now + var stopTime = DateTime.Now.Ticks; + var deltaTime = Convert.ToString((double)(stopTime - startTime) / 10000000); + + // Decode the answers + // Find the URL that was returned + int dnsId = bytesReceived[1]; + var receiveString = Encoding.ASCII.GetString(bytesReceived); + var index = 12; + int startOfUrlLength = bytesReceived[index]; + index++; + startOfUrl = receiveString.Substring(index, startOfUrlLength); + index += startOfUrlLength; + int domainLength = bytesReceived[index]; + index++; + domain = receiveString.Substring(index, domainLength); + index += domainLength; + index += 8; + + // Get the record type + int ResponseType = bytesReceived[index]; + index += 9; + + // Get the IP address if applicable + var ipResponse = ""; + switch (ResponseType) + { + case 1: + ipResponse = + $"{Convert.ToString(bytesReceived[index])}.{Convert.ToString(bytesReceived[index + 1])}.{Convert.ToString(bytesReceived[index + 2])}.{Convert.ToString(bytesReceived[index + 3])}"; + break; + case 5: + ipResponse = "CNAME"; + break; + case 6: + ipResponse = "SOA"; + break; + } + + SetStatus($"Answer: {startOfUrl}.{domain} : {ipResponse}"); + + // Find the url in the list + for (int i = 0; i < result.Items.Count; i++) + { + if (result.Items[i].Text != $"{startOfUrl}.{domain}") continue; + + string sDeltaTime; + switch (dnsId) + { + case 49: + result.Items[i].SubItems[1].Text = Convert.ToString(ipResponse); + sDeltaTime = Convert.ToString(deltaTime); + result.Items[i].SubItems[2].Text = + sDeltaTime.Length > 5 ? sDeltaTime.Substring(0, 5) : sDeltaTime; + result.Items[i].ForeColor = System.Drawing.Color.Red; + result.EnsureVisible(i); + result.Update(); + Application.DoEvents(); + result.Items[i].ForeColor = System.Drawing.Color.Black; + break; + + case 50: + result.Items[i].SubItems[3].Text = Convert.ToString(ipResponse); + sDeltaTime = Convert.ToString(deltaTime); + result.Items[i].SubItems[4].Text = + sDeltaTime.Length > 5 ? sDeltaTime.Substring(0, 5) : sDeltaTime; + result.Items[i].ForeColor = System.Drawing.Color.Red; + result.EnsureVisible(i); + result.Update(); + Application.DoEvents(); + result.Items[i].ForeColor = System.Drawing.Color.Black; + break; + } + + totalReceived++; + } + } + } + + private static void SetStatus(string text) + { + Log?.Invoke(null, text); + } + } +} diff --git a/EonaCat.DnsTester/Helpers/UrlHelper.cs b/EonaCat.DnsTester/Helpers/UrlHelper.cs new file mode 100644 index 0000000..caebf80 --- /dev/null +++ b/EonaCat.DnsTester/Helpers/UrlHelper.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace EonaCat.DnsTester.Helpers +{ + internal class UrlHelper + { + private static readonly RandomNumberGenerator _randomNumberGenerator = RandomNumberGenerator.Create(); + public static event EventHandler Log; + + public static void GetRandomUrls(ref List urlList, int totalUrls) + { + // Generate a cryptographically strong random string + byte[] randomBytes = new byte[32]; + _randomNumberGenerator.GetBytes(randomBytes); + string letters = Convert.ToBase64String(randomBytes); + + Dictionary searchEngineUrls = new Dictionary + { + { "Yahoo", "https://search.yahoo.com/search?p=" }, + { "Bing", "https://www.bing.com/search?q=" }, + { "Google", "https://www.google.com/search?q=" }, + { "Ask", "https://www.ask.com/web?q=" }, + { "WolframAlpha", "https://www.wolframalpha.com/input/?i=" }, + { "StartPage", "https://www.startpage.com/do/dsearch?query=" }, + { "Yandex", "https://www.yandex.com/search/?text=" }, + { "Qwant", "https://www.qwant.com/?q=" } + }; + + Random rand = new Random(); + + List localCleanNames = urlList; + + while (localCleanNames.Count < totalUrls) + { + int index = rand.Next(searchEngineUrls.Count); + KeyValuePair searchEngine = searchEngineUrls.ElementAt(index); + + string url = searchEngine.Value + letters; + + try + { + using (var client = new WebClient()) + { + string responseString = client.DownloadString(url); + + // find all .xxx.com addresses + MatchCollection hostNames = Regex.Matches(responseString, @"[.](\w+[.]com)"); + + // Loop through the match collection to retrieve all matches and delete the leading "." + HashSet uniqueNames = new HashSet(); + foreach (Match match in hostNames) + { + string name = match.Groups[1].Value; + if (name != $"{searchEngine.Key.ToLower()}.com") + { + uniqueNames.Add(name); + } + } + + // Add the names to the list + foreach (string name in uniqueNames) + { + if (localCleanNames.Count >= totalUrls) + { + break; + } + + if (!localCleanNames.Contains(name)) + { + localCleanNames.Add(name); + } + } + } + } + catch (Exception ex) + { + SetStatus($"{searchEngine.Key}: {ex.Message}"); + } + } + + urlList = localCleanNames; // Update the reference to the list + SetStatus($"{urlList.Count} Random URL's found"); + } + + private static void SetStatus(string text) + { + Log?.Invoke(null, text); + } + } +} diff --git a/EonaCat.DnsTester/MainForm.Designer.cs b/EonaCat.DnsTester/MainForm.Designer.cs index 2d01c8f..27125b8 100644 --- a/EonaCat.DnsTester/MainForm.Designer.cs +++ b/EonaCat.DnsTester/MainForm.Designer.cs @@ -38,8 +38,8 @@ this.RunTest = new System.Windows.Forms.Button(); this.lblDns1 = new System.Windows.Forms.Label(); this.lblDns2 = new System.Windows.Forms.Label(); - this.DnsList1 = new System.Windows.Forms.ComboBox(); - this.DnsList2 = new System.Windows.Forms.ComboBox(); + this.dnsList1 = new System.Windows.Forms.ComboBox(); + this.dnsList2 = new System.Windows.Forms.ComboBox(); this.UseCustomServers = new System.Windows.Forms.CheckBox(); this.lblCustom1 = new System.Windows.Forms.Label(); this.lblCustom2 = new System.Windows.Forms.Label(); @@ -139,25 +139,25 @@ this.lblDns2.TabIndex = 14; this.lblDns2.Text = "Dns 2:"; // - // DnsList1 + // dnsList1 // - this.DnsList1.FormattingEnabled = true; - this.DnsList1.ItemHeight = 31; - this.DnsList1.Location = new System.Drawing.Point(277, 155); - this.DnsList1.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7); - this.DnsList1.Name = "DnsList1"; - this.DnsList1.Size = new System.Drawing.Size(756, 39); - this.DnsList1.TabIndex = 15; + this.dnsList1.FormattingEnabled = true; + this.dnsList1.ItemHeight = 31; + this.dnsList1.Location = new System.Drawing.Point(277, 155); + this.dnsList1.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7); + this.dnsList1.Name = "dnsList1"; + this.dnsList1.Size = new System.Drawing.Size(756, 39); + this.dnsList1.TabIndex = 15; // - // DnsList2 + // dnsList2 // - this.DnsList2.FormattingEnabled = true; - this.DnsList2.ItemHeight = 31; - this.DnsList2.Location = new System.Drawing.Point(1229, 155); - this.DnsList2.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7); - this.DnsList2.Name = "DnsList2"; - this.DnsList2.Size = new System.Drawing.Size(788, 39); - this.DnsList2.TabIndex = 16; + this.dnsList2.FormattingEnabled = true; + this.dnsList2.ItemHeight = 31; + this.dnsList2.Location = new System.Drawing.Point(1229, 155); + this.dnsList2.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7); + this.dnsList2.Name = "dnsList2"; + this.dnsList2.Size = new System.Drawing.Size(788, 39); + this.dnsList2.TabIndex = 16; // // UseCustomServers // @@ -366,8 +366,8 @@ this.Controls.Add(this.lblCustom2); this.Controls.Add(this.lblCustom1); this.Controls.Add(this.UseCustomServers); - this.Controls.Add(this.DnsList2); - this.Controls.Add(this.DnsList1); + this.Controls.Add(this.dnsList2); + this.Controls.Add(this.dnsList1); this.Controls.Add(this.lblDns2); this.Controls.Add(this.lblDns1); this.Controls.Add(this.RunTest); @@ -396,8 +396,8 @@ private System.Windows.Forms.Button RunTest; private System.Windows.Forms.Label lblDns1; private System.Windows.Forms.Label lblDns2; - private System.Windows.Forms.ComboBox DnsList1; - private System.Windows.Forms.ComboBox DnsList2; + private System.Windows.Forms.ComboBox dnsList1; + private System.Windows.Forms.ComboBox dnsList2; private System.Windows.Forms.CheckBox UseCustomServers; private System.Windows.Forms.Label lblCustom1; private System.Windows.Forms.Label lblCustom2; diff --git a/EonaCat.DnsTester/MainForm.cs b/EonaCat.DnsTester/MainForm.cs index 71a1d04..430b0de 100644 --- a/EonaCat.DnsTester/MainForm.cs +++ b/EonaCat.DnsTester/MainForm.cs @@ -6,18 +6,20 @@ using System.Linq; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; +using System.Security.Policy; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; -using System.Windows.Threading; +using EonaCat.DnsTester.Helpers; namespace EonaCat.DnsTester { - public partial class MainForm : Form + public partial class MainForm : Form { - private bool UseCustomDnsServers = false; - public string DNS1, DNS2; + private bool useCustomDnsServers; + private string _dnsServer1, _dnsServer2; + private int _dnsTotalChecked; public bool IsRunning { get; private set; } @@ -28,460 +30,269 @@ namespace EonaCat.DnsTester private void RunTest_Click(object sender, EventArgs e) { - int i; - List CleanNames = new List(); + List urls = new List(); + SetupUrls(urls); - if (this.UseCustomDnsServers) + if (IsRunning) { - if (chkDns1.Checked) - { - DNS1 = CustomDns1.Text; - } + return; + } - if (chkDns2.Checked) - { - DNS2 = CustomDns2.Text; - } + IsRunning = true; + Process(urls.ToArray(), _dnsServer1, _dnsServer2); + IsRunning = false; + } + + private void SetupUrls(List urls) + { + if (useCustomDnsServers) + { + _dnsTotalChecked = 0; + if (chkDns1.Checked) + { + _dnsTotalChecked++; + _dnsServer1 = CustomDns1.Text; + } + + if (chkDns2.Checked) + { + _dnsTotalChecked++; + _dnsServer2 = CustomDns2.Text; + } } else { - if (chkDns1.Checked) - { - DNS1 = DnsList1.SelectedValue.ToString(); - } + _dnsTotalChecked = 0; + if (chkDns1.Checked) + { + _dnsTotalChecked++; + _dnsServer1 = dnsList1.SelectedValue.ToString(); + } - if (chkDns2.Checked) - { - DNS2 = DnsList2.SelectedValue.ToString(); - } + if (chkDns2.Checked) + { + _dnsTotalChecked++; + _dnsServer2 = dnsList2.SelectedValue.ToString(); + } } - ResultView.Items.Clear(); - ResultView.Update(); - Application.DoEvents(); - - GetWebAddresses(ref CleanNames, (int)numericUpDown1.Value); + ResultView.Items.Clear(); + ResultView.Update(); + Application.DoEvents(); - for (i = 0; i < CleanNames.Count; i++) - { - ListViewItem listURL = new ListViewItem(CleanNames[i]); - listURL.SubItems.Add(" "); - listURL.SubItems.Add(" "); - listURL.SubItems.Add(" "); - listURL.SubItems.Add(" "); - - ResultView.Items.Add(listURL); - } - if (ResultView.Items.Count > 1) - { - ResultView.EnsureVisible(ResultView.Items.Count - 1); - } - - ResultView.Update(); - Application.DoEvents(); - - if (IsRunning) - { - return; - } - - IsRunning = true; - CheckDNS(CleanNames.ToArray(), CleanNames.Count, DNS1, DNS2); - IsRunning = false; - } - - - private void TesterUI_Load(object sender, EventArgs e) - { - FillDnsList(); + UrlHelper.Log += UrlHelper_Log; + UrlHelper.GetRandomUrls(ref urls, (int)numericUpDown1.Value); + AddUrlToView(urls); } - private void FillDnsList() + private void UrlHelper_Log(object sender, string e) { - DnsList1.ValueMember = "ip"; - DnsList1.DisplayMember = "name"; + SetStatus(e); + } - DnsList2.ValueMember = "ip"; - DnsList2.DisplayMember = "name"; + private void AddUrlToView(List urls) + { + foreach (var currentUrl in urls) + { + ListViewItem listURL = new ListViewItem(currentUrl); + listURL.SubItems.Add(" "); + listURL.SubItems.Add(" "); + listURL.SubItems.Add(" "); + listURL.SubItems.Add(" "); + ResultView.Items.Add(listURL); + } + + if (ResultView.Items.Count > 1) + { + ResultView.EnsureVisible(ResultView.Items.Count - 1); + } + + ResultView.Update(); + Application.DoEvents(); + } + + + private void TesterUI_Load(object sender, EventArgs e) + { + PopulateDnsLists(); + } + + private void PopulateDnsLists() + { + dnsList1.ValueMember = "ip"; + dnsList1.DisplayMember = "name"; + + dnsList2.ValueMember = "ip"; + dnsList2.DisplayMember = "name"; + + var serverList = Path.Combine(Application.StartupPath, "Servers.xml"); DataSet servers1 = new DataSet(); DataSet servers2 = new DataSet(); - servers1.ReadXml(Path.Combine(Application.StartupPath, "Servers.xml")); - servers2.ReadXml(Path.Combine(Application.StartupPath, "Servers.xml")); - DataTable ns1 = servers1.Tables[0]; - DataTable ns2 = servers2.Tables[0]; - DnsList1.DataSource = ns1; - DnsList2.DataSource = ns2; + servers1.ReadXml(serverList); + servers2.ReadXml(serverList); + DataTable dataTable1 = servers1.Tables[0]; + DataTable dataTable2 = servers2.Tables[0]; + dnsList1.DataSource = dataTable1; + dnsList2.DataSource = dataTable2; } private void UseCustomServers_CheckedChanged(object sender, EventArgs e) { - this.UseCustomDnsServers = UseCustomServers.Checked; + useCustomDnsServers = UseCustomServers.Checked; SetUI(); } private void SetUI() { - if (this.UseCustomDnsServers) + if (useCustomDnsServers) { - this.DnsList1.Enabled = false; - this.DnsList2.Enabled = false; + dnsList1.Enabled = false; + dnsList2.Enabled = false; - this.CustomDns1.Enabled = true; - this.CustomDns2.Enabled = true; + CustomDns1.Enabled = true; + CustomDns2.Enabled = true; - this.CustomDns1.Visible = true; - this.CustomDns2.Visible = true; - this.lblCustom1.Visible = true; - this.lblCustom2.Visible = true; + CustomDns1.Visible = true; + CustomDns2.Visible = true; + lblCustom1.Visible = true; + lblCustom2.Visible = true; } else { - this.DnsList1.Enabled = true; - this.DnsList2.Enabled = true; - this.CustomDns1.Enabled = false; ; - this.CustomDns2.Enabled = false; + dnsList1.Enabled = true; + dnsList2.Enabled = true; + CustomDns1.Enabled = false; + CustomDns2.Enabled = false; - this.CustomDns1.Visible = false; - this.CustomDns2.Visible = false; - this.lblCustom1.Visible = false; - this.lblCustom2.Visible = false; + CustomDns1.Visible = false; + CustomDns2.Visible = false; + lblCustom1.Visible = false; + lblCustom2.Visible = false; } } - - private void GetWebAddresses(ref List CleanNames, int totalUrls) - { - int i, j; - byte[] random = new Byte[256]; - string Letters = ""; - // Make a 3 letter random string - - //RNGCryptoServiceProvider is an implementation of a random number generator. - RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); - rng.GetBytes(random); // The array is now filled with cryptographically strong random bytes. - for (i = 1; i < 256; i++) - { - // Just take the first three letters - if (random[i] > 0x40 && random[i] < 0x5b) Letters = Letters + Convert.ToChar(random[i]); - if (Letters.Length == 3) break; - } - - KeyValuePair searchEngine = new KeyValuePair(); - Random rand = new Random(); - - // Create a list of search engine URLs to query - Dictionary searchEngineUrls = new Dictionary - { - { "DuckDuckGo", "https://duckduckgo.com/html/?q=" }, - { "Yahoo", "https://search.yahoo.com/search?p=" }, - { "Bing", "https://www.bing.com/search?q=" }, - { "Google", "https://www.google.com/search?q=" }, - { "Ask", "https://www.ask.com/web?q=" }, - { "AOL", "https://www.aol.com/search?q=" }, - { "WolframAlpha", "https://www.wolframalpha.com/input/?i=" }, - { "StartPage", "https://www.startpage.com/do/dsearch?query=" }, - { "Yandex", "https://www.yandex.com/search/?text=" }, - { "Qwant", "https://www.qwant.com/?q=" } - }; - - try - { - while (CleanNames.Count < totalUrls) - { - int index = rand.Next(searchEngineUrls.Count); - searchEngine = searchEngineUrls.ElementAt(index); - - WebRequest Request = WebRequest.Create(searchEngine.Value + Letters); //Letters); - WebResponse Response = Request.GetResponse(); - Application.DoEvents(); - - // Get the response stream. - Stream Stream = Response.GetResponseStream(); - StatusBoxPrint(searchEngine.Key + " response received"); - - StreamReader StreamReader = new StreamReader(Stream, Encoding.ASCII); - string ResponseString = StreamReader.ReadToEnd(); - - // Close the response stream and response to free resources. - Stream.Close(); - Response.Close(); - Application.DoEvents(); - - // find all .xxx.com addresses - MatchCollection HostNames; - string[] Names = new string[totalUrls + 1000]; - - // Create a new Regex object and define the regular expression. - Regex Dotcom = new Regex("[.]([A-Za-z]*)[.]com"); - - - // Use the Matches method to find all matches in the input string. - HostNames = Dotcom.Matches(ResponseString); - - Application.DoEvents(); - - // Loop through the match collection to retrieve all - // matches and delete the leading "." - for (i = 0; i < HostNames.Count; i++) - { - Names[i] = HostNames[i].Value.Remove(0, 1); - } - - // eliminate its own search engine names and repeated entries - for (i = 0; i < HostNames.Count - 1; i++) - { - if (Names[i] == searchEngine.Key.ToLower() + ".com") Names[i] = ""; - for (j = i + 1; j < HostNames.Count; j++) - { - if (Names[i] == Names[j]) Names[j] = ""; - } - } - - Shuffle(Names); - - // Add the names to the list - for (i = 0; i < HostNames.Count; i++) - { - if (CleanNames.Count >= totalUrls) - { - break; - } - - if (!string.IsNullOrEmpty(Names[i]) && !CleanNames.Contains(Names[i])) - { - CleanNames.Add(Names[i]); - } - } - } - StatusBoxPrint(CleanNames.Count + " Random URL's found"); - } - catch(Exception exception) - { - StatusBoxPrint(searchEngine.Key + ": " ?? string.Empty + exception.Message); - } - } - - public static void Shuffle(T[] array) + private void Process(string[] urls, string dnsAddress1, string dnsAddress2) { - Random rng = new Random(); - int n = array.Length; - while (n > 1) + int i; + int urlsTotal = urls.Length; + const int ipPort = 53; + const string transactionId1 = "Q1"; + const string transactionId2 = "Q2"; + const string typeString = "\u0001" + "\u0000" + "\u0000" + "\u0001" + "\u0000" + "\u0000" + "\u0000" + "\u0000" + "\u0000" + "\u0000"; + const string trailerString = "\u0000" + "\u0000" + "\u0001" + "\u0000" + "\u0001"; + const int dnsReceiveTimeout = 5000; + string startOfUrl = string.Empty; + string domain = string.Empty; + byte[] bytesSend = new byte[256]; + Socket dnsSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + dnsSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, dnsReceiveTimeout); + + SetupDnsServers(dnsAddress1, dnsAddress2, ipPort, out var dnsEndpoint1, out var dnsEndpoint2); + + // Start the clock + var startTime = DateTime.Now.Ticks; + + for (i = 0; i < urlsTotal; i++) { - n--; - int k = rng.Next(n + 1); - T value = array[k]; - array[k] = array[n]; - array[n] = value; + var currentUrl = urls[i]; + startOfUrl = currentUrl.Substring(0, currentUrl.IndexOf(".")); + domain = currentUrl.Substring(currentUrl.IndexOf(".") + 1, + currentUrl.Length - currentUrl.IndexOf(".") - 1); + var dnsQuery = typeString + (char)startOfUrl.Length + startOfUrl + (char)domain.Length + domain + + trailerString; + + string queryString; + if (chkDns1.Checked) + { + queryString = transactionId1 + dnsQuery; + bytesSend = Encoding.ASCII.GetBytes(queryString); + if (dnsEndpoint1 != null) + dnsSocket.SendTo(bytesSend, bytesSend.Length, SocketFlags.None, dnsEndpoint1); + } + + if (!chkDns2.Checked) continue; + + queryString = transactionId2 + dnsQuery; + bytesSend = Encoding.ASCII.GetBytes(queryString); + if (dnsEndpoint2 != null) dnsSocket.SendTo(bytesSend, bytesSend.Length, SocketFlags.None, dnsEndpoint2); + } + + try + { + DnsHelper.Log += DnsHelper_Log; + DnsHelper.ProcessDns(startOfUrl, domain, urlsTotal, dnsSocket, bytesSend, startTime, _dnsTotalChecked, ResultView); + } + catch (SocketException socketException) + { + SetStatus( + Convert.ToString(socketException).IndexOf("time", StringComparison.Ordinal) > 0 + ? $"Timeout - No response received for {Convert.ToString(dnsReceiveTimeout / 1000)} seconds" + : Convert.ToString(socketException)); + } + finally + { + // close the socket + dnsSocket.Close(); } } - private void CheckDNS(string[] URLNames, int URLNamescount, string DNSAddress1, string DNSAddress2) - { - int i; - const int IPPort = 53; - const string TransactionID1 = "Q1"; // Use transaction ID of Q1 and Q2 to identify our packet and DNS - const string TransactionID2 = "Q2"; - const string TypeString = "\u0001" + "\u0000" + "\u0000" + "\u0001" + "\u0000" + "\u0000" + "\u0000" + "\u0000" + "\u0000" + "\u0000"; - const string TrailerString = "\u0000" + "\u0000" + "\u0001" + "\u0000" + "\u0001"; - const int DNSReceiveTimeout = 5000; - string URLNameStart, DomainName, QueryString, ReceiveString, IPResponse, sDeltaTime; - int URLNameStartLength, DomainNameLength, index, TransactionDNS; - byte[] Sendbytes = new byte[256]; - long StartTime, StopTime; - string DeltaTime; - Socket DNSsocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - DNSsocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, DNSReceiveTimeout); + private void DnsHelper_Log(object sender, string e) + { + SetStatus(e); + } - IPEndPoint dnsEP1 = null; - if (chkDns1.Checked && !string.IsNullOrWhiteSpace(DNSAddress1)) - { - dnsEP1 = new IPEndPoint(IPAddress.Parse(DNSAddress1), IPPort); - } - - IPEndPoint dnsEP2 = null; - if (chkDns2.Checked && !string.IsNullOrWhiteSpace(DNSAddress2)) - { - dnsEP2 = new IPEndPoint(IPAddress.Parse(DNSAddress2), IPPort); - } + private void SetupDnsServers(string dnsAddress1, string dnsAddress2, int ipPort, out IPEndPoint dnsEndpoint1, + out IPEndPoint dnsEndpoint2) + { + dnsEndpoint1 = null; + if (chkDns1.Checked && !string.IsNullOrWhiteSpace(dnsAddress1)) + { + dnsEndpoint1 = new IPEndPoint(IPAddress.Parse(dnsAddress1), ipPort); + } - // Start the clock - StartTime = DateTime.Now.Ticks; - - for (i = 0; i < URLNamescount; i++) - { - URLNameStart = URLNames[i].Substring(0, URLNames[i].IndexOf(".")); - DomainName = URLNames[i].Substring(URLNames[i].IndexOf(".") + 1, URLNames[i].Length - URLNames[i].IndexOf(".") - 1); - - if (chkDns1.Checked) - { - QueryString = TransactionID1 + TypeString + (char)URLNameStart.Length + URLNameStart + (char)DomainName.Length + DomainName + TrailerString; - Sendbytes = Encoding.ASCII.GetBytes(QueryString); - if (dnsEP1 != null) - { - DNSsocket.SendTo(Sendbytes, Sendbytes.Length, SocketFlags.None, dnsEP1); - } - } - - if (chkDns2.Checked) - { - QueryString = TransactionID2 + TypeString + (char)URLNameStart.Length + URLNameStart + (char)DomainName.Length + DomainName + TrailerString; - Sendbytes = Encoding.ASCII.GetBytes(QueryString); - if (dnsEP2 != null) - { - DNSsocket.SendTo(Sendbytes, Sendbytes.Length, SocketFlags.None, dnsEP2); - } - } - } - - byte[] Receivebytes = new byte[512]; - int totalReceived = 0; - - try - { - // wait for a response up to timeout - more: - DNSsocket.Receive(Receivebytes); - // make sure the message returned is ours - if (Receivebytes[0] == Sendbytes[0] && (Receivebytes[1] == 0x31) || (Receivebytes[1] == 0x32)) - { - if (Receivebytes[2] == 0x81 && Receivebytes[3] == 0x80) - { - // Get the time now - StopTime = DateTime.Now.Ticks; - DeltaTime = Convert.ToString((double)(StopTime - StartTime) / 10000000); - - // Decode the answers - // Find the URL that was returned - TransactionDNS = Receivebytes[1]; - ReceiveString = Encoding.ASCII.GetString(Receivebytes); - index = 12; - URLNameStartLength = Receivebytes[index]; - index++; - URLNameStart = ReceiveString.Substring(index, URLNameStartLength); - index = index + URLNameStartLength; - DomainNameLength = Receivebytes[index]; - index++; - DomainName = ReceiveString.Substring(index, DomainNameLength); - index = index + DomainNameLength; - index = index + 8; - - // Get the record type - int ResponseType = Receivebytes[index]; - index = index + 9; - - // Get the IP address if applicable - IPResponse = ""; - switch (ResponseType) - { - case 1: - IPResponse = Convert.ToString(Receivebytes[index]) + "." - + Convert.ToString(Receivebytes[index + 1]) + "." - + Convert.ToString(Receivebytes[index + 2]) + "." - + Convert.ToString(Receivebytes[index + 3]); break; - case 5: IPResponse = "CNAME"; break; - case 6: IPResponse = "SOA"; break; - } - StatusBoxPrint("DNS Answer: " + URLNameStart + "." + DomainName + " = " + IPResponse); - - // Find the URL entry in the list - for (i = 0; i < ResultView.Items.Count; i++) - { - if (ResultView.Items[i].Text == URLNameStart + "." + DomainName) - { - - switch (TransactionDNS) - { - case 0x31: - ResultView.Items[i].SubItems[1].Text = Convert.ToString(IPResponse); - sDeltaTime = Convert.ToString(DeltaTime); - if (sDeltaTime.Length > 5) ResultView.Items[i].SubItems[2].Text = sDeltaTime.Substring(0, 5); - else ResultView.Items[i].SubItems[2].Text = sDeltaTime; - ResultView.Items[i].ForeColor = System.Drawing.Color.Red; - ResultView.EnsureVisible(i); - ResultView.Update(); - Application.DoEvents(); - ResultView.Items[i].ForeColor = System.Drawing.Color.Black; - break; - - case 0x32: - ResultView.Items[i].SubItems[3].Text = Convert.ToString(IPResponse); - sDeltaTime = Convert.ToString(DeltaTime); - if (sDeltaTime.Length > 5) ResultView.Items[i].SubItems[4].Text = sDeltaTime.Substring(0, 5); - else ResultView.Items[i].SubItems[4].Text = sDeltaTime; - ResultView.Items[i].ForeColor = System.Drawing.Color.Red; - ResultView.EnsureVisible(i); - ResultView.Update(); - Application.DoEvents(); - ResultView.Items[i].ForeColor = System.Drawing.Color.Black; - break; - } - - totalReceived++; - } - } - } - - if (totalReceived < URLNamescount) - { - goto more; - } - } - } - catch (SocketException e) - { - if (Convert.ToString(e).IndexOf("time") > 0) - { - StatusBoxPrint("Timeout - No response received for " + Convert.ToString(DNSReceiveTimeout / 1000) + " seconds"); - } - else - { - StatusBoxPrint(Convert.ToString(e)); // for testing - } - } - finally - { - // close the socket - DNSsocket.Close(); - } - - } + dnsEndpoint2 = null; + if (chkDns2.Checked && !string.IsNullOrWhiteSpace(dnsAddress2)) + { + dnsEndpoint2 = new IPEndPoint(IPAddress.Parse(dnsAddress2), ipPort); + } + } private async void btnResolveIP_Click(object sender, EventArgs e) { - if (string.IsNullOrWhiteSpace(txtResolveIP.Text)) - { - MessageBox.Show("Please enter an IP address to resolve"); - return; - } - - if (!IPAddress.TryParse(txtResolveIP.Text , out IPAddress iPAddress)) - { - MessageBox.Show("Please enter a valid IP address"); - return; + if (string.IsNullOrWhiteSpace(txtResolveIP.Text)) + { + MessageBox.Show("Please enter an IP address to resolve"); + return; } - try - { - await Task.Run(() => - { - var dnsEntry = Dns.GetHostEntry(iPAddress); - Dispatcher.CurrentDispatcher.Invoke(() => - { - txtResolveHost.Text = dnsEntry.HostName; - }); + if (!IPAddress.TryParse(txtResolveIP.Text, out IPAddress iPAddress)) + { + MessageBox.Show("Please enter a valid IP address"); + return; + } + + try + { + await Task.Run(() => + { + var dnsEntry = Dns.GetHostEntry(iPAddress); + txtResolveHost.Invoke(() => + { + txtResolveHost.Text = dnsEntry.HostName; + }); }); - } - catch (Exception) - { - MessageBox.Show($"Could not get hostname for IP address '{txtResolveIP.Text}'"); - } + } + catch (Exception) + { + MessageBox.Show($"Could not get hostname for IP address '{txtResolveIP.Text}'"); + } } private async void btnResolveHost_Click(object sender, EventArgs e) @@ -494,15 +305,15 @@ namespace EonaCat.DnsTester try { - await Task.Run(() => - { - var dnsEntry = Dns.GetHostEntry(txtResolveHost.Text); + await Task.Run(() => + { + var dnsEntry = Dns.GetHostEntry(txtResolveHost.Text); - Dispatcher.CurrentDispatcher.Invoke(() => - { - txtResolveIP.Text = dnsEntry.AddressList.Where(x => x.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault().Address.ToString(); - }); - }); + txtResolveHost.Invoke(() => + { + txtResolveIP.Text = dnsEntry.AddressList.Where(x => x.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault().Address.ToString(); + }); + }); } catch (Exception) { @@ -510,17 +321,17 @@ namespace EonaCat.DnsTester } } - private void StatusBoxPrint(string LogText) - { - StatusBox.Items.Add(DateTime.Now + " " + LogText); - StatusBox.TopIndex = StatusBox.Items.Count - 1; - if (StatusBox.Items.Count > 5000) - { - StatusBox.Items.RemoveAt(0); - } - StatusBox.Update(); - } + private void SetStatus(string text) + { + StatusBox.Items.Add($"{DateTime.Now} {text}"); + StatusBox.TopIndex = StatusBox.Items.Count - 1; + if (StatusBox.Items.Count > STATUS_BAR_SIZE) + { + StatusBox.Items.RemoveAt(0); + } + StatusBox.Update(); + } - - } + const int STATUS_BAR_SIZE = 5000; + } }