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
232 lines (198 loc) · 8.98 KB
/
Copy pathDNSClient.cs
File metadata and controls
232 lines (198 loc) · 8.98 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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
using DnsClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using log4net;
namespace NETworkManager.Utilities;
public class DNSClient : SingletonBase<DNSClient>
{
private static readonly ILog Log = LogManager.GetLogger(typeof(DNSClient));
/// <summary>
/// Error message which is returned when the DNS client is not configured.
/// </summary>
private const string NotConfiguredMessage = "DNS client is not configured. Call Configure() first.";
/// <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>
/// Store the current DNS settings.
/// </summary>
private DNSClientSettings _settings;
/// <summary>
/// Method to configure the DNS client.
/// </summary>
/// <param name="settings"></param>
public void Configure(DNSClientSettings settings)
{
_settings = settings;
Log.Debug("Configure - Configuring DNS client...");
if (_settings.UseCustomDNSServers)
{
Log.Debug("Configure - Using custom DNS servers...");
// Setup custom DNS servers
List<NameServer> servers = [];
foreach (var (server, port) in _settings.DNSServers)
{
Log.Debug($"Configure - Adding custom DNS server: {server}:{port}");
servers.Add(new IPEndPoint(IPAddress.Parse(server), port));
}
Log.Debug("Configure - Creating LookupClient with custom DNS servers...");
_client = new LookupClient(new LookupClientOptions(servers.ToArray()));
}
else
{
Log.Debug("Configure - Creating LookupClient with Windows default DNS servers...");
_client = new LookupClient();
}
Log.Debug("Configure - DNS client configured.");
_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 UpdateWindowsDNSSever()
{
Log.Debug("UpdateWindowsDNSSever - Recreating LookupClient with with Windows default DNS servers...");
_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();
return record != null
? new DNSClientResultIPAddress(record.Address, $"{result.NameServer}")
: 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);
}
catch (Exception ex)
{
Log.Error($"Error while resolving A record (Query string is \"{query}\".", 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();
return record != null
? new DNSClientResultIPAddress(record.Address, $"{result.NameServer}")
: 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);
}
catch (Exception ex)
{
Log.Error($"Error while resolving AAAA record (Query string is \"{query}\".", 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();
return record != null
? new DNSClientResultString(record.CanonicalName, $"{result.NameServer}")
: 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);
}
catch (Exception ex)
{
Log.Error($"Error while resolving CNAME record (Query string is \"{query}\".", 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();
return record != null
? new DNSClientResultString(record.PtrDomainName, $"{result.NameServer}")
: 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);
}
catch (Exception ex)
{
Log.Error($"Error while resolving PTR record (IP address is \"{ipAddress}\".", ex);
return new DNSClientResultString(true, ex.Message);
}
}
}