forked from BornToBeRoot/NETworkManager
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDNSClient.cs
More file actions
200 lines (167 loc) · 7.53 KB
/
Copy pathDNSClient.cs
File metadata and controls
200 lines (167 loc) · 7.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
using DnsClient;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace NETworkManager.Utilities;
public class DNSClient : SingletonBase<DNSClient>
{
/// <summary>
/// Error message which is returned when the DNS client is not configured.
/// </summary>
private static string _notConfiguredMessage = "DNS client is not configured. Call Configure() first.";
/// <summary>
/// Store the current DNS settings.
/// </summary>
private DNSClientSettings _settings;
/// <summary>
/// Hold the current instance of the LookupClient.
/// </summary>
private LookupClient _client;
/// <summary>
/// Indicates if the DNS client is configured.
/// </summary>
private bool _isConfigured;
/// <summary>
/// Method to configure the DNS client.
/// </summary>
/// <param name="settings"></param>
public void Configure(DNSClientSettings settings)
{
_settings = settings;
if (_settings.UseCustomDNSServers)
{
// Setup custom DNS servers
List<NameServer> servers = new();
foreach (var (Server, Port) in _settings.DNSServers)
servers.Add(new IPEndPoint(IPAddress.Parse(Server), Port));
_client = new LookupClient(new LookupClientOptions(servers.ToArray())
{
});
}
else
{
UpdateFromWindows();
}
_isConfigured = true;
}
/// <summary>
/// Method to update the (Windows) name servers of the DNS client
/// when they may have changed due to a network update.
/// </summary>
public void UpdateFromWindows()
{
// Default (Windows) settings
if (_settings.UseCustomDNSServers)
return;
_client = new LookupClient();
}
/// <summary>
/// Resolve an IPv4 address from a hostname or FQDN.
/// </summary>
/// <param name="query">Hostname or FQDN as string like "example.com".</param>
/// <returns><see cref="IPAddress"/> of the host.</returns>
public async Task<DNSClientResultIPAddress> ResolveAAsync(string query)
{
if (!_isConfigured)
throw new DNSClientNotConfiguredException(_notConfiguredMessage);
try
{
var result = await _client.QueryAsync(query, QueryType.A);
// Pass the error we got from the lookup client (dns server).
if (result.HasError)
return new DNSClientResultIPAddress(result.HasError, result.ErrorMessage, $"{result.NameServer}");
// Validate result because of https://github.com/BornToBeRoot/NETworkManager/issues/1934
var record = result.Answers.ARecords().FirstOrDefault();
if (record != null)
return new DNSClientResultIPAddress(record.Address, $"{result.NameServer}");
else
return new DNSClientResultIPAddress(true, $"IP address for \"{query}\" could not be resolved and the DNS server did not return an error. Try to check your DNS server with: dig @{result.NameServer.Address} {query}", $"{result.NameServer}");
}
catch (DnsResponseException ex)
{
return new DNSClientResultIPAddress(true, ex.Message);
}
}
/// <summary>
/// Resolve an IPv6 address from a hostname or FQDN.
/// </summary>
/// <param name="query">Hostname or FQDN as string like "example.com".</param>
/// <returns><see cref="IPAddress"/> of the host.</returns>
public async Task<DNSClientResultIPAddress> ResolveAaaaAsync(string query)
{
if (!_isConfigured)
throw new DNSClientNotConfiguredException(_notConfiguredMessage);
try
{
var result = await _client.QueryAsync(query, QueryType.AAAA);
// Pass the error we got from the lookup client (dns server).
if (result.HasError)
return new DNSClientResultIPAddress(result.HasError, result.ErrorMessage, $"{result.NameServer}");
// Validate result because of https://github.com/BornToBeRoot/NETworkManager/issues/1934
var record = result.Answers.AaaaRecords().FirstOrDefault();
if (record != null)
return new DNSClientResultIPAddress(record.Address, $"{result.NameServer}");
else
return new DNSClientResultIPAddress(true, $"IP address for \"{query}\" could not be resolved and the DNS server did not return an error. Try to check your DNS server with: dig @{result.NameServer.Address} {query}", $"{result.NameServer}");
}
catch (DnsResponseException ex)
{
return new DNSClientResultIPAddress(true, ex.Message);
}
}
/// <summary>
/// Resolve a CNAME from a hostname or FQDN.
/// </summary>
/// <param name="query">Hostname or FQDN as string like "example.com".</param>
/// <returns>CNAME of the host.</returns>
public async Task<DNSClientResultString> ResolveCnameAsync(string query)
{
if (!_isConfigured)
throw new DNSClientNotConfiguredException(_notConfiguredMessage);
try
{
var result = await _client.QueryAsync(query, QueryType.CNAME);
// Pass the error we got from the lookup client (dns server).
if (result.HasError)
return new DNSClientResultString(result.HasError, result.ErrorMessage, $"{result.NameServer}");
// Validate result because of https://github.com/BornToBeRoot/NETworkManager/issues/1934
var record = result.Answers.CnameRecords().FirstOrDefault();
if (record != null)
return new DNSClientResultString(record.CanonicalName, $"{result.NameServer}");
else
return new DNSClientResultString(true, $"CNAME for \"{query}\" could not be resolved and the DNS server did not return an error. Try to check your DNS server with: dig @{result.NameServer.Address} {query}", $"{result.NameServer}");
}
catch (DnsResponseException ex)
{
return new DNSClientResultString(true, ex.Message);
}
}
/// <summary>
/// Resolve a PTR for an IP address.
/// </summary>
/// <param name="ipAddress">IP address of the host.</param>
/// <returns>PTR domain name.</returns>
public async Task<DNSClientResultString> ResolvePtrAsync(IPAddress ipAddress)
{
if (!_isConfigured)
throw new DNSClientNotConfiguredException(_notConfiguredMessage);
try
{
var result = await _client.QueryReverseAsync(ipAddress);
// Pass the error we got from the lookup client (dns server).
if (result.HasError)
return new DNSClientResultString(result.HasError, result.ErrorMessage, $"{result.NameServer}");
// Validate result because of https://github.com/BornToBeRoot/NETworkManager/issues/1934
var record = result.Answers.PtrRecords().FirstOrDefault();
if (record != null)
return new DNSClientResultString(record.PtrDomainName, $"{result.NameServer}");
else
return new DNSClientResultString(true, $"PTR for \"{ipAddress}\" could not be resolved and the DNS server did not return an error. Try to check your DNS server with: dig @{result.NameServer.Address} -x {ipAddress}", $"{result.NameServer}");
}
catch (DnsResponseException ex)
{
return new DNSClientResultString(true, ex.Message);
}
}
}