public void OnClientDisconnected(AsyncTCPLib.OnClientDisconnectedEventArgs <AsyncTCPLib.VirtualClient> e) { Association.Carrier userCarrier = this._associations[e.Client.Id]; if (userCarrier != null) { long accountId = Program.GetInstance().Server.Clients[e.Client.Id].Data.AuthenticationInfo.Id; if (userCarrier.Command == Socks.Constants.Command.Connect) { Association.ConnectProxy proxy = (Association.ConnectProxy)userCarrier.Data; Commit.Info info = new Commit.Info(accountId); if (userCarrier.WiredTx > 0 || userCarrier.WiredRx > 0) { info.Stats = new Commit.Stats(userCarrier.WiredTx, userCarrier.WiredRx); } info.Command = new Commit.Command( userCarrier.Command, e.Client.RemoteEndPoint, proxy.Client.RemoteEndPoint, userCarrier.WiredTx, userCarrier.WiredRx, userCarrier.CommandTime, userCarrier.CommandSuccess ); this._plugin.CommitInfo(info); } this._associations[e.Client.Id] = null; } }
/// <summary> /// IStateDependentHandler.Transmission implementation for AuthenticationState.Transmitting /// </summary> /// <returns>True if connection left open, false if not</returns> async Task <bool> Plugin.IStateDependentHandler.Transmission(Client client, byte[] message) { Association.Carrier userCarrier = this._associations[client.Id]; if (userCarrier != null) { await userCarrier.Transmission(message); return(true); } return(false); }
/// <summary> /// IStateDependentHandler.Command implementation for AuthenticationState.Authenticated /// </summary> /// <returns>True if connection left open, false if not</returns> async Task <bool> Plugin.IStateDependentHandler.Command(Client client, Plugin.ISocksMessage message) { bool returnData = false; Socks5S.Socks.Message.Command typedMessage = message as Socks5S.Socks.Message.Command; if (typedMessage.SocksCommand != Socks.Constants.Command.Connect) { Program.GetInstance().Log.InfoFormat("COMMAND: {0}", typedMessage.SocksCommand); } if (typedMessage.SocksVersion == Socks.Constants.Socks.Version) { using (MemoryStream responseStream = new MemoryStream()) using (BinaryWriter responseWriter = new BinaryWriter(responseStream)) { if (typedMessage.AddressType == Socks.Constants.AddressType.Domain && !typedMessage.DnsSuccess) { // domain resolve error responseWriter.Write(Socks.Constants.Socks.Version); responseWriter.Write((byte)Socks.Constants.Reply.HostUnreachable); responseWriter.Write((byte)0); responseWriter.Write((byte)Socks.Constants.AddressType.Domain); responseWriter.Write((byte)typedMessage.Domain.Length); responseWriter.Write(Encoding.UTF8.GetBytes(typedMessage.Domain)); responseWriter.Write((short)IPAddress.HostToNetworkOrder(typedMessage.DestinationPort)); responseWriter.Flush(); byte[] responseHostUnreachableData = responseStream.GetBuffer(); Array.Resize(ref responseHostUnreachableData, (int)responseStream.Length); await client.Send(responseHostUnreachableData); } else { if (typedMessage.DestinationAddress == IPAddress.Loopback || typedMessage.DestinationAddress == IPAddress.IPv6Loopback) { // not allowed to access local network responseWriter.Write(Socks.Constants.Socks.Version); responseWriter.Write((byte)Socks.Constants.Reply.ConnectionNotAllowedByRuleset); responseWriter.Write((byte)0); responseWriter.Write((byte)(typedMessage.AddressType == Socks.Constants.AddressType.Domain ? Socks.Constants.AddressType.IPv4 : typedMessage.AddressType)); responseWriter.Write(typedMessage.DestinationAddress.GetAddressBytes()); responseWriter.Write((short)IPAddress.HostToNetworkOrder(typedMessage.DestinationPort)); responseWriter.Flush(); byte[] responseHostUnreachableData = responseStream.GetBuffer(); Array.Resize(ref responseHostUnreachableData, (int)responseStream.Length); await client.Send(responseHostUnreachableData); } IPEndPoint remoteEndPoint = new IPEndPoint(typedMessage.DestinationAddress, typedMessage.DestinationPort); if (this._associations[client.Id] == null) { Association.Carrier carrier = null; bool isImplemented = true; try { if (typedMessage.SocksCommand == Socks.Constants.Command.Connect) { carrier = new Association.Carrier(Socks.Constants.Command.Connect, remoteEndPoint, ProtocolType.Tcp, this._bufferManager[client.Id].Data); } else if (typedMessage.SocksCommand == Socks.Constants.Command.UdpAssociate) { carrier = new Association.Carrier(Socks.Constants.Command.UdpAssociate, remoteEndPoint, ProtocolType.Udp, this._bufferManager[client.Id].Data); } } catch (NotImplementedException) { isImplemented = false; } if (!isImplemented) { responseWriter.Write(Socks.Constants.Socks.Version); responseWriter.Write((byte)Socks.Constants.Reply.CommandNotSupported); responseWriter.Write((byte)0); responseWriter.Write((byte)(typedMessage.AddressType == Socks.Constants.AddressType.Domain ? Socks.Constants.AddressType.IPv4 : typedMessage.AddressType)); responseWriter.Write(typedMessage.DestinationAddress.GetAddressBytes()); responseWriter.Write((short)IPAddress.HostToNetworkOrder(typedMessage.DestinationPort)); responseWriter.Flush(); byte[] errorResponse = responseStream.GetBuffer(); Array.Resize(ref errorResponse, (int)responseStream.Length); await client.Send(errorResponse); } // terminate the function on catch, can't return asynchronous on catch if (carrier == null) { return(false); } bool connectSuccess = false; carrier.Data.Client.OnClientDisconnected += (s, e) => { if (connectSuccess) { Program.GetInstance().Log.DebugFormat("Proxy connection {0} quit connection to {1}", remoteEndPoint, client.RemoteEndPoint); } client.Disconnect(); }; carrier.Data.Client.OnClientConnected += (s, e) => { connectSuccess = true; Program.GetInstance().Log.DebugFormat("Client {0} opened connection on {1} successfully", client.RemoteEndPoint, remoteEndPoint); }; carrier.Data.Client.OnClientDataReceived += async(s, e) => { carrier.WiredRx += e.Data.Length; //Program.GetInstance().Log.DebugFormat("Recv: {0}", BitConverter.ToString(e.Data)); await client.Send(e.Data); }; this._associations[client.Id] = carrier; await Task.Run(() => { carrier.Data.Client.Connect(); }); if (!connectSuccess) { Program.GetInstance().Log.DebugFormat("Client {0} connection to {1} failed", client.RemoteEndPoint, remoteEndPoint); } carrier.CommandSuccess = connectSuccess; responseWriter.Write(Socks.Constants.Socks.Version); responseWriter.Write(connectSuccess ? (byte)Socks.Constants.Reply.Succeeded : (byte)Socks.Constants.Reply.ConnectionRefused); responseWriter.Write((byte)0); if (typedMessage.DestinationAddress.AddressFamily == AddressFamily.InterNetwork) { responseWriter.Write((byte)Socks.Constants.AddressType.IPv4); } else if (typedMessage.DestinationAddress.AddressFamily == AddressFamily.InterNetworkV6) { responseWriter.Write((byte)Socks.Constants.AddressType.IPv6); } responseWriter.Write(typedMessage.DestinationAddress.GetAddressBytes()); responseWriter.Write((short)IPAddress.HostToNetworkOrder(typedMessage.DestinationPort)); responseWriter.Flush(); byte[] responseCommand = responseStream.GetBuffer(); Array.Resize(ref responseCommand, (int)responseStream.Length); client.Data.AuthenticationState = Socks.Constants.AuthenticationState.Transmitting; await client.Send(responseCommand); returnData = connectSuccess; } else { throw new Exception("Proxy data already associated for client id " + client.Id.ToString() + ", " + client.RemoteEndPoint.ToString()); } } /* * // Command not supported response * { * responseWriter.Write(Socks.Constants.Socks.Version); * responseWriter.Write((byte)Socks.Constants.Reply.CommandNotSupported); * responseWriter.Write((byte)0); * responseWriter.Write((byte)(typedMessage.AddressType == Socks.Constants.AddressType.Domain ? Socks.Constants.AddressType.IPv4 : typedMessage.AddressType)); * responseWriter.Write(typedMessage.DestinationAddress.GetAddressBytes()); * responseWriter.Write((short)IPAddress.HostToNetworkOrder(typedMessage.DestinationPort)); * responseWriter.Flush(); * * byte[] responseData = responseStream.GetBuffer(); * Array.Resize(ref responseData, (int)responseStream.Length); * * client.Send(responseData); * } */ } } return(returnData); }