EonaCat.DnsTester/EonaCat.DnsTester/MainForm.cs

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;
}
}