This commit is contained in:
EonaCat 2023-03-02 10:02:06 +01:00
parent cd376044d5
commit 4afe9153ed
4 changed files with 122 additions and 77 deletions

View File

@ -146,14 +146,27 @@ namespace EonaCat.DnsTester.Helpers
{ {
Console.WriteLine("new byte[] { " + responseBytes + " }"); Console.WriteLine("new byte[] { " + responseBytes + " }");
// Check if response is valid
if (responseBytes.Length < 12)
{
throw new Exception("Invalid DNS response");
}
// Set the offset to the start // Set the offset to the start
var offset = 0; var offset = 0;
// Parse the DNS header // Parse the DNS header
ushort id = (ushort)((responseBytes[0] << 8) | responseBytes[1]); ushort id = (ushort)((responseBytes[0] << 8) | responseBytes[1]);
ushort flags = (ushort)((responseBytes[2] << 8) | responseBytes[3]); ushort flags = (ushort)((responseBytes[2] << 8) | responseBytes[3]);
bool isResponse = (flags & 0x8000) != 0;
ushort qdcount = (ushort)((responseBytes[4] << 8) | responseBytes[5]); ushort qdcount = (ushort)((responseBytes[4] << 8) | responseBytes[5]);
ushort ancount = (ushort)((responseBytes[6] << 8) | responseBytes[7]); ushort ancount = (ushort)((responseBytes[6] << 8) | responseBytes[7]);
if (!isResponse)
{
throw new Exception("Invalid DNS response");
}
ushort nscount = (ushort)((responseBytes[8] << 8) | responseBytes[9]); ushort nscount = (ushort)((responseBytes[8] << 8) | responseBytes[9]);
ushort arcount = (ushort)((responseBytes[10] << 8) | responseBytes[11]); ushort arcount = (ushort)((responseBytes[10] << 8) | responseBytes[11]);
@ -243,62 +256,53 @@ namespace EonaCat.DnsTester.Helpers
static ResourceRecord ParseDnsAnswerRecord(byte[] responseBytes, ref int offset) static ResourceRecord ParseDnsAnswerRecord(byte[] responseBytes, ref int offset)
{ {
// Parse the DNS name // Parse the DNS name
string name = DnsNameParser.ParseName(responseBytes, ref offset); string name = DnsNameParser.ExtractDomainName(responseBytes, ref offset);
if (name == null) if (name == null)
{ {
return null; return null;
} }
// Parse the DNS type, class, ttl, and data length // Parse the DNS type, class, ttl, and data length
DnsRecordType type = (DnsRecordType)((responseBytes[offset] << 8) | responseBytes[offset++]); DnsRecordType type = (DnsRecordType)((responseBytes[offset++] << 8) + responseBytes[offset++]);
DnsRecordClass klass = (DnsRecordClass)((responseBytes[offset] << 8) | responseBytes[offset++]); DnsRecordClass klass = (DnsRecordClass)((responseBytes[offset++] << 8) + responseBytes[offset++]);
uint ttl = (uint)((responseBytes[offset] << 24) | (responseBytes[offset++] << 16) | (responseBytes[offset++] << 8) | responseBytes[offset++]); int ttl = (responseBytes[offset++] << 24) + (responseBytes[offset++] << 16) + (responseBytes[offset++] << 8) + responseBytes[offset++];
ushort rdlen = (ushort)((responseBytes[offset] << 8) + responseBytes[offset++]);
offset += 10;
// Parse the DNS data // Extract record data length
string data = null; int dataLength = (responseBytes[offset] << 8) + responseBytes[offset + 1];
offset += 2;
// Extract record data
byte[] recordData = new byte[dataLength];
Buffer.BlockCopy(responseBytes, offset, recordData, 0, dataLength);
string recordDataAsString = null;
switch ((DnsRecordType)type) switch ((DnsRecordType)type)
{ {
case DnsRecordType.A: case DnsRecordType.A:
if (rdlen != 4) if (dataLength != 4)
{ {
return null; return null;
} }
recordDataAsString = new IPAddress(recordData).ToString();
data = new IPAddress(new byte[] offset += recordData.Length;
{
responseBytes[offset], responseBytes[offset + 1], responseBytes[offset + 2],
responseBytes[offset + 3]
}).ToString();
offset += rdlen;
break; break;
case DnsRecordType.CNAME: case DnsRecordType.CNAME:
recordDataAsString = DnsNameParser.ExtractDomainName(responseBytes, ref offset);
break;
case DnsRecordType.NS: case DnsRecordType.NS:
data = DnsNameParser.ParseName(responseBytes, ref offset); recordDataAsString = DnsNameParser.ExtractDomainName(responseBytes, ref offset);
if (data == null)
{
return null;
}
break; break;
case DnsRecordType.MX: case DnsRecordType.MX:
ushort preference = (ushort)((responseBytes[offset] << 8) | responseBytes[offset + 1]); int preference = (responseBytes[0] << 8) + responseBytes[1];
offset += 2; offset += 2;
string exchange = DnsNameParser.ParseName(responseBytes, ref offset); string exchange = DnsNameParser.ExtractDomainName(responseBytes, ref offset);
if (exchange == null) recordDataAsString = $"{preference} {exchange}";
{
return null;
}
data = $"{preference} {exchange}";
break; break;
case DnsRecordType.TXT: case DnsRecordType.TXT:
data = Encoding.ASCII.GetString(responseBytes, offset, rdlen); recordDataAsString = Encoding.ASCII.GetString(recordData);
offset += rdlen;
break; break;
default: default:
offset += rdlen; offset += dataLength;
break; break;
} }
@ -308,7 +312,7 @@ namespace EonaCat.DnsTester.Helpers
Type = type, Type = type,
Class = klass, Class = klass,
Ttl = TimeSpan.FromSeconds(ttl), Ttl = TimeSpan.FromSeconds(ttl),
Data = data, Data = recordDataAsString,
}; };
} }
@ -358,7 +362,7 @@ namespace EonaCat.DnsTester.Helpers
{ {
A = 1, A = 1,
NS = 2, NS = 2,
CNAME = 5, CNAME = 6,
MX = 15, MX = 15,
TXT = 16, TXT = 16,
AAAA = 28, AAAA = 28,

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
namespace EonaCat.DnsTester.Helpers namespace EonaCat.DnsTester.Helpers
{ {
@ -29,5 +30,34 @@ namespace EonaCat.DnsTester.Helpers
return string.Join(".", labels); return string.Join(".", labels);
} }
public static string ExtractDomainName(byte[] buffer, ref int offset)
{
List<string> labels = new List<string>();
while (true)
{
byte labelLength = buffer[offset++];
if (labelLength == 0)
{
break;
}
if ((labelLength & 0xC0) == 0xC0)
{
// Compressed domain name
int pointer = (int)(((labelLength & 0x3F) << 8) + buffer[offset++]);
labels.Add(ExtractDomainName(buffer, ref pointer));
break;
}
string label = Encoding.ASCII.GetString(buffer, offset, labelLength);
labels.Add(label);
offset += labelLength;
}
return string.Join(".", labels);
}
} }
} }

