"An established connection was aborted by the software in your host machine." after establishing a SSH connection to a juniper firewall

Apr 5, 2013 at 10:55 AM
Edited Apr 5, 2013 at 11:00 AM
hello!

I am trying to execute some commands on a Juniper SSG 350M (with default settings, but ssh enabled on all interfaces) Firewall, after establishing a ssh connection... but I always get the same error:

"An established connection was aborted by the software in your host machine."

My code looks as follows:
ConnectionInfo connInfo = new PasswordConnectionInfo(host, 22, username, password);

connInfo.Timeout = TimeSpan.FromMinutes(30);
                                
SshClient client = new SshClient(connInfo);

try
{
    client.Connect();
}
catch (Exception ex)
{
    textBox1.Text += "++++++++++++++++" + ex.StackTrace.ToString() + "\r\n";
    textBox1.Text += "++++++++++++++++" + ex.Message.ToString() + "\r\n";
}
//textBox1.Text += client.ConnectionInfo.GetType();
String command = "get system version";
                                    
SshCommand cmd99 = null;
try
{

    cmd99 = client.RunCommand(command);
}
catch (Exception ex)
{
    textBox1.Text += "######################" + ex.StackTrace.ToString() + "\r\n";
    textBox1.Text += "######################" + ex.Message.ToString() + "\r\n";
}
client.Disconnect();
After executing the code, the exception occurs at the client.RunCommand(command) line. My output:

Starting SSH Connection to 192.168.1.1
at Renci.SshNet.Session.WaitHandle(WaitHandle waitHandle)
at Renci.SshNet.Channels.Channel.WaitHandle(WaitHandle waitHandle)
at Renci.SshNet.Channels.ChannelSession.SendExecRequest(String command)
at Renci.SshNet.SshCommand.BeginExecute(AsyncCallback callback, Object state)
at Renci.SshNet.SshCommand.Execute()
at Renci.SshNet.SshClient.RunCommand(String commandText)
at WindowsFormsApplication1.Form1.button1_Click(Object sender, EventArgs e) in C:\Users\dsteiner\Documents\Visual Studio 2010\Projects\SSHNET-Connector\WindowsFormsApplication1\Form1.cs:line 140
An established connection was aborted by the software in your host machine.
Connection to 192.168.1.1 closed



The juniper firewall system log writes:

2013-04-05 19:00:39 warn SCP: Admin 'netscreen' at host 192.168.1.99 executed invalid scp command: 'get system version'.
2013-04-05 19:00:39 warn SSH: Password authentication successful for admin user 'netscreen' at host 192.168.1.99.


So I think that the connection was successful, but the command isn't working. Why? Is it because the RunCommand executes a SCP-command (see firewall log)?

btw, the SSH conneciton via putty is successfull, also when entering the command "get system version" afterwards...

please help me. thank you
Coordinator
Apr 6, 2013 at 6:59 PM
I think that device does not allow execution of "get system version" command.

Its probably valid but only when executed using Shell.
Some SSH implementations restrict what can be done or executed and it might be the case.
Hope it explains.

Thanks,
Oleg
Apr 8, 2013 at 10:09 AM
Thanks for the reply,
well, I found a solution... the command itself was not the problem, but using the RunCommand() method was so. Instead of the RunCommand() method I used the shellstream example from https://sshnet.codeplex.com/discussions/348421 and now it works!
using System;
using System.IO;
using System.Threading;
using Renci.SshNet;
 
namespace ConsoleApplications
{
    public class Program
    {
        private static System.ComponentModel.IContainer components;
 
        private static void Main(string[] args)
        {
            using (var client = new SshClient(host, "admin", "abc"))
            {
                client.Connect();
 
                using (var stream = client.CreateShellStream("dumb", 80, 24, 800, 600, 1024))
                {
                    var reader = new StreamReader(stream);
                    var writer = new StreamWriter(stream);
                    writer.AutoFlush = true;
 
                    while (stream.Length == 0)
                    {
                        Thread.Sleep(500);
                    }
                    ReadStream(reader);
 
                    WriteStream("show run", writer, stream);
                    ReadStream(reader);
 
                    WriteStream("show ver", writer, stream);
                    ReadStream(reader);
                }
 
                client.Disconnect();
            }
        }
 
