Ejemplo n.º 1
0
 //客户机有数据来就触发这里,其实就是跟上面的一样套路,只是反过来
 private void OnClientData(IAsyncResult result)
 {
     if (IsStop)
     {
         return;
     }
     try
     {
         ProxyInfo   pi = result.AsyncState as ProxyInfo;
         SocketError error;
         int         size = pi.client.Client.EndReceive(result, out error);
         if (size > 0)
         {
             //转发给远程真实服务器
             NetworkStream stream = pi.proxy.GetStream();
             stream.Write(pi.up_buf, 0, size);
             //继续等待下一个数据包
             pi.client.Client.BeginReceive(pi.up_buf, 0, pi.up_buf.Length, SocketFlags.None, this.OnClientData, pi);
         }
     }
     catch
     {
     }
 }
Ejemplo n.º 2
0
        private async void OnConnect(object _client)
        {
            if (IsStop)
            {
                return;
            }
            TcpClient client = _client as TcpClient;

            try
            {
                byte[]        up_buf   = new byte[BufferLen];
                byte[]        down_buf = new byte[BufferLen];
                NetworkStream stream   = client.GetStream();

                //====================================================================
                //连上的第一件事情就是先处理握手包,我刚意识到这不需要丢到循环里面啊
                int num = await stream.ReadAsync(up_buf, 0, 2); //读2字节客户端发上来的东西,第一字节是协议,第二字节是下个包的长度

                //Debug(up_buf, num, "1");
                if (num != 2)
                {
                    return;
                }

                int packlen = 0;
                packlen = up_buf[1];
                num     = await stream.ReadAsync(up_buf, 0, packlen);

                //Debug(up_buf, num, "2");

                //回应握手包
                down_buf[0] = 0x05;
                down_buf[1] = 0x00;//回复说不需要认证

                await stream.WriteAsync(down_buf, 0, 2);

                stream.Flush();
                //====================================================================


                //====================================================================
                //然后就是收目标请求信息并回复
                //先收个4字节的包头
                IPAddress ip = null;
                num = stream.Read(up_buf, 0, 4);
                //Debug(up_buf, num, "3");
                if (num <= 0)
                {
                    return;
                }
                //如果目标是个ip
                if (up_buf[3] == 1 || up_buf[3] == 4)
                {
                    //是个IPV6有16字节,ipv4是4字节
                    int    iplen = (up_buf[3] == 1) ? 4 : 16;
                    byte[] iparr = new byte[iplen];
                    num = stream.Read(iparr, 0, iplen);
                    if (num <= 0)
                    {
                        stream.Close();
                        client.Close();
                        return;
                    }
                    ip = new IPAddress(iparr);
                    Output(client.Client.RemoteEndPoint.ToString() + "请求ip:" + ip.ToString());
                }
                //是个域名
                else if (up_buf[3] == 3)
                {
                    num = stream.Read(up_buf, 0, 1);
                    int urllen = up_buf[0];
                    num = stream.Read(up_buf, 0, urllen);
                    string url = Encoding.ASCII.GetString(up_buf);
                    //域名反查ip
                    IPAddress[] iplist = Dns.GetHostAddresses(url);
                    if (iplist.Length == 0)
                    {
                        stream.Close();
                        client.Close();
                        return;
                    }
                    ip = iplist[0];
                    Output(client.Client.RemoteEndPoint.ToString() + "请求域名:" + url);
                }
                //协议之外的就不知道是个什么鬼了
                else
                {
                    stream.Close();
                    client.Close();
                    return;
                }
                //收端口号
                int port = 0;
                num = stream.Read(up_buf, 0, 2);
                byte[] portArr = { up_buf[1], up_buf[0] };//反转字节序
                port = BitConverter.ToUInt16(portArr, 0);

                Output("目标:" + ip.ToString() + ":" + port.ToString());

                //回复客户端,完成握手
                byte[] myip   = ((IPEndPoint)this.Tcp.LocalEndpoint).Address.GetAddressBytes();
                byte[] myport = BitConverter.GetBytes((ushort)this.Port);
                down_buf[0] = 5;
                down_buf[1] = 0;
                down_buf[2] = 0;
                down_buf[3] = 1;
                myip.CopyTo(down_buf, 4);
                myport.CopyTo(down_buf, 8);
                await stream.WriteAsync(down_buf, 0, 10);

                //====================================================================


                //====================================================================
                //握手完毕就是正常的收发数据包了
                TcpClient proxy = new TcpClient();
                proxy.Connect(ip, port);//连上真实目标(握手包里得到的ip和端口)

                //用事件来做比较我之前写的while更科学点
                //此处需要写个结构体放proxy和client,因为我希望同时传递proxy和client的socket对象,数据接收事件却只能传递一个参数
                ProxyInfo pi = new ProxyInfo();
                pi.proxy    = proxy;
                pi.client   = client;
                pi.up_buf   = new byte[BufferLen];
                pi.down_buf = new byte[BufferLen];

                proxy.Client.BeginReceive(pi.down_buf, 0, pi.down_buf.Length, SocketFlags.None, this.OnProxyData, pi);
                client.Client.BeginReceive(pi.up_buf, 0, pi.up_buf.Length, SocketFlags.None, this.OnClientData, pi);
            }catch (Exception ex) {
                Output(ex.ToString());
            }
        }