I meet a trouble called Domain Pollution or DNS Cache Poisoning, so I wanna resolve the Urls to ip addresses through a proxy. I set the system proxy and using the C# code below:
Dns.GetHostEntry("example.com").AddressList[0].ToString();
But It still return a polluted ip, the same as a ping command return. I guess it didn't go through the proxy. So how should I resolve DNS through a proxy in C#?
(Environment: Windows 11, .Net5)
CodePudding user response:
can you try this:
DnsUtils.FlushCache("example.com");
public class DnsUtils
{
[DllImport("dnsapi.dll", EntryPoint="DnsFlushResolverCache")]
static extern UInt32 DnsFlushResolverCache();
[DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCacheEntry_A")]
public static extern int DnsFlushResolverCacheEntry(string hostName);
public static void FlushCache()
{
DnsFlushResolverCache();
}
public static void FlushCache(string hostName)
{
DnsFlushResolverCacheEntry(hostName);
}
}
solution from : BRIAN MANCINI - System.Net.Dns Flush Cache Issues
CodePudding user response:
Instead of using the system proxy, you can just use DoH. Since I never managed to use the library I linked in my comment, I write my own parser for the simpler JSON DoH. That API isn't standard, but there are a couple of large providers supporting it so unless they're all blocked, you should be fine.
For your requirement, I'm assuming you're only interested in resolving a domain A record (GetHostEntry would only return IPv6 address if the PC has IPv6), so you only need the name
(set to the domain you resolve) and type
parameter (either A
for IPv4 or AAAA
for IPv6). This means sending a GET request tohttps://dns.google/resolve?name=example.com&type=A
if you're using Google DNS.
From the JSON response, you're only interested in one of the Answer
nodes' data
values, so you don't actually need a proper class for all the elements. I try to find a solution that doesn't use any additional dependency, but they're either too lengthy or unreliable, so you need to add the Newtonsoft.Json
package for easy parsing.
This is what I came up with
using Newtonsoft.Json;
public class DoHJson
{
private static HttpClient Client = new HttpClient();
//reuse instead of disposing all the time https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/index.html
private static string[] Providers = new[] //add providers you can find here
{
"cloudflare-dns.com/dns-query",
"dns.nextdns.io/",
"dns.adguard.com/resolve",
"dns.google/resolve"
};
public static string GetAddress(string domain)
{
//randomize which provider to use
var provider = Providers[Random.Shared.Next(Providers.Length)];
var uri = $"https://{provider}?name={domain}&type=A";
using (var request = new HttpRequestMessage(new HttpMethod("GET"), uri))
{
request.Headers.TryAddWithoutValidation("accept", "application/dns-json");
var response = Client.Send(request);
var jsonText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
dynamic json = JsonConvert.DeserializeObject<dynamic>(jsonText);
return json.Answer[0].data;
}
}
}
Use it like DoHJson.GetAddress("example.com")
. Note that different providers may give different answers, so you can just modify the code to just use a single provider if you need a consistent answer (though technically even a single provider can give answers in a different order each time)