Exemple #1
0
        private void socket_Receive(IAsyncResult ar)
        {
            try
            {
                int received = Handle.EndReceive(ar);

                if (received <= 0)
                {
                    Disconnect();
                    return;
                }
                if (received > 5000 || _handshakeStream.Length + received > 5000)
                {
                    //attack prevention of overflowing the HandshakeStream
                    //It's really impossible for Socks or HTTPS proxies to use even 5000 for Initial Packets
                    Disconnect();
                    return;
                }

                LengthReceived += received;
                _handshakeStream.Write(_buffer, 0, received);
            }
            catch
            {
                Disconnect();
                return;
            }

            byte[] payload = _handshakeStream.ToArray();

            switch (PacketsReceived)
            {
            case 0:
            {
                //initial Socks packet
                if (payload.Length >= 3)
                {
                    string headerStr = Encoding.ASCII.GetString(payload);

                    //check the proxy client
                    if (payload[0] == SOCKS5_VERSION_NUMBER)
                    {
                        Type = ProxyType.Socks5;
                    }
                    else if (headerStr.StartsWith("CONNECT") && headerStr.Contains(":"))
                    {
                        Type = ProxyType.HTTPS;

                        //Grab here the IP / PORT
                        using (StreamReader sr = new StreamReader(new MemoryStream(payload)))
                        {
                            string line = sr.ReadLine();
                            if (line == null)
                            {
                                break;
                            }

                            //could have done it better with RegEx... oh well
                            string[] split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                            if (split.Length > 0)
                            {
                                try
                                {
                                    string ipPort = split[1];
                                    this.TargetServer = ipPort.Split(':')[0];
                                    this.TargetPort   = ushort.Parse(ipPort.Split(':')[1]);

                                    this._isConnectCommand = true;
                                    this._isDomainNameType = true;

                                    //Send Command to client and wait for response from CommandHandler
                                    new ReverseProxyConnect(ConnectionId, this.TargetServer, this.TargetPort).Execute(Client);
                                    Server.CallonConnectionEstablished(this);

                                    return;     //Quit receiving and wait for client's response
                                }
                                catch
                                {
                                    Disconnect();
                                }
                            }
                        }
                    }
                    else
                    {
                        break;
                    }

                    if (CheckProxyVersion(payload))
                    {
                        SendSuccessToClient();
                        PacketsReceived++;
                        _handshakeStream.SetLength(0);
                        Server.CallonConnectionEstablished(this);
                    }
                }
                break;
            }

            case 1:
            {
                //Socks command
                int MinPacketLen = 6;
                if (payload.Length >= MinPacketLen)
                {
                    if (!CheckProxyVersion(payload))
                    {
                        return;
                    }

                    this._isConnectCommand = payload[1] == 1;
                    this._isBindCommand    = payload[1] == 2;
                    this._isUdpCommand     = payload[1] == 3;

                    this._isIpType         = payload[3] == 1;
                    this._isDomainNameType = payload[3] == 3;
                    this._isIPv6NameType   = payload[3] == 4;

                    Array.Reverse(payload, payload.Length - 2, 2);
                    this.TargetPort = BitConverter.ToUInt16(payload, payload.Length - 2);

                    if (_isConnectCommand)
                    {
                        if (_isIpType)
                        {
                            this.TargetServer = payload[4] + "." + payload[5] + "." + payload[6] + "." + payload[7];
                        }
                        else if (_isDomainNameType)
                        {
                            int domainLen = payload[4];
                            if (MinPacketLen + domainLen < payload.Length)
                            {
                                this.TargetServer = Encoding.ASCII.GetString(payload, 5, domainLen);
                            }
                        }

                        if (this.TargetServer.Length > 0)
                        {
                            //Send Command to client and wait for response from CommandHandler
                            new ReverseProxyConnect(ConnectionId, this.TargetServer, this.TargetPort).Execute(Client);
                        }
                    }
                    else
                    {
                        SendFailToClient();
                        return;
                    }

                    Server.CallonUpdateConnection(this);

                    //Quit receiving data and wait for Client's response
                    return;
                }
                break;
            }
            }

            try
            {
                Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, socket_Receive, null);
            }
            catch
            {
                Disconnect();
            }
        }