Exemple #1
0
        public int BlindlyRelayData(
            MyBinaryReader inputStreamReader,
            BinaryWriter outputStreamWriter,
            SniffedDataChunk sniffedDataChunk = null)
        {
            int noBytesTransferred = 0;
            int bytesRead          = 0;
            int chunkCounter       = 0;

            byte[] buffer = new byte[MaxBufferSize];

            while ((bytesRead = inputStreamReader.Read(buffer, 0, buffer.Length)) > 0)
            {
                // Forward received data packets to peer
                outputStreamWriter.Write(buffer, 0, bytesRead);
                noBytesTransferred += bytesRead;

                // If a sniffer data chunk object is defined write application data to it
                if (sniffedDataChunk != null)
                {
                    sniffedDataChunk.AppendData(buffer, bytesRead);
                }

                chunkCounter++;
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "BlindlyRelayData(): FragmentNo:{0} bytesTransferred:{1}", chunkCounter, bytesRead);
            }

            return(noBytesTransferred);
        }
Exemple #2
0
        public int ForwardSingleLineToPeer(
            MyBinaryReader clientStreamReader,
            BinaryWriter webServerStreamWriter,
            Encoding contentCharsetEncoding,
            byte[] serverNewlineBytes,
            SniffedDataChunk sniffedDataChunk,
            bool mustBeProcessed)
        {
            int noBytesTransferred = 0;

            byte[] clientData = clientStreamReader.ReadBinaryLine();

            if (clientData?.Length > 0)
            {
                // Forward received data packets to peer
                webServerStreamWriter.Write(clientData, 0, clientData.Length);
                noBytesTransferred += clientData.Length;

                // If a sniffer data chunk object is defined write application data to it
                if (sniffedDataChunk != null)
                {
                    sniffedDataChunk.AppendData(clientData, clientData.Length);
                }

                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardSingleLineNonprocessedDataToPeer(): clientData.Length:{0}", clientData.Length);
            }
            else
            {
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardSingleLineNonprocessedDataToPeer(): clientData:NULL");
            }

            return(noBytesTransferred);
        }
