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); }
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); }
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(); } }
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); }
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); }
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); }