View File

@ -49,9 +49,9 @@
StatusBox = new System.Windows.Forms.ListBox(); StatusBox = new System.Windows.Forms.ListBox();
ResultView = new System.Windows.Forms.ListView(); ResultView = new System.Windows.Forms.ListView();
Url = new System.Windows.Forms.ColumnHeader(); Url = new System.Windows.Forms.ColumnHeader();
DNS1IP = new System.Windows.Forms.ColumnHeader(); DNS1DATA = new System.Windows.Forms.ColumnHeader();
DNS1Performance = new System.Windows.Forms.ColumnHeader(); DNS1Performance = new System.Windows.Forms.ColumnHeader();
DNS2IP = new System.Windows.Forms.ColumnHeader(); DNS2DATA = new System.Windows.Forms.ColumnHeader();
DNS2Performance = new System.Windows.Forms.ColumnHeader(); DNS2Performance = new System.Windows.Forms.ColumnHeader();
panel3 = new System.Windows.Forms.Panel(); panel3 = new System.Windows.Forms.Panel();
btnResolveHost = new System.Windows.Forms.Button(); btnResolveHost = new System.Windows.Forms.Button();
@ -273,7 +273,7 @@
// //
// ResultView // ResultView
// //
ResultView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { Url, DNS1IP, DNS1Performance, DNS2IP, DNS2Performance }); ResultView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { Url, DNS1DATA, DNS1Performance, DNS2DATA, DNS2Performance });
ResultView.GridLines = true; ResultView.GridLines = true;
ResultView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; ResultView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
ResultView.Location = new System.Drawing.Point(56, 49); ResultView.Location = new System.Drawing.Point(56, 49);
@ -290,27 +290,27 @@
Url.Text = "URL"; Url.Text = "URL";
Url.Width = 160; Url.Width = 160;
// //
// DNS1IP // DNS1DATA
// //
DNS1IP.Text = "IP Address from DNS 1"; DNS1DATA.Text = "Data";
DNS1IP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; DNS1DATA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
DNS1IP.Width = 140; DNS1DATA.Width = 140;
// //
// DNS1Performance // DNS1Performance
// //
DNS1Performance.Text = "DNS 1 Performance"; DNS1Performance.Text = "Performance";
DNS1Performance.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; DNS1Performance.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
DNS1Performance.Width = 120; DNS1Performance.Width = 120;
// //
// DNS2IP // DNS2DATA
// //
DNS2IP.Text = "IP Address from DNS 2"; DNS2DATA.Text = "Data";
DNS2IP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; DNS2DATA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
DNS2IP.Width = 140; DNS2DATA.Width = 140;
// //
// DNS2Performance // DNS2Performance
// //
DNS2Performance.Text = "DNS 2 Performance"; DNS2Performance.Text = "Performance";
DNS2Performance.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; DNS2Performance.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
DNS2Performance.Width = 120; DNS2Performance.Width = 120;
// //
@ -428,9 +428,9 @@
private System.Windows.Forms.ListBox StatusBox; private System.Windows.Forms.ListBox StatusBox;
private System.Windows.Forms.ListView ResultView; private System.Windows.Forms.ListView ResultView;
private System.Windows.Forms.ColumnHeader Url; private System.Windows.Forms.ColumnHeader Url;
private System.Windows.Forms.ColumnHeader DNS1IP; private System.Windows.Forms.ColumnHeader DNS1DATA;
private System.Windows.Forms.ColumnHeader DNS1Performance; private System.Windows.Forms.ColumnHeader DNS1Performance;
private System.Windows.Forms.ColumnHeader DNS2IP; private System.Windows.Forms.ColumnHeader DNS2DATA;
private System.Windows.Forms.ColumnHeader DNS2Performance; private System.Windows.Forms.ColumnHeader DNS2Performance;
private System.Windows.Forms.Panel panel3; private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.Button btnResolveHost; private System.Windows.Forms.Button btnResolveHost;