Exemple #3
0
        public int ForwardChunkedDataToPeerChunked(
            MyBinaryReader inputStreamReader,
            BinaryWriter outputStreamWriter,
            Encoding contentCharsetEncoding,
            byte[] serverNewlineBytes,
            SniffedDataChunk sniffedDataChunk,
            bool isProcessed) // <-- relevant for sslstrip and injectFile
        {
            int    noBytesTransferred            = 0;
            int    noEffectivelyTransferredBytes = 0;
            int    announcedChunkSize            = 0;
            int    chunkCounter     = 0;
            string previousChunkLen = "00";

            while (true)
            {
                chunkCounter += 1;

                // Read chunk size
                string chunkLenStr = inputStreamReader.ReadLine(false);

                // Jump out of the loop if it is the last data packet
                if (string.IsNullOrEmpty(chunkLenStr))
                {
                    Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardChunkedDataToPeer2(): WOOPS! chunkLenStr isNullOrEmpty!!!");
                    break;
                }

                announcedChunkSize = int.Parse(chunkLenStr, System.Globalization.NumberStyles.HexNumber);
                // If announced chunk size is invalid/<0 jump out of the loop
                if (announcedChunkSize < 0)
                {
                    Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardChunkedDataToPeer2(): WOOPS! Invalid chunk size!!!");
                    break;
                }

                // Receive announced data chunk from server
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardChunkedDataToPeer2(): ChunkNo={0}: previousChunkLen=0x{1} ChunkLength=0x{2}", chunkCounter, previousChunkLen, chunkLenStr);
                noEffectivelyTransferredBytes = this.RelayChunk2(inputStreamReader, outputStreamWriter, announcedChunkSize, contentCharsetEncoding, serverNewlineBytes, isProcessed);
                noBytesTransferred           += noEffectivelyTransferredBytes;
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardChunkedDataToPeer2(): blockSize > 0: ChunkNo={0} chunkLenStr.Length={1}, Content=|0x{2}|", chunkCounter, chunkLenStr.Length, chunkLenStr);
                previousChunkLen = chunkLenStr;

                // If chunk size is zero jump out of the loop
                if (announcedChunkSize == 0 || chunkLenStr == "0")
                {
                    break;
                }
            }

            return(noBytesTransferred);
        }
        private void ForwardClientRequestToServer()
        {
            // 1. Close old server request streams
            if (this.requestObj.ServerRequestHandler != null)
            {
                this.requestObj.ServerRequestHandler.CloseServerConnection();
            }

            // 1.1 Reset previously received server response details
            this.requestObj.ServerResponseObj.ResponseHeaders.Clear();
            this.requestObj.ServerResponseObj.StatusLine.Reset();

            // If remote server requires HTTPS create an SSL based socket stream.
            // Reasons : Plugin.SslStripn: Http redirect cache record
            //           Plugin.SslStripn: Hsts cache record
            //           Plugin.SslStripn: SslStrip cache record
            if (this.requestObj.ProxyProtocol == ProxyProtocol.Https)
            {
                this.requestObj.ServerRequestHandler = new ToServer.TcpClientSsl(this.requestObj, this.requestObj.ClientRequestObj.ClientBinaryReader, this.requestObj.ClientRequestObj.ClientBinaryWriter);
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "HttpReverseProxy.ForwardClientRequestToServer(): Create HTTPS socket connection to {0}", this.requestObj.ClientRequestObj.Host);
            }
            else
            {
                this.requestObj.ServerRequestHandler = new ToServer.TcpClientPlainText(this.requestObj, this.requestObj.ClientRequestObj.ClientBinaryReader, this.requestObj.ClientRequestObj.ClientBinaryWriter);
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "HttpReverseProxy.ForwardClientRequestToServer(): Create HTTP socket connection to {0}", this.requestObj.ClientRequestObj.Host);
            }

            // 2. Send tcp-client request headers to remoteSocket
            this.requestObj.ServerRequestHandler.OpenServerConnection(this.requestObj.ClientRequestObj.Host);
            this.requestObj.ServerRequestHandler.ForwardRequestC2S(this.requestObj.ClientRequestObj.RequestLine.MethodString, this.requestObj.ClientRequestObj.RequestLine.Path, this.requestObj.ClientRequestObj.RequestLine.HttpVersion, this.requestObj.ClientRequestObj.RequestLine.NewlineBytes);
            this.requestObj.ServerRequestHandler.ForwardHeadersC2S(this.requestObj.ClientRequestObj.ClientRequestHeaders, this.requestObj.ClientRequestObj.RequestLine.NewlineBytes);

            // 3. Send tcp-client request data to remoteSocket
            bool mustBeProcessed = this.IsClientRequestDataProcessable();

            Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "HttpReverseProxy.ForwardClientRequestToServer(): CLIENT REQUEST : {0}PROCESS", (mustBeProcessed ? string.Empty : "DONT "));
            SniffedDataChunk sniffedDataChunk = new SniffedDataChunk(Config.MaxSniffedClientDataSize);

            this.requestObj.ServerRequestHandler.RelayDataC2S(mustBeProcessed, sniffedDataChunk);
            this.EditClientRequestData(sniffedDataChunk);

            // 4 Read remotesocket response headers
            this.requestObj.ServerRequestHandler.ReadServerStatusLine(this.requestObj);
            this.requestObj.ServerRequestHandler.ReadServerResponseHeaders(this.requestObj.ServerResponseObj);
        }
        private void EditClientRequestData(SniffedDataChunk sniffedDataChunk)
        {
            // Append client request headers to the log data string
            try
            {
                foreach (string key in this.requestObj.ClientRequestObj.ClientRequestHeaders.Keys)
                {
                    string logData = string.Join("..", this.requestObj.ClientRequestObj.ClientRequestHeaders[key]);
                    this.requestObj.HttpLogData += $"..{key}: {logData}";
                }
            }
            catch (Exception)
            {
            }

            // Append client request data to the log data string
            if (sniffedDataChunk?.TotalBytesWritten > 0)
            {
                this.requestObj.HttpLogData += "...." + sniffedDataChunk.GetDataString();
            }
        }
