private bool HandleSocks4(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout)
        {
            var commandCode = SocketAbstraction.ReadByte(socket, timeout);

            if (commandCode == -1)
            {
                // SOCKS client closed connection
                return(false);
            }

            //  TODO:   See what need to be done depends on the code

            var portBuffer = new byte[2];

            if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
            {
                // SOCKS client closed connection
                return(false);
            }

            var port = Pack.BigEndianToUInt16(portBuffer);

            var ipBuffer = new byte[4];

            if (SocketAbstraction.Read(socket, ipBuffer, 0, ipBuffer.Length, timeout) == 0)
            {
                // SOCKS client closed connection
                return(false);
            }

            var ipAddress = new IPAddress(ipBuffer);

            var username = ReadString(socket, timeout);

            if (username == null)
            {
                // SOCKS client closed connection
                return(false);
            }

            var host = ipAddress.ToString();

            RaiseRequestReceived(host, port);

            channel.Open(host, port, this, socket);

            SocketAbstraction.SendByte(socket, 0x00);

            if (channel.IsOpen)
            {
                SocketAbstraction.SendByte(socket, 0x5a);
                SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length);
                SocketAbstraction.Send(socket, ipBuffer, 0, ipBuffer.Length);
                return(true);
            }

            // signal that request was rejected or failed
            SocketAbstraction.SendByte(socket, 0x5b);
            return(false);
        }
示例#2
0
 public void BigEndianToUInt16()
 {
     Assert.AreEqual(0, Pack.BigEndianToUInt16(new byte[] { 0, 0 }));
     Assert.AreEqual(1, Pack.BigEndianToUInt16(new byte[] { 0, 1 }));
     Assert.AreEqual(256, Pack.BigEndianToUInt16(new byte[] { 1, 0 }));
     Assert.AreEqual(257, Pack.BigEndianToUInt16(new byte[] { 1, 1 }));
     Assert.AreEqual(1025, Pack.BigEndianToUInt16(new byte[] { 4, 1 }));
     Assert.AreEqual(ushort.MaxValue, Pack.BigEndianToUInt16(new byte[] { 255, 255 }));
 }
        private bool HandleSocks5(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout)
        {
            var authenticationMethodsCount = SocketAbstraction.ReadByte(socket, timeout);

            if (authenticationMethodsCount == -1)
            {
                // SOCKS client closed connection
                return(false);
            }

            var authenticationMethods = new byte[authenticationMethodsCount];

            if (SocketAbstraction.Read(socket, authenticationMethods, 0, authenticationMethods.Length, timeout) == 0)
            {
                // SOCKS client closed connection
                return(false);
            }

            if (authenticationMethods.Min() == 0)
            {
                // no user authentication is one of the authentication methods supported
                // by the SOCKS client
                SocketAbstraction.Send(socket, new byte[] { 0x05, 0x00 }, 0, 2);
            }
            else
            {
                // the SOCKS client requires authentication, which we currently do not support
                SocketAbstraction.Send(socket, new byte[] { 0x05, 0xFF }, 0, 2);

                // we continue business as usual but expect the client to close the connection
                // so one of the subsequent reads should return -1 signaling that the client
                // has effectively closed the connection
            }

            var version = SocketAbstraction.ReadByte(socket, timeout);

            if (version == -1)
            {
                // SOCKS client closed connection
                return(false);
            }

            if (version != 5)
            {
                throw new ProxyException("SOCKS5: Version 5 is expected.");
            }

            var commandCode = SocketAbstraction.ReadByte(socket, timeout);

            if (commandCode == -1)
            {
                // SOCKS client closed connection
                return(false);
            }

            var reserved = SocketAbstraction.ReadByte(socket, timeout);

            if (reserved == -1)
            {
                // SOCKS client closed connection
                return(false);
            }

            if (reserved != 0)
            {
                throw new ProxyException("SOCKS5: 0 is expected for reserved byte.");
            }

            var addressType = SocketAbstraction.ReadByte(socket, timeout);

            if (addressType == -1)
            {
                // SOCKS client closed connection
                return(false);
            }

            var host = GetSocks5Host(addressType, socket, timeout);

            if (host == null)
            {
                // SOCKS client closed connection
                return(false);
            }

            var portBuffer = new byte[2];

            if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
            {
                // SOCKS client closed connection
                return(false);
            }

            var port = Pack.BigEndianToUInt16(portBuffer);

            RaiseRequestReceived(host, port);

            channel.Open(host, port, this, socket);

            var socksReply = CreateSocks5Reply(channel.IsOpen);

            SocketAbstraction.Send(socket, socksReply, 0, socksReply.Length);

            return(true);
        }