Esempio n. 1
0
 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);
        }