Exemple #6
0
        public int RelayDataC2S(bool mustBeProcessed, SniffedDataChunk sniffedDataChunk)
        {
            int noRelayedBytes = 0;

            byte[] buffer = new byte[MaxBufferSize];

            // 1. No data to relay/process
            if (this.requestObj.ProxyDataTransmissionModeC2S == DataTransmissionMode.NoDataToTransfer)
            {
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClienBase.RelayDataC2S(): DataTransmissionMode.NoDataToTransfer");

                // 2.0 Unknow amount of data chunks is transferred from the tcpClient to the peer system because
                // -   HTTP headerByteArray "Transfer-Encoding" was set
            }
            else if (this.requestObj.ProxyDataTransmissionModeC2S == DataTransmissionMode.Chunked)
            {
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClienBase.RelayDataC2S(): DataTransmissionMode.Chunked, processed:false");
                noRelayedBytes = this.ForwardChunkedDataToPeerChunked(
                    this.clientStreamReader,
                    this.webServerStreamWriter,
                    this.requestObj.ClientRequestObj.ContentTypeEncoding.ContentCharsetEncoding,
                    this.requestObj.ClientRequestObj.RequestLine.NewlineBytes,
                    sniffedDataChunk,
                    mustBeProcessed);



                // 2.1 Unknow amount of data chunks is transferred from the tcpClient to the peer system because
                // -   HTTP headerByteArray "Transfer-Encoding" was set
            }
            else if (this.requestObj.ProxyDataTransmissionModeC2S == DataTransmissionMode.FixedContentLength)
            {
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClienBase.RelayDataC2S(): DataTransmissionMode.ContentLength, processed:false");
                noRelayedBytes = this.ForwardNonchunkedDataToPeerNonChunked(
                    this.clientStreamReader,
                    this.webServerStreamWriter,
                    this.requestObj.ClientRequestObj.ContentTypeEncoding.ContentCharsetEncoding,
                    this.requestObj.ClientRequestObj.ContentLength,
                    sniffedDataChunk,
                    mustBeProcessed);


                // 2.2 Unknow amount of data chunks is transferred from the tcpClient to the peer system because
                // -   HTTP headerByteArray "Transfer-Encoding" was set
            }
            else if (this.requestObj.ProxyDataTransmissionModeC2S == DataTransmissionMode.ReadOneLine)
            {
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClienBase.RelayDataC2S(): DataTransmissionMode.ReadOneLine, processed:false");
                this.ForwardSingleLineToPeer(
                    this.clientStreamReader,
                    this.webServerStreamWriter,
                    this.requestObj.ClientRequestObj.ContentTypeEncoding.ContentCharsetEncoding,
                    this.requestObj.ClientRequestObj.RequestLine.NewlineBytes,
                    sniffedDataChunk,
                    mustBeProcessed);



                // 4 Predefined amount of data is transferred from the tcpClient to the peer system because
                // -   HTTP headerByteArray "Content-Length" was defined
            }
            else if (this.requestObj.ProxyDataTransmissionModeC2S == DataTransmissionMode.RelayBlindly)
            {
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClienBase.RelayDataC2S(): DataTransmissionMode.ContentLength, ContentLength:{0}, processed:true", this.requestObj.ClientRequestObj.ContentLength);
                this.BlindlyRelayData(this.clientStreamReader, this.webServerStreamWriter, sniffedDataChunk);



                // 5 This state actually should never happen!
                //   I'll decide later what to do after it happened
            }
            else
            {
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClienBase.RelayDataC2S(): ContentLength:{0}, processed:false", this.requestObj.ClientRequestObj.ContentLength);
                noRelayedBytes = this.ForwardNonchunkedDataToPeerNonChunked(
                    this.clientStreamReader,
                    this.webServerStreamWriter,
                    this.requestObj.ClientRequestObj.ContentTypeEncoding.ContentCharsetEncoding,
                    this.requestObj.ClientRequestObj.ContentLength,
                    null,
                    false);
            }

            return(noRelayedBytes);
        }
Exemple #7
0
        public int ForwardNonchunkedDataToPeerChunked(
            MyBinaryReader inputStreamReader,
            BinaryWriter outputStreamWriter,
            Encoding contentCharsetEncoding,
            int transferredContentLength,
            byte[] serverNewlineBytes,
            SniffedDataChunk sniffedDataChunk,
            bool mustBeProcessed)
        {
            int noBytesTransferred = 0;

            byte[] buffer = new byte[MaxBufferSize];
            int    totalTransferredBytes = 0;
            int    bytesRead             = 0;

            while (totalTransferredBytes < transferredContentLength)
            {
                // Read data from peer 1
                int maxDataToTransfer = transferredContentLength - totalTransferredBytes;
                bytesRead = inputStreamReader.Read(buffer, 0, buffer.Length);

                if (bytesRead <= 0)
                {
                    Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardNonchunkedDataToPeer3(2:DATA), No data to transfer");
                    break;
                }

                //
                if (sniffedDataChunk != null)
                {
                    sniffedDataChunk.AppendData(buffer, bytesRead);
                }

                // Encode received bytes to the announced format
                DataChunk serverDataChunk = new DataChunk(buffer, bytesRead, this.requestObj.ServerResponseObj.ContentTypeEncoding.ContentCharsetEncoding);

                if (mustBeProcessed == true)
                {
                    Lib.PluginCalls.ServerDataTransfer(this.requestObj, serverDataChunk);
                }

                // Send chunk size to recepient
                string chunkSizeHexStringTmp = serverDataChunk.ContentDataLength.ToString("x");
                byte[] chunkSizeDeclaration  = contentCharsetEncoding.GetBytes(chunkSizeHexStringTmp);
                outputStreamWriter.Write(chunkSizeDeclaration, 0, chunkSizeDeclaration.Length);
                outputStreamWriter.Write(serverNewlineBytes, 0, serverNewlineBytes.Length);

                // Send data packet to recipient
                outputStreamWriter.Write(serverDataChunk.ContentData, 0, serverDataChunk.ContentDataLength);
                outputStreamWriter.Write(serverNewlineBytes, 0, serverNewlineBytes.Length);
                outputStreamWriter.Flush();

                noBytesTransferred += serverDataChunk.ContentDataLength;
                Logging.Instance.LogMessage(
                    this.requestObj.Id,
                    this.requestObj.ProxyProtocol,
                    Loglevel.Debug,
                    "TcpClientRaw.ForwardNonchunkedDataToPeer3(): Data successfully relayed to client. ContentDataLength:{0} chunkSizeHexStringTmp={1} noBytesTransferred={2}",
                    serverDataChunk.ContentDataLength,
                    chunkSizeHexStringTmp,
                    noBytesTransferred);

                totalTransferredBytes += bytesRead;
            }

            // Send trailing "0 length" chunk
            string chunkSizeZeroHexString = 0.ToString("x");

            byte[] chunkSizeZeroDeclaration = contentCharsetEncoding.GetBytes(chunkSizeZeroHexString);
            outputStreamWriter.Write(chunkSizeZeroDeclaration, 0, chunkSizeZeroDeclaration.Length);
            outputStreamWriter.Write(serverNewlineBytes, 0, serverNewlineBytes.Length);
            outputStreamWriter.Write(serverNewlineBytes, 0, serverNewlineBytes.Length);

            Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardNonchunkedDataToPeer3(2:DATA): Total amount of transferred data={0}", totalTransferredBytes);
            return(noBytesTransferred);
        }
