环境介绍:
客户端软件安装在一台处在代理环境中的PC上,通过代理上互联网,代理协议是socks4 端口1080,也提供http协议代理,端口是808,没有用户名密码验证。代理服务器上设置了DNS服务器的地址。客户端软件通过socks4代理协议,是通过域名访问服务器端的,采用C#开发.net framwork 2.0。
问题描述:
如果在PC机的网络配置上的DNS服务器上填写了代理服务器的IP地址,那么就可以正确完成域名解析连上服务器端,如果PC上的DNS服务器配置上不填,那么就无法正确解析域名,提示an invalid IP address was specified。但通过IE浏览器(配置好了http代理的相关信息)就能访问互联网上的网站。想寻求解决办法,正常来说是不用配PC上的DNS服务器地址的,但不知道用哪个方法或函数,可以实现将域名发到代理服务器,让代理服务器连接DNS服务器来解析域名,将IP地址返回到PC的客户端软件上。
下面是我们使用的解析dns的代码,从完整代码中抽取出来了:
                string ipTemp = string.Empty;
                if (!IsCorrenctIP(m_ServerIP))
                {
                    ipTemp = Dns.GetHostEntry(m_ServerIP).AddressList[0].ToString();
                    m_ServerIP = ipTemp;
                }
                if (!IsCorrenctIP(m_AssemblyServerIP))
                {
                    ipTemp =Dns.GetHostEntry(m_AssemblyServerIP).AddressList[0].ToString();
                    m_AssemblyServerIP = ipTemp;
                }
                if (!IsCorrenctIP(m_DataDownloadServerIP))
                {
                    ipTemp=Dns.GetHostEntry(m_DataDownloadServerIP).AddressList[0].ToString();
                    m_DataDownloadServerIP = ipTemp;
                }

解决方案 »

  1.   

    查了很多资料,关键找不到DNS这个类里面实现的底层里是怎样指定DNS服务器的,如果在本机的网络设置里面没有找到DNS服务器地址的话,怎么知道将这个域名解析请求发到代理服务器那边。
      

  2.   

    想到一个思路不知道对不对,在我们的代码里,先进行了域名解析,然后再去执行和代理的连接动作,这样的话在域名解析时,是不是DNS类不知道该把域名解析请求先发到代理服务器上去,由代理服务器转发出去,因此应该先进性和代理服务器的连接,再进行域名解析,就像在网上找到的一段代码一样:
    //************************************************
    //
    //重点在说明如何实现Socket5代理协议方式通讯
    //http://blog.sina.com.cn/zhujiechang
    //
    //************************************************
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    namespace sampleProxySocket
    {
        class Program
        {
            // Declare the delegate prototype to send data back to the form
            static byte[] m_byBuff = new byte[256]; // Recieved data buffer
            static void Main(string[] args)
            {
                //重点来
                try
                {
                    Console.WriteLine("socket5使用示例!");
                    string proxyAddress = "192.168.1.2";
                    int proxyPort = 1080;
                    string destAddress = "www.csdn.net";
                    int destPort = 80;
                    IPEndPoint proxyIp = new IPEndPoint(IPAddress.Parse(proxyAddress), proxyPort);
                    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                socket.Connect(proxyIp);    //代理地址                Shake_hands(socket);    //协议握手                IPEndPoint destIp = new IPEndPoint(Dns.GetHostEntry(destAddress).AddressList[0], destPort);
                    Protocol_Request(socket, destIp);   //协议请求                //正常的请求
                    SetupRecieveCallback(socket); 
                    socket.Send(Encoding.ASCII.GetBytes(
                        string.Format("GET / HTTP/1.1 \r\nAccept: */* \r\nAccept-Language: zh-cn \r\nHost:{0}\r\n\r\n",
                        destAddress)));
                                  
                    
                }
      

  3.   

    如果是HTTP代理的话 先进行域名解析  如果是TCP/IP的话 不用先解析吧!
      

  4.   

    又有一个解决思路就是因为在socks协议中可以直接发域名作为通过代理要访问的服务器的地址的,
    代理协议内容如下:和代理握手完成之后,要进行一个请求连接,这个就是对远程服务器的连接,我们知道当前既然连接的是代理服务器,我们实际上发送数据的对象并不是它,也就是我们要告诉代理服务器去连接真实的某某,现在就是在做这一步了。
    SOCKS请求的格式如下: 
    VER CMD RSV ATYP DST.ADDR DST.PROT 
    1 1 X’00’ 1 Variable 2 其中
    · VER 协议版本: X’05’
    · CMD
    · CONNECT:X’01’
    · BIND:X’02’
    · UDP ASSOCIATE:X’03’
    · RSV 保留
    · ATYP 后面的地址类型
    · IPV4:X’01’
    · 域名:X’03’
    · IPV6:X’04’'
    · DST.ADDR 目的地址
    · DST.PORT 以网络字节顺序出现的端口号
    SOCKS服务器会根据源地址和目的地址来分析请求,然后根据请求类型返回一个或多个应答。
    ATYP字段中描述了地址字段(DST.ADDR,BND.ADDR)所包含的地址类型:
    · X'01'
    基于IPV4的IP地址,4个字节长
    · X'03'
    基于域名的地址,地址字段中的第一字节是以字节为单位的该域名的长度,没有结尾的NUL字节。
    · X'04'
    基于IPV6的IP地址,16个字节长。
    Variable表示该域的长度是可变的。所以是不是可以将下面代码里面的data[3]赋值为03,然后直接用域名,向代理服务器发送向互联网上服务器的请求。
     if (proxyType == InnerCommEnum.ProxyType.PT_Socks4)//socks4代理服务
                {
                    IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(m_proxyIP), Convert.ToInt32(m_proxyPost));
                    //根据IP地址和端口号创建远程终结点
                    EndPoint endPoint = (EndPoint)ipEndPoint;
                    try
                    {
                        m_ClientMainSocket.Connect(endPoint);
                        m_ClientMainSocket.ReceiveTimeout = 10000;
                        //连接请求
                        byte[] data = new byte[9];
                        data[0] = 4;//VER 协议版本
                        data[1] = 1;//CMD CONNECT:X’01’BIND:X’02’ UDP ASSOCIATE:X’03’
                       // data[2] = 0;//RSV 保留
                      //  data[3] = 1;//ATYP 后面的地址类型 IPV4:X’01’域名:X’03’ IPV6:X’04’'                    int length = 0;
                        byte[] buff = new byte[1024];
                        IPEndPoint destIP = new IPEndPoint(IPAddress.Parse(m_ServerIP), Convert.ToInt32(m_ServerPort));
                        
                        Array.Copy(BitConverter.GetBytes(
                        IPAddress.HostToNetworkOrder(destIP.Port)), 2, data, 2, 2);//以网络字节顺序出现的端口号                    
                        Array.Copy(destIP.Address.GetAddressBytes(), 0, data, 4, 4); //DST.ADDR 目的地址
                        m_ClientMainSocket.Send(data, SocketFlags.None);
      

  5.   

    郁闷死了,用户那边用的是socks4,socks4不支持这种直接写域名访问的方式,大家有没有知道怎么发送域名解析的请求到socks4代理服务器上,然后取回解析好的ip的方法呢。