指定在.NET中用于解析主机名的DNS服务器

我想知道是否有办法强制System.Net.Dns类使用一组自定义DNS服务器来解析主机名,而不是使用与主网络连接相关联的服务器。

我怀疑这只能使用像DnDns( http://dndns.codeplex.com )这样的自定义库,但我希望这可以在.NET中完成。

不能用.Net Framework做到这一点。 Dns.Resolve方法依赖于内部Win32 API,后者又通过与网络连接关联的DNS服务器。

为了使其工作,您必须更改与网络适配器地址关联的DNS服务器。

您可以使用“JH Software的.NET Client for .NET”执行此操作 – 而无需更改DNS本地服务器。 请参阅http://www.simpledns.com/dns-client-lib.aspx上的第二个代码示例

测试.net标准:

public static async Task GetHostEntryAsync(string host, string dns = null) { if (string.IsNullOrEmpty(host)) { return null; } //Check if any cached result exists Tuple key = new Tuple(host, dns); if (NetHelper._dnsCache.TryGetValue(key, out Tuple record) && record.Item2 > DateTime.Now) { return record.Item1; } //Check dns server's address or port IPHostEntry result = null; int dnsPort; if (dns != null) { string[] blocks = dns.Split(':'); if (blocks.Length == 2 && int.TryParse(blocks[1], out dnsPort))//dns is ip v4 { dns = blocks[0]; } else if (blocks.Length == 9 && int.TryParse(blocks[8], out dnsPort))//dns is ip v6 { blocks[0] = blocks[0].TrimStart('['); blocks[7] = blocks[7].TrimStart(']'); dns = string.Format("{0}:{1}:{2}:{3}:{4}:{5}:{6}:{7}", blocks); } else { dnsPort = 53; } } else { dnsPort = 53; } //Check if host is ip address if (host[0] == '[' && host[host.Length - 1] == ']')//IPV6 address { host = host.Substring(1, host.Length - 2); } if (IPAddress.TryParse(host, out IPAddress address)) { result = new IPHostEntry { AddressList = new IPAddress[] { address } }; } else if (string.IsNullOrEmpty(dns)) { result = await Dns.GetHostEntryAsync(host); } else { #region Resolve with customized dns server IPAddress dnsAddr; if (!IPAddress.TryParse(dns, out dnsAddr)) { throw new ArgumentException("The dns host must be ip address.", nameof(dns)); } using (MemoryStream ms = new MemoryStream()) { Random rnd = new Random(); //About the dns message:http://www.ietf.org/rfc/rfc1035.txt //Write message header. ms.Write(new byte[] { (byte)rnd.Next(0, 0xFF),(byte)rnd.Next(0, 0xFF), 0x01, 0x00, 0x00,0x01, 0x00,0x00, 0x00,0x00, 0x00,0x00 }, 0, 12); //Write the host to query. foreach (string block in host.Split('.')) { byte[] data = Encoding.UTF8.GetBytes(block); ms.WriteByte((byte)data.Length); ms.Write(data, 0, data.Length); } ms.WriteByte(0);//The end of query, muest 0(null string) //Query type:A ms.WriteByte(0x00); ms.WriteByte(0x01); //Query class:IN ms.WriteByte(0x00); ms.WriteByte(0x01); Socket socket = new Socket(SocketType.Dgram, ProtocolType.Udp); try { //send to dns server byte[] buffer = ms.ToArray(); while (socket.SendTo(buffer, 0, buffer.Length, SocketFlags.None, new IPEndPoint(dnsAddr, dnsPort)) < buffer.Length) ; buffer = new byte[0x100]; EndPoint ep = socket.LocalEndPoint; int num = socket.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref ep); //The response message has the same header and question structure, so we move index to the answer part directly. int index = (int)ms.Length; //Parse response records. void SkipName() { while (index < num) { int length = buffer[index++]; if (length == 0) { break; } else if (length > 191) { return; } index += length; } } List addresses = new List(); while (index < num) { SkipName();//Seems the name of record is useless in this scense, so we just needs to get the next index after name. byte type = buffer[index += 2]; index += 7;//Skip class and ttl int length = buffer[index++] << 8 | buffer[index++];//Get record data's length if (type == 0x01)//A record { if (length == 4)//Parse record data to ip v4, this is what we need. { addresses.Add(new IPAddress(new byte[] { buffer[index], buffer[index + 1], buffer[index + 2], buffer[index + 3] })); } } index += length; } result = new IPHostEntry { AddressList = addresses.ToArray() }; } finally { socket.Dispose(); } } #endregion } //Cache and return result NetHelper._dnsCache[key] = new Tuple(result, DateTime.Now.AddMinutes(15)); #pragma warning disable CS4014 Task.Run(async () => { await Task.Delay((int)TimeSpan.FromMinutes(15).TotalMilliseconds); NetHelper._dnsCache.Remove(key); }); #pragma warning restore CS4014 return result; } 

如果您能够在docker容器中运行应用程序,则可以在启动时提供dns服务器ip地址。

docker run --dns=1.2.3.4 repo/myimage command.exe

https://docs.docker.com/v17.09/engine/userguide/networking/configure-dns/