Exemple #8
0
        public int ForwardNonchunkedDataToPeerNonChunked(
            MyBinaryReader inputStreamReader,
            BinaryWriter outputStreamWriter,
            Encoding contentCharsetEncoding,
            int transferredContentLength,
            SniffedDataChunk sniffedDataChunk,
            bool mustBeProcessed)
        {
            int          noBytesTransferred = 0;
            MemoryStream memStream          = new MemoryStream();

            byte[] buffer = new byte[MaxBufferSize];
            int    totalTransferredBytes = 0;
            int    bytesRead             = 0;

            while (totalTransferredBytes < transferredContentLength)
            {
                // Read data from peer 1
                int maxDataToTransfer = transferredContentLength - totalTransferredBytes;
                bytesRead = inputStreamReader.Read(buffer, 0, buffer.Length);

                if (bytesRead <= 0)
                {
                    Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardNonchunkedDataToPeer2(2:DATA), No data to transfer");
                    break;
                }

                // Write data to memory stream
                memStream.Write(buffer, 0, bytesRead);

                if (sniffedDataChunk != null)
                {
                    sniffedDataChunk.AppendData(buffer, bytesRead);
                }

                totalTransferredBytes += bytesRead;
                Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardNonchunkedDataToPeer2(2:DATA, TotalDataToTransfer:{0}): Relaying data from: Client -> Server (bytesRead:{1} totalTransferredBytes:{2})", buffer.Length, bytesRead, totalTransferredBytes);
            }

            byte[] dataPacket = memStream.ToArray();
            //if (dataPacket.Length != MaxBufferSize)
            //{
            //  throw new Exception("The announced content length and the amount of received data are not the same");
            //}

            // Encode received bytes to the announced format
            DataChunk serverDataChunk = new DataChunk(dataPacket, dataPacket.Length, this.requestObj.ServerResponseObj.ContentTypeEncoding.ContentCharsetEncoding);

            if (mustBeProcessed == true)
            {
                Lib.PluginCalls.ServerDataTransfer(this.requestObj, serverDataChunk);
            }

            // Send data packet to recipient
            outputStreamWriter.Write(serverDataChunk.ContentData, 0, serverDataChunk.ContentDataLength);
            outputStreamWriter.Flush();
            noBytesTransferred += serverDataChunk.ContentDataLength;
            Logging.Instance.LogMessage(
                this.requestObj.Id,
                this.requestObj.ProxyProtocol,
                Loglevel.Debug,
                "TcpClientRaw.ForwardNonchunkedDataToPeer2(): Data successfully relayed to client. ContentDataSize:{0})",
                serverDataChunk.ContentDataLength);

            Logging.Instance.LogMessage(this.requestObj.Id, this.requestObj.ProxyProtocol, Loglevel.Debug, "TcpClientRaw.ForwardNonchunkedDataToPeer2(2:DATA): Total amount of transferred data={0}", totalTransferredBytes);
            return(noBytesTransferred);
        }