1

I have a problem in C# when trying to open a SSH tunnel on 127.0.0.1:9999.

This is my Program.cs

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Begin");

        PlinkTest plink = new PlinkTest();

        String feedback = plink.CreateTunnel("1.2.3.4", "user", "user");

        Console.WriteLine("THING:" + feedback);

        Console.Read();
    }
}

This is my program, PlinkTest.cs:

class PlinkTest
{
    String PATH_TO_PLINK = @"C:\plink\plink.exe";
    public PlinkTest()
    {
    }

    public string RequestInfo(string remoteHost, string userName, string password, string[] lstCommands)
    {
        m_szFeedback = "Feedback from: " + remoteHost + "\r\n";

       //  ProcessStartInfo psi = new ProcessStartInfo("echo y | C:\\plink\\plink.exe")
        ProcessStartInfo psi = new ProcessStartInfo("C:\\plink\\plink.exe")
        {
            Arguments = String.Format("-ssh -N -D 9999 user@1.2.3.4 -pw user -v"),
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        Process p = Process.Start(psi);

        m_objLock = new Object();
        m_blnDoRead = true;

        AsyncReadFeedback(p.StandardOutput); // start the async read of stdout
        AsyncReadFeedback(p.StandardError); // start the async read of stderr

        StreamWriter strw = p.StandardInput;

        foreach (string cmd in lstCommands)
        {
            strw.WriteLine(cmd); // send commands 
        }
        strw.WriteLine("exit"); // send exit command at the end

        p.WaitForExit(); // block thread until remote operations are done
        return m_szFeedback;
    }


    public string CreateTunnel(string remoteHost, string userName, string password)
    {
        m_szFeedback = "Feedback from: " + remoteHost + "\r\n";

        //  ProcessStartInfo psi = new ProcessStartInfo("echo y | C:\\plink\\plink.exe")
        ProcessStartInfo psi = new ProcessStartInfo(PATH_TO_PLINK)
        {
            Arguments = String.Format("-ssh -N -D 9999 user@1.2.3.4 -pw user -v"),
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        Process p = Process.Start(psi);

        m_objLock = new Object();
        m_blnDoRead = true;

        AsyncReadFeedback(p.StandardOutput); // start the async read of stdout
        AsyncReadFeedback(p.StandardError); // start the async read of stderr

        StreamWriter strw = p.StandardInput;


        // SLEEP HERE 10 SEC

        strw.WriteLine("exit"); // send exit command at the end

        p.WaitForExit(); // block thread until remote operations are done
        return m_szFeedback;
    }


    private String m_szFeedback; // hold feedback data
    private Object m_objLock; // lock object
    private Boolean m_blnDoRead; // boolean value keeping up the read (may be used to interrupt the reading process)

    public void AsyncReadFeedback(StreamReader strr)
    {
        Thread trdr = new Thread(new ParameterizedThreadStart(__ctReadFeedback));
        trdr.Start(strr);
    }
    private void __ctReadFeedback(Object objStreamReader)
    {
        StreamReader strr = (StreamReader)objStreamReader;
        string line;
        while (!strr.EndOfStream && m_blnDoRead)
        {
            line = strr.ReadLine();
            // lock the feedback buffer (since we don't want some messy stdout/err mix string in the end)
            lock (m_objLock) { m_szFeedback += line + "\r\n"; }
        }
    }
}

FIRST PROBLEM

The first problem I am facing is accepting RSA key automatically, whitch I can do running

echo y |plink.exe -ssh -N -D 9999 user@1.2.3.4 -pw user -v

but it turns out that I get an error when I use echo y | at Process p = Process.Start(psi); line where psi variable is ok. I know how to put arguments after with Arguments = String.Format("-ssh -N -D 9999 user@1.2.3.4 -pw user -v"), but i don't know how to put them in front of the command.

SECOND PROBLEM

The second problem is that I don't want to wait for the content because when I am creating the tunnel it says nothing, just waiting. I just want to open a SSH tunnel in background on 127.0.0.1:9999, that's all.

What do I have to change?

Thanks.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Fitman
  • 11
  • 4

3 Answers3

1
  1. To verify an SSH host key, use the -hostkey switch. Do not try to skip the host key verification. It's there to protect you from man-in-the-middle attacks.

    Arguments = String.Format("-ssh -N -D 9999 user@1.2.3.4 -pw user -v -hostkey aa:bb:cc:dd:..."),
    

    Anyway, your piping syntax does not work on its own, because it's cmd.exe that understands it only, so you would have to run it like:

    ProcessStartInfo psi = new ProcessStartInfo("cmd.exe")
    {
        Arguments = String.Format("/C echo y | C:\\plink\\plink.exe -ssh -N -D 9999 user@1.2.3.4 -pw user -v"),
    }
    

    But again, do not do it!

  2. i don't want to wait for the content

So, do not wait.

We do not know, what you application purpose is.

If just to open the tunnel, then make it wait (for a key press?) indefinitely, to keep the tunnel open.

If the application is going to use the tunnel, then just carry on with the other tasks, without closing the SSH session.


You should better use a native .NET SSH library for the tunnel, then using an external application.

For example the SSH.NET. See .NET SSH Port Forwarding

Community
  • 1
  • 1
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
-1

Obviously it is not possible to do io redirection with echo in your scenario.

Try to send the y to plink using the strw.WriteLine(...); you already have in place or create a yes.txt file in which you put a single y and have plink read its content with plink < yes.txt.

A quick scan of plinks manual page showed no parameter that enables you to specify an "all-yes mode".

Marged
  • 10,577
  • 10
  • 57
  • 99
  • so y can just put after `StreamWriter strw = p.StandardInput;` line a `strw.WriteLine("y");` ? is that ok? – Fitman Oct 16 '15 at 22:43
  • you can try, it won't kill any animals if it fails ;-) – Marged Oct 16 '15 at 22:44
  • and believe me, i tried that `all-yes mode` ... it is not available in the lastest versions of `plink` – Fitman Oct 16 '15 at 22:44
  • the thing is that i have to somehow delete the actual `RSA KEY` to triger that question of "do you wan to .... cache ... (y/n)" ... and i don't now that yet, i will give a try though ... – Fitman Oct 16 '15 at 22:53
  • when i am logging on a server i am not using this, i only use `putty` but i just want to create a tunnel, even if i give you 1.2.3.4 user user you cannot do anything with it because it does not have shell attached, it is only tunnel, that's all, so no need to not have an "all-yes mode". Understand now? Anyway, i have solved the problem here is the link http://pastebin.com/ChzAu82E ... what do you think about this? It is ok? Have to addmit, you help me a lot, thanks! – Fitman Oct 26 '15 at 01:38
  • You are tunneling through SSH for some reason, right? The reason is security. If you do not verify the host key, no security. So, no, I do not understand. – Martin Prikryl Oct 26 '15 at 05:57
-1

Just execute this code ....it will take cache key... string sPlinkPath = @" ""C:\Program Files (x86)\PuTTY\plink.exe"" ";

        string sCommandToStoreKeyInCach = "echo y |"+ sPlinkPath + clsGlobalVariables.sIpAdd + " -pw XXXX exit";

        Process GetCpuInfo = new Process();

        // Redirect the output stream of the child process.
        GetCpuInfo.StartInfo.UseShellExecute = false;
        GetCpuInfo.StartInfo.RedirectStandardInput = true;
        GetCpuInfo.StartInfo.RedirectStandardOutput = true;
        GetCpuInfo.StartInfo.RedirectStandardError = true;

        GetCpuInfo.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
        GetCpuInfo.StartInfo.Arguments = "/c " + sCommandToStoreKeyInCach;

        GetCpuInfo.StartInfo.CreateNoWindow = true;
        GetCpuInfo.Start();

        GetCpuInfo.WaitForExit();

Tell me if this doesn't...work...

kki
  • 1
  • 2