View File

@ -273,38 +273,49 @@ namespace EonaCat.DnsTester
var stopTime = DateTime.Now.Ticks; var stopTime = DateTime.Now.Ticks;
var deltaTime = Convert.ToString((double)(stopTime - dnsResponse.StartTime) / 10000000, CultureInfo.InvariantCulture); var deltaTime = Convert.ToString((double)(stopTime - dnsResponse.StartTime) / 10000000, CultureInfo.InvariantCulture);
SetStatus($"ResourceRecord: Name: {dnsResponse.Answers.FirstOrDefault().Name} : Type : {dnsResponse.Answers.FirstOrDefault().Type} : Data : {dnsResponse.Answers.FirstOrDefault().Data}"); foreach (var answer in dnsResponse.Answers)
{
SetStatus(
$"ResourceRecord: Name: {answer.Name} : Type : {answer.Type} : Data : {answer.Data}");
}
for (int i = 0; i < ResultView.Items.Count; i++) for (int i = 0; i < ResultView.Items.Count; i++)
{ {
if (ResultView.Items[i].Text != $"{dnsResponse.Answers.FirstOrDefault().Name.TrimEnd('.')}") continue; foreach (var answer in dnsResponse.Answers)
string sDeltaTime;
switch (dnsResponse.DnsId)
{ {
case "Dns1": if (ResultView.Items[i].Text != $"{answer.Name.TrimEnd('.')}")
ResultView.Items[i].SubItems[1].Text = Convert.ToString(dnsResponse.Answers.FirstOrDefault().Data); continue;
sDeltaTime = Convert.ToString(deltaTime);
ResultView.Items[i].SubItems[2].Text =
sDeltaTime.Length > 5 ? sDeltaTime.Substring(0, 5) : 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 "Dns2": string sDeltaTime;
ResultView.Items[i].SubItems[3].Text = Convert.ToString(dnsResponse.Answers.FirstOrDefault().Data); switch (dnsResponse.DnsId)
sDeltaTime = Convert.ToString(deltaTime); {
ResultView.Items[i].SubItems[4].Text = case "Dns1":
sDeltaTime.Length > 5 ? sDeltaTime.Substring(0, 5) : sDeltaTime; ResultView.Items[i].SubItems[1].Text =
ResultView.Items[i].ForeColor = System.Drawing.Color.Red; Convert.ToString(answer.Data);
ResultView.EnsureVisible(i); sDeltaTime = Convert.ToString(deltaTime);
ResultView.Update(); ResultView.Items[i].SubItems[2].Text =
Application.DoEvents(); sDeltaTime.Length > 5 ? sDeltaTime.Substring(0, 5) : sDeltaTime;
ResultView.Items[i].ForeColor = System.Drawing.Color.Black; ResultView.Items[i].ForeColor = System.Drawing.Color.Red;
break; ResultView.EnsureVisible(i);
ResultView.Update();
Application.DoEvents();
ResultView.Items[i].ForeColor = System.Drawing.Color.Black;
break;
case "Dns2":
ResultView.Items[i].SubItems[3].Text =
Convert.ToString(answer.Data);
sDeltaTime = Convert.ToString(deltaTime);
ResultView.Items[i].SubItems[4].Text =
sDeltaTime.Length > 5 ? sDeltaTime.Substring(0, 5) : 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;
}
} }
} }
} }