/// <summary> /// Used to keep receiving data from it's destination /// </summary> internal void StartNetworkStream() { if (stream != null) { return; //don't start the network stream twice } this.stream = new NetworkStream(this, networkStreamCallback); ReceiveBuffer = new byte[70000]; Handle.BeginReceive(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, AsyncSocketCallback, null); }
private void AsyncReceiveProxy(IAsyncResult ar) { try { int received = Handle.EndReceive(ar); if (received <= 0) { Disconnect(); return; } LengthReceived += received; byte[] payload = new byte[received]; Array.Copy(_buffer, payload, received); Client.Send(new ReverseProxyData { ConnectionId = ConnectionId, Data = payload }); LengthSent += payload.Length; PacketsSended++; } catch { Disconnect(); return; } PacketsReceived++; Server.CallonUpdateConnection(this); try { Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceiveProxy, null); } catch { } }
internal SyncObject Receive(ReceiveCallback callback) { lock (Handle) { if (callback == null) { throw new ArgumentNullException("callback"); } if (!Connected) { return(null); } SyncObject syncObject = new SyncObject(this); NetworkPayload networkPayload = new NetworkPayload(this, syncObject, callback); SocketError error = SocketError.AccessDenied; Handle.BeginReceive(networkPayload.Payload, 0, (int)networkPayload.PacketSize, SocketFlags.None, out error, ReceivePayloadCallback, networkPayload); return(syncObject); } }
public void CommandResponse(ReverseProxyConnectResponse response) { //a small prevention for calling this method twice, not required... just incase if (!_receivedConnResponse) { _receivedConnResponse = true; if (response.IsConnected) { this.HostName = response.HostName; //tell the Proxy Client that we've established a connection if (Type == ProxyType.HTTPS) { SendToClient(Encoding.ASCII.GetBytes("HTTP/1.0 200 Connection established\r\n\r\n")); } else if (Type == ProxyType.Socks5) { //Thanks to http://www.mentalis.org/soft/projects/proxy/ for the Maths try { SendToClient(new byte[] { SOCKS5_VERSION_NUMBER, SOCKS5_CMD_REPLY_SUCCEEDED, SOCKS5_RESERVED, 1, //static: it's always 1 (byte)(response.LocalEndPoint % 256), (byte)(Math.Floor((decimal)(response.LocalEndPoint % 65536) / 256)), (byte)(Math.Floor((decimal)(response.LocalEndPoint % 16777216) / 65536)), (byte)(Math.Floor((decimal)response.LocalEndPoint / 16777216)), (byte)(Math.Floor((decimal)response.LocalPort / 256)), (byte)(response.LocalPort % 256) }); } catch { //just incase the math failed //it will still show it's succesful SendToClient(new byte[] { SOCKS5_VERSION_NUMBER, SOCKS5_CMD_REPLY_SUCCEEDED, SOCKS5_RESERVED, 1, //static: it's always 1 0, 0, 0, 0, //bind ip 0, 0 //bind port }); } } _handshakeStream.Close(); ProxySuccessful = true; try { //start receiving data from the proxy Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, socket_ReceiveProxy, null); } catch { Disconnect(); } } else { if (Type == ProxyType.HTTPS) { Disconnect(); } else if (Type == ProxyType.Socks5) { //send a connection fail packet SendToClient(new byte[] { SOCKS5_VERSION_NUMBER, SOCKS5_CMD_REPLY_CONNECTION_REFUSED, SOCKS5_RESERVED, 1, //static: it's always 1 0, 0, 0, 0, //Bind Address 0, 0 //Bind Port }); } } Server.CallonUpdateConnection(this); } }
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(); } }
public void HandleCommandResponse(ReverseProxyConnectResponse response) { if (!_receivedConnResponse) { _receivedConnResponse = true; if (response.IsConnected) { this.HostName = response.HostName; if (Type == ProxyType.HTTPS) { SendToClient(Encoding.ASCII.GetBytes("HTTP/1.0 200 Connection established\r\n\r\n")); } else if (Type == ProxyType.SOCKS5) { try { List <byte> responsePacket = new List <byte>(); responsePacket.Add(SOCKS5_VERSION_NUMBER); responsePacket.Add(SOCKS5_CMD_REPLY_SUCCEEDED); responsePacket.Add(SOCKS5_RESERVED); responsePacket.Add(1); responsePacket.AddRange(response.LocalAddress.GetAddressBytes()); responsePacket.Add((byte)(Math.Floor((decimal)response.LocalPort / 256))); responsePacket.Add((byte)(response.LocalPort % 256)); SendToClient(responsePacket.ToArray()); } catch { SendToClient(new byte[] { SOCKS5_VERSION_NUMBER, SOCKS5_CMD_REPLY_SUCCEEDED, SOCKS5_RESERVED, 1, 0, 0, 0, 0, 0, 0 }); } } _handshakeStream.Close(); ProxySuccessful = true; try { Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceiveProxy, null); } catch { Disconnect(); } } else { if (Type == ProxyType.HTTPS) { Disconnect(); } else if (Type == ProxyType.SOCKS5) { SendToClient(new byte[] { SOCKS5_VERSION_NUMBER, SOCKS5_CMD_REPLY_CONNECTION_REFUSED, SOCKS5_RESERVED, 1, 0, 0, 0, 0, 0, 0 }); } } Server.CallonUpdateConnection(this); } }
private void AsyncReceive(IAsyncResult ar) { try { int received = Handle.EndReceive(ar); if (received <= 0) { Disconnect(); return; } if (received > 5000 || _handshakeStream.Length + received > 5000) { Disconnect(); return; } LengthReceived += received; _handshakeStream.Write(_buffer, 0, received); } catch { Disconnect(); return; } byte[] payload = _handshakeStream.ToArray(); switch (PacketsReceived) { case 0: { if (payload.Length >= 3) { string headerStr = Encoding.ASCII.GetString(payload); if (payload[0] == SOCKS5_VERSION_NUMBER) { Type = ProxyType.SOCKS5; } else if (headerStr.StartsWith("CONNECT") && headerStr.Contains(":")) { Type = ProxyType.HTTPS; using (StreamReader sr = new StreamReader(new MemoryStream(payload))) { string line = sr.ReadLine(); if (line == null) { break; } 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; new ReverseProxyConnect(ConnectionId, this.TargetServer, this.TargetPort).Execute(Client); Server.CallonConnectionEstablished(this); return; } catch { Disconnect(); } } } } else { break; } if (CheckProxyVersion(payload)) { SendSuccessToClient(); PacketsReceived++; _handshakeStream.SetLength(0); Server.CallonConnectionEstablished(this); } } break; } case 1: { 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) { new ReverseProxyConnect(ConnectionId, this.TargetServer, this.TargetPort).Execute(Client); } } else { SendFailToClient(); return; } Server.CallonUpdateConnection(this); return; } break; } } try { Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceive, null); } catch { Disconnect(); } }
private void ReceivePayloadCallback(IAsyncResult ar) { NetworkPayload networkPayload = (NetworkPayload)ar.AsyncState; SocketError error = SocketError.AccessDenied; int received = 0; try { //even tho there is "out error" it can still throw a error received = Handle.EndReceive(ar, out error); } catch { } if (received <= 0 || error != SocketError.Success) { Client.Disconnect(DisconnectReason.UnexpectedlyDisconnected); return; } BytesIn += (ulong)received; this.LastPacketSW = Stopwatch.StartNew(); networkPayload.WriteOffset += (uint)received; if (networkPayload.WriteOffset == networkPayload.PacketSize && networkPayload.ReceivedHeader) { uint Offset = 0; uint length = (uint)networkPayload.Payload.Length; //let's check the payload hash if (networkPayload.Header.Hash != networkPayload.Header.HashPayload(networkPayload.Payload, (int)Offset, (int)length, HandshakeChecksum)) { Client.Disconnect(DisconnectReason.DataModificationDetected); return; } //decrypt, decompress, de-cache the data we received networkPayload.Payload = protection.RemoveProtection(networkPayload.Payload, ref Offset, ref length, ref networkPayload.Header); IMessage message = null; try { message = messageHandler.HandleMessage(new PayloadReader(networkPayload.Payload), networkPayload.Header.MessageId); } catch { } networkPayload.syncObject.Value = networkPayload.Callback(message); networkPayload.syncObject.Pulse(); return; //no need to read futher } if (!networkPayload.ReceivedHeader && networkPayload.ReceivedPacket) { try { networkPayload.ReceivedHeader = true; //wopEncryption.Decrypt(networkPayload.Payload, 0, HEADER_SIZE); networkPayload.Header = new PacketHeader(networkPayload.Payload, 0, this); if (!DPI.Inspect(networkPayload.Header)) { Client.Disconnect(DisconnectReason.DeepPacketInspectionDisconnection); return; } networkPayload.PacketSize = networkPayload.Header.PacketSize; networkPayload.Payload = new byte[networkPayload.Header.PacketSize]; networkPayload.WriteOffset = 0; //just reset offset for reading } catch { Client.Disconnect(DisconnectReason.UnexpectedlyDisconnected); return; } } if (networkPayload.WriteOffset != networkPayload.PacketSize) { Handle.BeginReceive(networkPayload.Payload, (int)networkPayload.WriteOffset, (int)(networkPayload.PacketSize - networkPayload.WriteOffset), SocketFlags.None, out error, ReceivePayloadCallback, networkPayload); } }
private void AsyncSocketCallback(IAsyncResult result) { int BytesTransferred = 0; try { BytesTransferred = Handle.EndReceive(result); } catch { } if (BytesTransferred <= 0) { try { if (!InvokedOnDisconnect) { InvokedOnDisconnect = true; Client.Disconnect(DisconnectReason.UnexpectedlyDisconnected); } } catch (Exception ex) { Client.onException(ex, ErrorType.Core); } return; } this.LastPacketSW = Stopwatch.StartNew(); try { //let's check the certificate if (Client.Certificate.ValidFrom > (Client.ServerSided ? DateTime.Now : Client.TimeSync)) //DateTime.Now) { //we need to wait till the time is right Client.Disconnect(DisconnectReason.CertificatePastValidTime); return; } if (Client.Certificate.ValidTo < (Client.ServerSided ? DateTime.Now : Client.TimeSync))//DateTime.Now) { //certificate is not valid anymore Client.Disconnect(DisconnectReason.CertificatePastValidTime); return; } BytesIn += (ulong)BytesTransferred; //to make it 2x faster remove Array.Copy and set buffer offset in asyncReceiveEvent //too bad i've not acomplished this yet some really weird shit is happening then int writeOffset = stream.Write(ReceiveBuffer, 0, BytesTransferred); this.stream.Flush(); Handle.BeginReceive(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, AsyncSocketCallback, null); } catch (Exception ex) { /*if (Client.ServerAllowsReconnecting) * { * Client.Connect(ConnectionState.Reconnecting); * } * else*/ { Client.Disconnect(DisconnectReason.UnexpectedlyDisconnected); Client.onException(ex, ErrorType.Core); } } }
private void AynsReceive(IAsyncResult result) { int BytesTransferred = -1; try { BytesTransferred = Handle.EndReceive(result); SysLogger.Log("Received " + BytesTransferred, SysLogType.Network); if (BytesTransferred <= 0) { Disconnect(); return; } } catch (Exception ex) { SysLogger.Log(ex.Message, SysLogType.Error); Disconnect(); return; } try { //let's check the certificate if (Client.Server != null && Client.Server.serverProperties != null) { if (Client.ConnectionTime > Client.Server.serverProperties.ClientTimeConnected) { //we need to wait till the time is right Disconnect(); return; } } this.LastPacketRecvSW = Stopwatch.StartNew(); ReadableDataLen += BytesTransferred; DataIn += (ulong)BytesTransferred; bool Process = true; while (Process) { if (ReceiveState == ReceiveType.Header) { Process = ReadableDataLen >= HEADER_SIZE; if (ReadableDataLen >= HEADER_SIZE) { lock (HeaderEncryption) { headerConfuser.Deobfuscate(ref Buffer, ReadOffset); HeaderEncryption.Decrypt(Buffer, ReadOffset, HEADER_SIZE); } using (PayloadReader pr = new PayloadReader(Buffer)) { pr.Position = ReadOffset; PayloadLen = pr.ReadThreeByteInteger(); CurPacketId = pr.ReadByte(); ConnectionId = pr.ReadUShort(); HeaderId = pr.ReadUShort(); HeaderChecksum = pr.ReadByte(); FeatureId = pr.ReadInteger(); } byte ReChecksum = 0; //re-calculate the checksum ReChecksum += (byte)PayloadLen; ReChecksum += CurPacketId; ReChecksum += (byte)ConnectionId; ReChecksum += (byte)HeaderId; ReChecksum += (byte)FeatureId; if (ReChecksum != HeaderChecksum || PayloadLen >= MAX_PACKET_SIZE || PayloadLen < 0) { Disconnect(); return; } if (PayloadLen > Buffer.Length) { ResizeBuffer(PayloadLen); } TotalReceived = HEADER_SIZE; ReadableDataLen -= HEADER_SIZE; ReadOffset += HEADER_SIZE; ReceiveState = ReceiveType.Payload; } } else if (ReceiveState == ReceiveType.Payload) { Process = ReadableDataLen >= PayloadLen; if (ReadableDataLen >= PayloadLen) { byte[] DecryptedBuffer = null; int DecryptedBuffLen = 0; messageHandler.DecryptMessage(this, Buffer, ReadOffset, PayloadLen, ref DecryptedBuffer, ref DecryptedBuffLen); if (DecryptedBuffer == null) { //failed to decrypt data Disconnect(); return; } TotalReceived += PayloadLen; using (PayloadReader pr = new PayloadReader(DecryptedBuffer)) { OperationalSocket OpSocket = null; if (ConnectionId > 0) { lock (OperationalSockets) { if (!OperationalSockets.TryGetValue(ConnectionId, out OpSocket)) { //strange... Disconnect(); return; } } } Type type = Headers.GetHeaderType(HeaderId); if (type != null) { Header header = Header.DeSerialize(type, pr); if (header == null) { Disconnect(); return; } uint MessageId = pr.ReadUInteger(); IMessage message = OpSocket != null?OpSocket.MessageHandler.DeSerialize(pr, MessageId) : messageHandler.DeSerialize(pr, MessageId); if (message != null) { message.RawSize = TotalReceived; message.Header = header; if (!HandShakeCompleted) { if (message.GetType() == typeof(MsgHandshake)) { //process the handshake messages straight away message.ProcessPayload(Client, null); } } else { ProcessMessage(new SystemPacket(header, message, ConnectionId, OpSocket)); } } } else { Disconnect(); return; } } TotalReceived = 0; PacketsIn++; ReadOffset += PayloadLen; ReadableDataLen -= PayloadLen; ReceiveState = ReceiveType.Header; } } } int len = ReceiveState == ReceiveType.Header ? HEADER_SIZE : PayloadLen; if (ReadOffset + len >= this.Buffer.Length) { //no more room for this data size, at the end of the buffer ? //copy the buffer to the beginning Array.Copy(this.Buffer, ReadOffset, this.Buffer, 0, ReadableDataLen); WriteOffset = ReadableDataLen; ReadOffset = 0; } else { //payload fits in the buffer from the current offset //use BytesTransferred to write at the end of the payload //so that the data is not split WriteOffset += BytesTransferred; } if (Buffer.Length - WriteOffset > 0) { Handle.BeginReceive(this.Buffer, WriteOffset, Buffer.Length - WriteOffset, SocketFlags.None, AynsReceive, null); } else { //Shoudln't be even possible... very strange Disconnect(); } } catch (Exception ex) { //unexpected error, client might have disconnected itself, or else report this error SysLogger.Log(ex.Message, SysLogType.Error); Disconnect(); return; } }
internal void StartReceiver() { Handle.BeginReceive(this.Buffer, 0, this.Buffer.Length, SocketFlags.None, AynsReceive, null); }