        private static void ReadStream(StreamReader reader)
        {
            string line = reader.ReadLine();
            while (line != null)
            {
                Console.WriteLine(line);
                line = reader.ReadLine();
            }
        }
 
        private static void WriteStream(string cmd, StreamWriter writer, ShellStream stream)
        {
            writer.WriteLine(cmd);
            while (stream.Length == 0)
            {
                Thread.Sleep(500);
            }
        }
    }
}
Apr 8, 2013 at 10:57 AM
another question:

Is it possible to get the name of the firewall during the connection establishment or after a successfull connection? I have to know it to be able to send the correct commands to the correct firewall in my source code.

I tried to implement it as follows:
var line = reader.ReadLine();
while (line != null)
{
    line = reader.ReadLine();
    deviceName = line.Substring(0, line.Length - 3);
     textBox1.Text += "\r\n+++++++DEVICE-NAME+++: " + deviceName + "\r\n";
}
but the problem is that the hostname can be changed when configuring the firewall. So is there any possibility to get the real type of the firewall?
Thanks in advance!
Coordinator
Apr 8, 2013 at 1:41 PM
Hi,

Unfortunately I do not know how this can be done.

If you can find a specification of it or code example I can try to incorporate it in the future release.

Thanks,
Oleg
Apr 9, 2013 at 9:06 AM
I unfortunately don't have any specification, I even think that there won't be sent any information about the server during the connection establishment. I solved it by commiting type-specific commands and requested the answers that I get from the device.

e.g.
bool flag = false;
writer.WriteLine("root"); 

while (stream.Length == 0)
{
    Thread.Sleep(500);
}
line = reader.ReadLine();
while (line != null)
{
    if (line.Contains("unknown keyword"))
    {
        flag = true;
        break;
    }
    textBox1.Text += "\r\n" + line;
    line = reader.ReadLine();
}

if (flag == true)
{
    textBox1.Text += "\r\nThis device is a SSG-30M\r\n";
}
else
{
    textBox1.Text += "\r\nThis is another device\r\n";
}
Aug 19, 2013 at 2:52 PM
I ran into this exact issue, and threw together some solutions I found scattered around. As this issue seems to be limited to specific Juniper network devices, as this thread is the top result in searches for "Juniper SSH.Net" maybe posting my solution here will help some other hapless souls like myself.

Utilizing this Powershell SSH.Net module and the latest SSH.Net (for .net 3.5, but also tested and validated against 4.0).

This is my Powershell solution for automating running commands against my Juniper appliance:
function RunSSHCommand(){
    param(
        [string]$computername,
        [string]$sshcommand
    );
    if($global:sshStream -eq $null){
        $global:sshStream=($global:sshsessions).$computername.CreateShellStream(([string](new-object system.random).next()).Substring(0,5), 80, 24, 800, 600, 1024);
    }
    if($global:sshStream -ne $null){
        $output="";
        $reader= New-Object -typename System.IO.StreamReader -argumentlist $global:sshStream ;
        $writer= New-Object -typename System.IO.StreamWriter -argumentlist $global:sshStream ;
        $writer.autoflush=$true;
        
        $writer.WriteLine(" ");$writer.flush();
        for($i=0;$i -lt 10;$i++){if($global:sshStream.length -eq 0){start-sleep -Milliseconds 250;}else{break;}}
        $line=$reader.readline();
        while($line -ne $null){$line;$line=$reader.readline();}
        
        $writer.WriteLine($sshcommand);$writer.flush();
        while($global:sshStream.length -eq 0){start-sleep -Milliseconds 250;}
        $line=$reader.readline();
        while($line -ne $null){$output+=$line;$line;$line=$reader.readline();}
        <#
        $writer.close();
        $reader.close();
        $stream.close();$stream.dispose(); 
        #>
    }else{
        "RunSSHCommand:Failed. Unable to CreateShellStream against SSHSession($computername)";
    }
if($output -ne ""){return $output;}
}

import-module ssh-sessions;
$computername="192.168.1.254";
new-sshsession -computername $computername -username netscreen;
RunSSHCommand -computername $computername -sshcommand "get system version";
RunSSHCommand -computername $computername -sshcommand "get admin user login";
remove-sshsession -computername $computername;
[[Yes, i'm aware the coding practice of using Globals isn't epic, but its functional and doesn't violate the environment i'm working in, please feel free to modify it to suit your own needs]]

Cheer,
-TheJonnyG