This question already has an answer here:
Providing input/subcommands to a command (cli) executed with SSH.NET SshClient.RunCommand
(1 answer)
Closed 3 years ago.
I've created a simple app which uses the Renci.SshNet library to update firewall configuration on my Fortigate device.
var auth =
new AuthenticationMethod[] { new PasswordAuthenticationMethod(username, password) };
ConnectionInfo ConnNfo = new ConnectionInfo(server, 22, username, auth);
sshclient.Connect();
string command;
string addressname = "testaddress";
command = "config firewall address";
output.Add(command);
output.Add(sshclient.CreateCommand(command).Execute());
command = string.Format(#"edit {0}", addressName);
output.Add(command);
output.Add(sshclient.CreateCommand(command).Execute());
sshclient.Disconnect();
I get the following from the output:
config firewall address
fw1 # fw1 (address) #
edit testaddress
fw1 # Unknown action 0 fw1 #
The same commands work fine over a normal SSH connection.
fw1 # config firewall address
fw1 (address) # edit testaddress
new entry 'testaddress' added
fw1 (testaddress) #
Just wondering if I'm using it correctly sending separate CreateCommans.Execute().
If I understand it correctly, the edit testaddress is a subcommand of the config firewall address command.
While your code executes it as a separate top-level command.
You have to feed the edit testaddress subcommand to the input of the config firewall address command. But SSH.NET unfortunately does not support providing an input with the CreateCommand interface.
You have to open a shell session (what is otherwise a not recommended approach for automating a command execution).
Use SshClient.CreateShellStream or SshClient.CreateShell and send the commands to its input:
"config firewall address\nedit testaddress\n"
For a sample code see C# send Ctrl+Y over SSH.NET.
Related
I have an Open Source Voice Chatting application which works fine on LAN.
But the problem is with connecting two PCs Manually.
Let's suppose there are two PCs (Application instances), PC A and PC B.
To make a connection I have to put the IP Address of the PC A into PC B and IP Address of the PC B into PC A.
I want to make the small code change where if the application is running on two PCs and they both are connected via LAN then both sides get the IP address automatically. Like auto-detection.
So my logic was to first know the IP Address on the LAN using arp -a command then writes the output in a text file and only obtain the IP addresses that start with 192... and check the instance of the application on each address using This Solution.
Unfortunately, I end up getting an error which states that.
Unhandled Exception: System.Runtime.InteropServices.COMException: The
RPC server is unavailable.
at
System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32
errorCode, IntPtr errorInfo) at
System.Management.ManagementScope.InitializeGuts(Object o) at
System.Management.ManagementScope.Initialize() at
System.Management.ManagementObjectSearcher.Initialize() at
System.Management.ManagementObjectSearcher.Get()
This is the code which i used to accomplish this task.
//Write the cmd Output in a text file
string strCmdText;
strCmdText = #"/K arp -a > C:\Test\Result.txt";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
//To get the IP address which starts with the 192.
const string ipPattern = #"^\s*(192\.168\.\d{1,3}\.\d{1,3}\b)";
var ipRegex = new Regex(ipPattern);
var ipAddresses192168 = File.ReadAllLines(#"C:\Test\Result.txt")
.Skip(3) // Skip 3 lines
.Where(line => ipRegex.IsMatch(line))
.Select(line => ipRegex.Match(line).Groups[1].Value);
foreach (var ipAddress in ipAddresses192168)
{
Console.WriteLine(ipAddress);
// Check for the running instance of the application on LAN network.
ManagementScope scope = new ManagementScope(#"\\" + ipAddress + #"\root\cimv2");
string query = "SELECT * FROM Win32_Process WHERE Name='WavPlayer.exe'";
var searcher = new ManagementObjectSearcher(query);
searcher.Scope = scope;
bool isRunning = searcher.Get().Count > 0;
}
So my question is, Is there any other straight forward process to accomplish this task using C#.net?
I am available to provide more info about this question so any help is appreciated.
I am doing SSH to a Linux machine and again from there want to SSH to another Linux machine to carry out few Perforce tasks.
using (SshClient ssh = new SshClient("ip address","username", "pwd"))
{
ssh.Connect();
command = ssh.CreateCommand("ssh hostname");
result = command.Execute();
Console.WriteLine(result);
}
Where the ssh hostname is a password less ssh. How can I control the second SSH session and pass commands to it?
Even explored the CreateShell function, but seems like it is not suggested for automation.
In general, trying to automate ssh command is a bad design.
You better use a port forwarding (aka SSH tunnel) to implement the "hop".
var firstClient =
new SshClient(firstHostName, firstUserName, firstPassword);
firstClient.Connect();
var port = new ForwardedPortLocal("127.0.0.1", secondHostName, 22);
firstClient.AddForwardedPort(port);
port.Start();
var secondClient =
new SshClient(port.BoundHost, (int)port.BoundPort, secondUserName, secondPassword);
secondClient.Connect();
var command = secondClient.CreateCommand("ls");
var result = command.Execute();
Console.WriteLine(result);
There are some cases, when automating the ssh is acceptable (while still not ideal). E.g. because there's an authentication to the second host set up on the first one. I.e. there might be private key in the .ssh folder and you are not allowed to transfer that key to your client machine.
Even then, try talking to the system Administrator to find a better solution. The private key is still accessible using the credentials contained in your application, so it's not protected any better, had the private key itself been contained directly in the application.
Anyway, ssh can accept a command on its command line, like:
command = ssh.CreateCommand("ssh hostname command");
result = command.Execute();
Console.WriteLine(result);
I'm currently doing an assignment where I want my program to be able to read and update a database. The database itself runs on oracle and was provided by my university (I have my own schema I believe?)
Right now I can connect via SSH using programs such as teraterm or putty, once I log in it takes me to an interactive menu which allows me to select a few various options. One of which is shell. Once I select that I am able to use bash commands to log into the SQL section and use these:
bash$ export ORACLE_HOME=/opt/oracle/product/client/11.2.0
bash$ export TWO_TASK=SSID
bash$ $ORACLE_HOME/bin/sqlplus
to connect to the SQL database. Easy.
However, I want to be able to do that through my program and it is proving difficult for me. I am using SSH.NET and can connect via SSH seemingly well. The problem is I cannot access the SQL section. When I run the commands the first two work correctly I believe, but the last one does not. It seems to not be able to see the anything past $ORACLE_HOME. When I "echo $ORACLE_HOME /*" it even tells me that /bin is a folder:
/bin /boot /dev /etc /export /hey.php /home /lib /lib64 /local /lost+found /media /misc
/mnt /opt /proc /root /sbin /selinux /srv /stage /sys /tmp /usr /var
But instead, when I run the last line of code I get the error message:
Error = "bash: /bin/sqlplus: No such file or directory\n"
I'm not sure whether there is an easier way of accessing the SQL stuff... But I am very close using SSH.NET but I just can't see why I can't open the SQL section like I can in putty or teraterm...
Any help would be greatly appreciated, thank you for your time.
My actual C# code is this:
//Connection information
string user = "SSHusername";
string pass = "password";
string host = "address";
//Set up the SSH connection
using (var client = new SshClient(host, user, pass))
{
//Start the connection
client.Connect();
var output = client.RunCommand("export ORACLE_HOME=/opt/oracle/product/client/11.2.0");
Console.WriteLine(output.Result);
output = client.RunCommand("export TWO_TASK=SSID");
Console.WriteLine(output.Result);
output = client.RunCommand("$ORACLE_HOME/bin/sqlplus");
Console.WriteLine(output.Result);
output = client.RunCommand("username");
Console.WriteLine(output.Result);
output = client.RunCommand("password");
Console.WriteLine(output.Result);
output = client.RunCommand("SELECT * FROM users;");
Console.WriteLine(output.Result);
client.Disconnect();
Console.WriteLine(output.Result);
}
1.I suggest you use native C# package for connect Oracle. You will get wrong format of output.
I see your variable is not work. Because SQLPLUS client should be under
$ORACLE_HOME/bin/sqlplus. But your code show /bin/sqlplus. Means $ORACE_HOME not work.
You can directly change code and run directly sqlplus like /opt/oracle/product/client/11.2.0/bin/sqlplus user/pass#SSID
You can set some script on remote oracle server and get result over that or upload script from C# host to remote each time.
If you're using the SSH.NET library, using a Shell instead of separate Commands should work - something like (untested):
using (var client = new SshClient(host, user, pass)) {
client.Connect();
client.CreateCommand("export ORACLE_HOME=/opt/oracle/product/client/11.2.0").Execute();
client.CreateCommand("export TWO_TASK=SSID").Execute();
client.CreateCommand("$ORACLE_HOME/bin/sqlplus").Execute());
...
client.Disconnect();
}
Original source code found at SSH.NET example
ok folks i have seen alot of questions about this but none that i can use or understand
What i am attempting to do is connect to putty from asp.net c# and then run a command to get the status
i will then use the results to draw a report every 3 seconds and display it on my web page
this is the first time a have attempted this so i am rather ignorant
private void connect_putty()
{
Process sh = new Process();
sh.StartInfo.FileName = "Putty.exe";
sh.StartInfo.UseShellExecute = false;
sh.StartInfo.CreateNoWindow = false;
sh.StartInfo.Arguments = "";
}
what i presently have which to be honest is pathetic any help will be appreciated
Thanks in advance
I would suggest using Tamir.SSH.
This will allow you to do everything from C#.
Also, I wrote some code once, it may help you.
https://github.com/daneb/Push2Linux/blob/master/Form1.cs
Sample:
SshShell ssh; // create our shell
ssh = new SshShell(aHost.host, aHost.username, aHost.password);
// Command Output
string commandoutput = string.Empty;
// Remove Terminal Emulation Characters
ssh.RemoveTerminalEmulationCharacters = true;
// Connect to the remote server
ssh.Connect();
//Specify the character that denotes the end of response
commandoutput = ssh.Expect(promptRegex);
PuTTY includes all the terminal emulation (hence the name), so assuming you mean 'connect via ssh', instead of the putty app specifically, then SSH.NET and SharpSSH are 2 good choices.
See this related question: C# send a simple SSH command
I need to open specific port for my application.
I have tried using INetFwAuthorizedApplication rule per application for all ports.
fwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(app)
Alternatively open one port for all appllications using INetFwOpenPort.
firewallManager.LocalPolicy.CurrentProfile.GloballyOpenPorts.Add(port)
Is there any way to programmatically open only single port per application programmatically?
I can do it manually through firewall settings.
There's a question about blocking connections with an answer with instructions for creating firewall rules in C#. You should be able to adapt this for any kind of firewall rule I imagine.
https://stackoverflow.com/a/1243026/12744
The following code creates a firewall rule that blocks any outgoing
connections on all of your network adapters:
using NetFwTypeLib; // Located in FirewallAPI.dll
...
INetFwRule firewallRule = (INetFwRule)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FWRule"));
firewallRule.Action = NET_FW_ACTION_.NET_FW_ACTION_BLOCK;
firewallRule.Description = "Used to block all internet access.";
firewallRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT;
firewallRule.Enabled = true;
firewallRule.InterfaceTypes = "All";
firewallRule.Name = "Block Internet";
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
firewallPolicy.Rules.Add(firewallRule);
You could also just use PowerShell.
using System.Management.Automation;
...
private void OpenPort(int port)
{
var powershell = PowerShell.Create();
var psCommand = $"New-NetFirewallRule -DisplayName \"<rule description>\" -Direction Inbound -LocalPort {port} -Protocol TCP -Action Allow";
powershell.Commands.AddScript(psCommand);
powershell.Invoke();
}