Home > database >  C# How to resolve DNS through a proxy?
C# How to resolve DNS through a proxy?

Time:08-03

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)

  • Related