338 lines
11 KiB
C#
338 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.IO;
|
|
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 EonaCat.DnsTester.Helpers;
|
|
|
|
namespace EonaCat.DnsTester
|
|
{
|
|
public partial class MainForm : Form
|
|
{
|
|
private bool useCustomDnsServers;
|
|
private string _dnsServer1, _dnsServer2;
|
|
private int _dnsTotalChecked;
|
|
|
|
public bool IsRunning { get; private set; }
|
|
|
|
public MainForm()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
private void RunTest_Click(object sender, EventArgs e)
|
|
{
|
|
List<string> urls = new List<string>();
|
|
SetupUrls(urls);
|
|
|
|
if (IsRunning)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IsRunning = true;
|
|
Process(urls.ToArray(), _dnsServer1, _dnsServer2);
|
|
IsRunning = false;
|
|
}
|
|
|
|
private void SetupUrls(List<string> urls)
|
|
{
|
|
if (useCustomDnsServers)
|
|
{
|
|
_dnsTotalChecked = 0;
|
|
if (chkDns1.Checked)
|
|
{
|
|
_dnsTotalChecked++;
|
|
_dnsServer1 = CustomDns1.Text;
|
|
}
|
|
|
|
if (chkDns2.Checked)
|
|
{
|
|
_dnsTotalChecked++;
|
|
_dnsServer2 = CustomDns2.Text;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_dnsTotalChecked = 0;
|
|
if (chkDns1.Checked)
|
|
{
|
|
_dnsTotalChecked++;
|
|
_dnsServer1 = dnsList1.SelectedValue.ToString();
|
|
}
|
|
|
|
if (chkDns2.Checked)
|
|
{
|
|
_dnsTotalChecked++;
|
|
_dnsServer2 = dnsList2.SelectedValue.ToString();
|
|
}
|
|
|
|
}
|
|
|
|
ResultView.Items.Clear();
|
|
ResultView.Update();
|
|
Application.DoEvents();
|
|
|
|
UrlHelper.Log += UrlHelper_Log;
|
|
UrlHelper.GetRandomUrls(ref urls, (int)numericUpDown1.Value);
|
|
AddUrlToView(urls);
|
|
}
|
|
|
|
private void UrlHelper_Log(object sender, string e)
|
|
{
|
|
SetStatus(e);
|
|
}
|
|
|
|
private void AddUrlToView(List<string> 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(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)
|
|
{
|
|
useCustomDnsServers = UseCustomServers.Checked;
|
|
SetUI();
|
|
}
|
|
|
|
private void SetUI()
|
|
{
|
|
if (useCustomDnsServers)
|
|
{
|
|
dnsList1.Enabled = false;
|
|
dnsList2.Enabled = false;
|
|
|
|
CustomDns1.Enabled = true;
|
|
CustomDns2.Enabled = true;
|
|
|
|
CustomDns1.Visible = true;
|
|
CustomDns2.Visible = true;
|
|
lblCustom1.Visible = true;
|
|
lblCustom2.Visible = true;
|
|
|
|
}
|
|
else
|
|
{
|
|
dnsList1.Enabled = true;
|
|
dnsList2.Enabled = true;
|
|
CustomDns1.Enabled = false;
|
|
CustomDns2.Enabled = false;
|
|
|
|
CustomDns1.Visible = false;
|
|
CustomDns2.Visible = false;
|
|
lblCustom1.Visible = false;
|
|
lblCustom2.Visible = false;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
private void Process(string[] urls, string dnsAddress1, string dnsAddress2)
|
|
{
|
|
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++)
|
|
{
|
|
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 DnsHelper_Log(object sender, string e)
|
|
{
|
|
SetStatus(e);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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}'");
|
|
}
|
|
}
|
|
|
|
private async void btnResolveHost_Click(object sender, EventArgs e)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(txtResolveHost.Text))
|
|
{
|
|
MessageBox.Show("Please enter an hostname to resolve");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
await Task.Run(() =>
|
|
{
|
|
var dnsEntry = Dns.GetHostEntry(txtResolveHost.Text);
|
|
|
|
txtResolveHost.Invoke(() =>
|
|
{
|
|
txtResolveIP.Text = dnsEntry.AddressList.Where(x => x.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault().Address.ToString();
|
|
});
|
|
});
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show($"Could not get hostname for IP address '{txtResolveIP.Text}'");
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|