A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始



  1.     class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             GFWDnsResolver dnsResolver = GFWDnsResolver.Instance();
  6.             string domain = "www.google.com";
  7.             string ip = dnsResolver.GFWResolve(domain);
  8.             Console.WriteLine(ip + "    " + domain);
  9.             Console.ReadKey();
  10.         }
  11.     }

  12.     public class GFWDnsResolver
  13.     {
  14.         private static GFWDnsResolver resolver = null;
  15.          
  16.         private static string DNS_SERVER = "8.8.8.8";

  17.         private Encoding coding = Encoding.UTF8;

  18.         private bool debug = false;
  19.         private bool cache = false;

  20.         private int maxTryTimes = 2;
  21.         private int waitTimes = 3;

  22.         private Dictionary<string, string> dnsCache = new Dictionary<string, string>();

  23.         string[] blackList = {
  24.             "74.125.127.102", "74.125.155.102", "74.125.39.102", "74.125.39.113",
  25.              "209.85.229.138",
  26.              "128.121.126.139", "159.106.121.75", "169.132.13.103", "192.67.198.6",
  27.              "202.106.1.2", "202.181.7.85", "203.161.230.171", "203.98.7.65",
  28.              "207.12.88.98", "208.56.31.43", "209.145.54.50", "209.220.30.174",
  29.              "209.36.73.33", "211.94.66.147", "213.169.251.35", "216.221.188.182",
  30.              "216.234.179.13", "243.185.187.39", "37.61.54.158", "4.36.66.178",
  31.              "46.82.174.68", "59.24.3.173", "64.33.88.161", "64.33.99.47",
  32.              "64.66.163.251", "65.104.202.252", "65.160.219.113", "66.45.252.237",                                                                                                                           
  33.              "72.14.205.104", "72.14.205.99", "78.16.49.15", "8.7.198.45", "93.46.8.89"};

  34.         public static GFWDnsResolver Instance()
  35.         {
  36.             if (resolver == null)
  37.             {
  38.                 resolver = new GFWDnsResolver();
  39.             }
  40.             return resolver;
  41.         }

  42.         private GFWDnsResolver() { }

  43.         private bool IsBadReply(string ip)
  44.         {
  45.             for (int i = 0; i < blackList.Length; i++)
  46.             {
  47.                 if (blackList[i].Equals(ip))
  48.                 {
  49.                     return true;
  50.                 }
  51.             }
  52.             return false;
  53.         }

  54.         public string GFWResolve(string domain)
  55.         {
  56.             IPAddress[] address = Dns.GetHostAddresses(domain);
  57.             string ip = address[0].ToString();
  58.             if (!IsBadReply(ip))
  59.             {
  60.                 return ip;
  61.             }
  62.             else if (cache && dnsCache.ContainsKey(domain))
  63.             {
  64.                 return dnsCache[domain];
  65.             }

  66.             for (int i = 0; i < maxTryTimes; i++)
  67.             {
  68.                 ip = Resolve(domain);
  69.                 if (IsBadReply(ip) || ip == null)
  70.                 {
  71.                     continue;
  72.                 }
  73.                 else
  74.                 {
  75.                     if (cache)
  76.                     {
  77.                         dnsCache.Add(domain, ip);
  78.                     }
  79.                     return ip;
  80.                 }
  81.             }
  82.             return string.Empty;
  83.         }

  84.         private void HexDump(byte[] bytes)
  85.         {
  86.             Console.WriteLine(BytesToHex(bytes));
  87.         }

  88.         private string BytesToHex(byte[] bytes)
  89.         {
  90.             StringBuilder sb = new StringBuilder();
  91.             for (int i = 0; i < bytes.Length; i++)
  92.             {
  93.                 sb.AppendFormat("{0:X2}", bytes[i]);
  94.             }

  95.             string hex = sb.ToString();
  96.             return hex;
  97.         }

  98.         private string Resolve(string domain)
  99.         {
  100.             byte[] recvData = new byte[512];
  101.             byte[] data = BuildRequestData(domain);
  102.             string result = null;
  103.             if (debug)
  104.             {
  105.                 Console.WriteLine("dns query request package dump:");
  106.                 HexDump(data);
  107.             }

  108.             IPEndPoint iep = new IPEndPoint(IPAddress.Parse(DNS_SERVER), 53);
  109.             Socket dataSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  110.             dataSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 6 * 1000);
  111.             dataSocket.SendTo(data, iep);

  112.             byte[] respData = new byte[512];
  113.             for (int i = 0; i < waitTimes; i++)
  114.             {
  115.                 try
  116.                 {
  117.                     int intReceived = dataSocket.Receive(respData);
  118.                     byte[] dataReceive = new byte[intReceived];
  119.                     Array.Copy(respData, dataReceive, intReceived);

  120.                     if (debug)
  121.                     {
  122.                         Console.WriteLine("============ dns query answer package dump");
  123.                         HexDump(dataReceive);
  124.                     }

  125.                     string ip = DecodeDnsResponse(dataReceive, domain);
  126.                     if (IsBadReply(ip))
  127.                     {
  128.                         continue;
  129.                     }
  130.                     else
  131.                     {
  132.                         result = ip;
  133.                         break;
  134.                     }
  135.                 }
  136.                 catch (SocketException ex)
  137.                 {
  138.                     throw ex;
  139.                 }
  140.             }

  141.             dataSocket.Close();
  142.             return result;
  143.         }

  144.         private byte[] BuildRequestData(string host)
  145.         {
  146.             // head + (host length +1) + eof sign + qtype + qclass
  147.             int size = 12 + host.Length + 1 + 1 + 4;
  148.             using (MemoryStream buff = new MemoryStream(size))
  149.             {
  150.                 byte[] tmp = null;

  151.                 Random random = new Random();
  152.                 byte[] seq = new byte[2];
  153.                 random.NextBytes(seq);
  154.                 buff.Write(seq, 0, seq.Length);

  155.                 byte[] header = new byte[] { 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  156.                 buff.Write(header, 0, header.Length);

  157.                 string[] parts = host.Split('.');
  158.                 for (int i = 0; i < parts.Length; i++)
  159.                 {
  160.                     buff.WriteByte((byte)parts[i].Length);

  161.                     byte[] partsByte = coding.GetBytes(parts[i]);
  162.                     buff.Write(partsByte, 0, partsByte.Length);
  163.                 }

  164.                 tmp = new byte[] { 0x00 };
  165.                 buff.Write(tmp, 0, tmp.Length);

  166.                 tmp = new byte[] { 0x00, 0x01, 0x00, 0x01 };
  167.                 buff.Write(tmp, 0, tmp.Length);

  168.                 return buff.ToArray();
  169.             }
  170.         }

  171.         private string DecodeDnsResponse(byte[] resp, string host)
  172.         {
  173.             using (MemoryStream stream = new MemoryStream(resp))
  174.             {
  175.                 using (BinaryReader buffer = new BinaryReader(stream))
  176.                 {
  177.                     //parse the query answer count.
  178.                     int pos = 7;
  179.                     stream.Position = pos;
  180.                     ushort qncount = buffer.ReadUInt16();

  181.                     //skip query answer field
  182.                     pos = 12 + 1 + host.Length + 1 + 4;
  183.                     stream.Position = pos;
  184.                     for (int i = 0; i < qncount; i++)
  185.                     {
  186.                         stream.Position = pos;
  187.                         byte pointFlg = buffer.ReadByte();
  188.                         if ((pointFlg & 0xc0) == 0xc0)
  189.                         {
  190.                             pos += 3;
  191.                         }
  192.                         else
  193.                         {
  194.                             pos += 2 + host.Length + 1;
  195.                         }

  196.                         stream.Position = pos;
  197.                         ushort queryType = buffer.ReadUInt16();

  198.                         if (debug)
  199.                         {
  200.                             Console.WriteLine("qncount:" + qncount + "pos:" + pos + "queryType:" + queryType);
  201.                         }

  202.                         pos += 8;
  203.                         stream.Position = pos;
  204.                         int dataLen = buffer.ReadByte();
  205.                         pos += 1;

  206.                         //A record
  207.                         if (queryType == 0x0001)
  208.                         {
  209.                             if (debug)
  210.                             {
  211.                                 Console.WriteLine("parse A record");
  212.                             }

  213.                             string ip = string.Empty;
  214.                             for (int j = 0; j < dataLen; j++)
  215.                             {
  216.                                 stream.Position = pos;
  217.                                 int v = buffer.ReadByte();
  218.                                 v = v > 0 ? v : 0x0ff & v;
  219.                                 ip += v + (j == dataLen - 1 ? "" : ".");
  220.                                 pos += 1;
  221.                             }
  222.                             return ip;
  223.                         }
  224.                         else
  225.                         {
  226.                             pos += dataLen;
  227.                         }
  228.                     }
  229.                     return string.Empty;
  230.                 }            
  231.             }
  232.         }
  233.     }

复制代码



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马