예제 #1
0
        /// <summary>
        /// 客户端接收到数据
        /// </summary>
        /// <param name="tcpClient"></param>
        /// <param name="saea"></param>
        /// <param name="clientErrorType"></param>
        private void OnReceive(HHTcpClient tcpClient, SocketAsyncEventArgs saea, ClientErrorType clientErrorType)
        {
            if (clientErrorType != ClientErrorType.Success)
            {
                Close(clientErrorType);
                return;
            }
            if (HttpProxySessionInfo.HeadLength == -1)//尚为解析协议头
            {
                if (HttpProxySessionInfo.MemoryStream == null)
                {
                    HttpProxySessionInfo.MemoryStream = new System.IO.MemoryStream();
                }
                HttpProxySessionInfo.MemoryStream.Write(saea.Buffer, saea.Offset, saea.BytesTransferred);

                ToParseQuery();//解析协议头
            }
            else
            {
                if (DSsaea == null)
                {
                    DSsaea = new SocketAsyncEventArgs();
                }
                //直接转发就行了
                DSsaea.SetBuffer(saea.Buffer, saea.Offset, saea.BytesTransferred);
                if (!desTcpCliet.BeginSend(DSsaea, out var errorType))
                {
                    Close(errorType);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// 解析协议头
        /// </summary>
        private void ToParseQuery()
        {
            #region 解析协议头
            string aBin = Encoding.UTF8.GetString(HttpProxySessionInfo.MemoryStream.ToArray());
            int    index, indexbe, lastindex, onLine;
            index = aBin.IndexOf("\r\n\r\n");
            if (index == -1)
            {
                if (aBin.Length > 102400)//数据大于100k还没解析出协议头  关闭
                {
                    Close(ClientErrorType.OtherError);
                }
                else if (!cTcpClient.BeginReceive(Rsaea, out ClientErrorType clientErrorType))
                {
                    Close(ClientErrorType.OtherError);
                }
                return;
            }
            HttpProxySessionInfo.HeadLength = index + 4;
            if (aBin.Length != HttpProxySessionInfo.HeadLength)
            {
                aBin = Encoding.UTF8.GetString(HttpProxySessionInfo.MemoryStream.ToArray(), 0, HttpProxySessionInfo.HeadLength);
            }
            //解析访问方式
            index = aBin.IndexOf(' ');
            if (index == -1 || index > 10)
            {
                //解析访问方式错误
                Close(ClientErrorType.OtherError);
                return;
            }
            HttpProxySessionInfo.HttpRequestType = aBin.Substring(0, index);
            //解析协议版本
            lastindex = aBin.IndexOf("\r\n", index);
            if (lastindex == -1)
            {
                //协议头错误
                Close(ClientErrorType.OtherError);
                return;
            }
            onLine  = lastindex;
            indexbe = aBin.LastIndexOf(' ', lastindex);
            if (indexbe == -1)
            {
                //协议头错误
                Close(ClientErrorType.OtherError);
                return;
            }
            HttpProxySessionInfo.HttpVersion = aBin.Substring(indexbe + 1, lastindex - indexbe - 1);
            HttpProxySessionInfo.HttpPath    = aBin.Substring(index + 1, indexbe - index - 1);
            //解析host

            string hostUrl = string.Empty;
            //CONNECT
            if ("CONNECT" == HttpProxySessionInfo.HttpRequestType)
            {
                hostUrl = HttpProxySessionInfo.HttpPath;
            }
            else
            {
                index = aBin.IndexOf("Host: ");
                if (index == -1)
                {
                    //协议头错误
                    Close(ClientErrorType.OtherError);
                    return;
                }
                index    += 6;
                lastindex = aBin.IndexOf("\r\n", index);
                if (lastindex == -1)
                {
                    //协议头错误
                    Close(ClientErrorType.OtherError);
                    return;
                }
                hostUrl = aBin.Substring(index, lastindex - index);
            }
            if (string.IsNullOrEmpty(hostUrl))
            {
                //协议头错误
                Close(ClientErrorType.OtherError);
                return;
            }
            string[] ho = hostUrl.Split(':');
            HttpProxySessionInfo.Host = ho[0];
            if (ho.Length > 2)
            {
                //协议头错误
                Close(ClientErrorType.OtherError);
                return;
            }
            if (ho.Length == 2)
            {
                if (ushort.TryParse(ho[1], out ushort pro))
                {
                    HttpProxySessionInfo.Port = pro;
                }
                else//错误的端口
                {
                    Close(ClientErrorType.OtherError);
                    return;
                }
            }
            else
            {
                if ("CONNECT" == HttpProxySessionInfo.HttpRequestType)
                {
                    HttpProxySessionInfo.Port = 443;
                }
                else
                {
                    HttpProxySessionInfo.Port = 80;
                }
            }
            #endregion

            if (!IPAddress.TryParse(HttpProxySessionInfo.Host, out IPAddress ipaddr))
            {
                try
                {
                    IPAddress[] iplist = Dns.GetHostAddresses(HttpProxySessionInfo.Host);
                    if (iplist != null && iplist.Length > 0)
                    {
                        ipaddr = iplist[0];
                    }
                    else
                    {
                        //无法解析host
                        Close(ClientErrorType.OtherError);
                        return;
                    }
                }
                catch (Exception)
                {
                    //无法解析host
                    Close(ClientErrorType.OtherError);
                    return;
                }
            }
            byte[] ipBytes = ipaddr.GetAddressBytes();//尝试访问局域网
            if (ipBytes[0] == 10 || (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) || (ipBytes[0] == 192 && ipBytes[1] == 168))
            {
                //尝试访问局域网
                Close(ClientErrorType.Danger);
                return;
            }
            if (ipBytes[0] == 127 && ipBytes[1] == 0 && ipBytes[2] == 0 && ipBytes[3] == 1 && HttpProxySessionInfo.Port != 57869)
            {
                //尝试访问本地其他端口
                Close(ClientErrorType.Danger);
                return;
            }
            IPEndPoint localEndPoint = new IPEndPoint(ipaddr, HttpProxySessionInfo.Port);
            Socket     socket        = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
            {
                socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
            }
            //if (aBin.IndexOf("\r\nProxy-Connection: Keep-Alive\r\n", StringComparison.OrdinalIgnoreCase) != -1 || aBin.IndexOf("\r\nConnection: Keep-Alive\r\n") != -1)
            //{
            //    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            //}
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);

            IAsyncResult waitcon = socket.BeginConnect(localEndPoint, null, null);

            if (!waitcon.AsyncWaitHandle.WaitOne(15000))
            {
                //无法连接host
                Close(ClientErrorType.OtherError);
                return;
            }
            desTcpCliet            = new HHTcpClient(socket);
            desTcpCliet.OnError   += DOnError;
            desTcpCliet.OnReceive += DOnReceive;
            desTcpCliet.OnSendEnd += DOnSendEnd;
            if ("CONNECT" == HttpProxySessionInfo.HttpRequestType)
            {
                //先发送
                if (Ssaea == null)
                {
                    Ssaea = new SocketAsyncEventArgs();
                }
                byte[] bin = Encoding.UTF8.GetBytes($"{HttpProxySessionInfo.HttpVersion} 200 Connection established\r\nProxy-Agent: Mentalis Proxy Server\r\n\r\n");
                Ssaea.SetBuffer(bin, 0, bin.Length);
                if (!cTcpClient.BeginSend(Ssaea, out _))
                {
                    Close(ClientErrorType.OtherError);
                    return;
                }
            }
            else
            {
                //http协议 重组包
                if (HttpProxySessionInfo.HttpPath.Length >= 7 && HttpProxySessionInfo.HttpPath.Substring(0, 7).ToLower().Equals("http://"))
                {
                    index = HttpProxySessionInfo.HttpPath.IndexOf('/', 7);
                    if (index == -1)
                    {
                        HttpProxySessionInfo.HttpPath = "/";
                    }
                    else
                    {
                        HttpProxySessionInfo.HttpPath = HttpProxySessionInfo.HttpPath.Substring(index);
                    }
                }

                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.Append($"{HttpProxySessionInfo.HttpRequestType} {HttpProxySessionInfo.HttpPath} {HttpProxySessionInfo.HttpVersion}\r\n");
                string[] heads = aBin.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                //排除掉第一行
                for (int i = 1; i < heads.Length; i++)
                {
                    if (heads[i].Length > 18 && heads[i].Substring(0, 16).ToLower() == "proxy-connection")
                    {
                        if (heads[i].Substring(18).ToLower() == "keep-alive")
                        {
                            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                        }
                        heads[i] = $"Connection: " + heads[i].Substring(18);
                    }
                    else if (heads[i].Length > 12 && heads[i].Substring(0, 10).ToLower() == "connection")
                    {
                        if (heads[i].Substring(12).ToLower() == "keep-alive")
                        {
                            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                        }
                    }
                    stringBuilder.Append(heads[i]);
                    stringBuilder.Append("\r\n");
                }
                stringBuilder.Append("\r\n");

                //if (aBin.IndexOf("\r\nProxy-Connection: Keep-Alive\r\n") == -1)
                //{
                //    stringBuilder.Append(aBin.Substring(onLine, HttpProxySessionInfo.HeadLength - onLine));
                //}
                //else
                //{
                //    stringBuilder.Append(aBin.Substring(onLine, HttpProxySessionInfo.HeadLength - onLine).Replace("\r\nProxy-Connection: Keep-Alive\r\n", "\r\nConnection: Keep-Alive\r\n"));

                //}
                //是否有非头数据
                byte[] bin;
                if (HttpProxySessionInfo.MemoryStream.Length > HttpProxySessionInfo.HeadLength)
                {
                    bin = new byte[stringBuilder.Length + HttpProxySessionInfo.MemoryStream.Length - HttpProxySessionInfo.HeadLength];
                    Encoding.UTF8.GetBytes(stringBuilder.ToString()).CopyTo(bin, 0);
                    HttpProxySessionInfo.MemoryStream.Position = HttpProxySessionInfo.HeadLength;

                    HttpProxySessionInfo.MemoryStream.Read(bin, stringBuilder.Length, (int)HttpProxySessionInfo.MemoryStream.Length - HttpProxySessionInfo.HeadLength);
                }
                else
                {
                    bin = Encoding.UTF8.GetBytes(stringBuilder.ToString());
                }
                Console.WriteLine(Encoding.UTF8.GetString(bin));
                //if (HttpProxySessionInfo.HttpPath.IndexOf("http://") == 0)//需要重组头部
                //{
                //    index = HttpProxySessionInfo.HttpPath.IndexOf('/', 7);
                //    if (index == -1)
                //        HttpProxySessionInfo.HttpPath = "/";
                //    else
                //        HttpProxySessionInfo.HttpPath = HttpProxySessionInfo.HttpPath.Substring(index);
                //    bin = Encoding.UTF8.GetBytes($"{HttpProxySessionInfo.HttpRequestType} {HttpProxySessionInfo.HttpPath} {HttpProxySessionInfo.HttpVersion}{aBin.Substring(onLine, HttpProxySessionInfo.HeadLength - onLine)}");
                //}
                //else
                //{
                //    //Proxy-Connection: Keep-Alive
                //    if (aBin.IndexOf("\r\nProxy-Connection: Keep-Alive\r\n") != -1)
                //    {
                //        bin = Encoding.UTF8.GetBytes(aBin.Replace("\r\nProxy-Connection: Keep-Alive\r\n", "\r\nConnection: Keep-Alive\r\n"));
                //    }
                //    else
                //    {
                //        bin = HttpProxySessionInfo.MemoryStream.ToArray();
                //    }

                //}



                //http 发送所有数据给目标
                if (DSsaea == null)
                {
                    DSsaea = new SocketAsyncEventArgs();
                }
                DSsaea.SetBuffer(bin, 0, bin.Length);
                if (!desTcpCliet.BeginSend(DSsaea, out var errorType))
                {
                    Close(errorType);
                    return;
                }
            }
        }