예제 #1
0
        /// <summary>
        /// Runs Reverse SSH Tunnel, using command: "ssh -NvR bindAddress:remoteAccessPort:localSideHost:localSidePort user@remoteHost
        /// </summary>
        /// <param name="bindAddress">
        /// By default, the listening socket on the server will be bound to the loopback interface only.
        /// This may be overridden by specifying a bind_address.
        /// An empty bind_address, or the address '*', indicates that the remote socket should listen on all interfaces.
        /// Specifying a remote bind_address will only succeed if the server's GatewayPorts option is enabled.
        /// </param>
        /// <returns></returns>
        public bool Start(string bindAddress = DEFAULT_BIND_ADDRESS)
        {
            if (bindAddress == DEFAULT_BIND_ADDRESS && !IsHostChanged)
            {
                LastStartedCommandSSH = DefaultSSHCommand;
            }
            else
            {
                LastStartedCommandSSH = CreateCommandString(SSH_FORMAT_STRING, bindAddress, RemoteHost.Port, LocalSideHost.IP, LocalSideHost.Port, RemoteHost.User, RemoteHost.IP);
            }

            _SSHProcess = new BashProcess(LastStartedCommandSSH);

            _SSHProcess.StandardOutputStringReceived += _SSHProcess_StandardOutputStringReceived;
            _SSHProcess.StandardErrorStringReceived  += _SSHProcess_StandardOutputStringReceived;

            IsTunnelEstablished = _SSHProcess.RunNewProcess(true, true, true);
            return(IsTunnelEstablished);
        }
예제 #2
0
        /// <summary>
        /// Finds old processes used by last command and kill them
        /// </summary>
        /// <returns>Current tunnel connection type</returns>
        public async Task <(TunnelConnectionState, string)> CheckAndKillOldProcesses()
        {
            try
            {
                if (await CheckConnectionType() != TunnelConnectionState.NoConnection)
                {
                    List <int> PIDs = BashProcess.FindPIDs(LastStartedCommandSSH ?? DefaultSSHCommand);
                    foreach (int pid in PIDs)
                    {
                        BashProcess.KillProcess(pid);
                    }
                }

                return(await CheckConnectionType(), null);
            }
            catch (TunnelEstablishedException ex)
            {
                return(TunnelConnectionState.StoppedWithoutChecking, ex.Message);
            }
        }
예제 #3
0
        /// <summary>
        /// Checking connection type (local/remote) / state (connected/disconnected)
        /// (To execute this method, device must be ssh authorised_host (ssh can't ask for password))
        /// </summary>
        /// <returns>Tunnel connection state or throws TunnelUnknownConnectionStateException when netstat has no result.</returns>
        /// <exception cref="TunnelUnknownConnectionStateException">When netstat on remote device (command executed via SSH) returns null/whitespace (no netstatResult)
        /// or when regexp match for netstat result, finds other address (than `0.0.0.0`/`127.0.0.1`) using tunnel's port.</exception>
        public async Task <TunnelConnectionState> CheckConnectionType()
        {
            string netstatLocalAddress = null;

            BashProcess netstatProcess = new BashProcess($"ssh {RemoteHost.User}@{RemoteHost.IP} netstat -tlnp")
            {
                SubscribeStandardOutput = false
            };

            string netstatResult = await netstatProcess.RunNewProcessAndReadStdOutputAsync();

            if (!string.IsNullOrWhiteSpace(netstatResult))
            {
                Regex regex = new Regex($@"[0-255].[0-255].[0-255].[0-255](?=:{RemoteHost.Port})");
                Match match = regex.Match(netstatResult);
                if (match.Success)
                {
                    netstatLocalAddress = match.Groups[0].Value;
                }

                switch (netstatLocalAddress)
                {
                case "0.0.0.0":
                    IsTunnelEstablished = true;
                    return(TunnelConnectionState.RemoteConnection);

                case "127.0.0.1":
                    IsTunnelEstablished = true;
                    return(TunnelConnectionState.LocalConnection);

                case null:      // No match for regexp pattern - it means, no connection established
                    IsTunnelEstablished = false;
                    return(TunnelConnectionState.NoConnection);

                default:
                    throw new TunnelUnknownConnectionStateException($"Unknown Tunnel Connection State: {netstatLocalAddress}");
                }
            }

            throw new TunnelUnknownConnectionStateException("Unknown Tunnel Connection State: no netstatResult");
        }