This is my code to connect and send a file to a remote SFTP server.
public static void SendDocument(string fileName, string host, string remoteFile, string user, string password)
{
Scp scp = new Scp();
scp.OnConnecting += new FileTansferEvent(scp_OnConnecting);
scp.OnStart += new FileTansferEvent(scp_OnProgress);
scp.OnEnd += new FileTansferEvent(scp_OnEnd);
scp.OnProgress += new FileTansferEvent(scp_OnProgress);
try
{
scp.To(fileName, host, remoteFile, user, password);
}
catch (Exception e)
{
throw e;
}
}
I can successfully connect, send and receive files using CoreFTP. Thus, the issue is not with the server. When I run the above code, the process seems to stop at the scp.To method. It just hangs indefinitely.
Anyone know what might my problem be? Maybe it has something to do with adding the key to the a SSH Cache? If so, how would I go about this?
EDIT: I inspected the packets using wireshark and discovered that my computer is not executing the Diffie-Hellman Key Exchange Init. This must be the issue.
EDIT: I ended up using the following code. Note, the StrictHostKeyChecking was turned off to make things easier.
JSch jsch = new JSch();
jsch.setKnownHosts(host);
Session session = jsch.getSession(user, host, 22);
session.setPassword(password);
System.Collections.Hashtable hashConfig = new System.Collections.Hashtable();
hashConfig.Add("StrictHostKeyChecking", "no");
session.setConfig(hashConfig);
try
{
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp c = (ChannelSftp)channel;
c.put(fileName, remoteFile);
c.exit();
}
catch (Exception e)
{
throw e;
}
Thanks.
I use Tamir.SharpSSH - latest version 1.1.1.13
This has a class SFTP. You can use this class directly to do SFTP instead of using JSch, Session class.
Quick Sample here:
127.0.0.1 - Server IP
/SFTPFolder1/SFTPFolder2 - Server Location Where I want my files to go
Sftp sftpClient = new Sftp("127.0.0.1", "myuserName", "MyPassword");
sftpClient.Connect();
sftpClient.Put(#"C:\Local\LocalFile.txt", "/SFTPFolder1/SFTPFolder2");
Let me know if you have any issues.
Without looking at your log files it is hard to tell what the issue is.
However keep in mind that SCP is not SFTP - they are completely different protocols that run over SSH. It is possible that your SFTP does not actually support SCP - not all SFTP servers do. CoreFTP may be using SFTP.
Our commercial package, edtFTPnet/PRO, might also be worth trying, if only as an alternative to try to get a different client working against your server.
Related
I've seen other threads about this error, but I am having this error randomly. Out of 30 connects, 12 got this error. Trying to understand why this is, and what possible solutions are.
using (SftpClient client = new SftpClient(sftpHost, sftpPort, sftpUser, sftpPassword))
{
client.Connect();
}
throws this exception:
Renci.SshNet.Common.SshConnectionException: Server response does not contain SSH protocol identification
This might sound trivial, but I have tried the Renci.SshNet.Async package and it worked with out any issue. The following could be a reason/s for the problem with solution or alternative solution.
Renci.SshNet.Async might have bug or issues that appears in specific environment or in specific combination. Some mentioned same problems here, no solution https://github.com/sshnet/SSH.NET/issues/377
Some has experienced same problem and mentioned a solutions, one is to retry n number of times Renci.SshNet : "server response does not contain ssh protocol identification"
The problem is not with your client but more or less with your Host. It can be many things or issues.
Finally I would try using WinSCP which is also well recognized library for .net (nuget). I have tried it my self as well and have never experienced any issues so far. I suggest you to get it and try it as alternative to your current solution, and see if it helps. If WinSCP works then point 1 is valid, if you experience same issue with WinSCP then point 3 is valid. This way we can make conclusions and narrow down to the problem.
Here examples provided by WinSCP https://winscp.net/eng/docs/library_examples.
My Test example is:
This is just playground example to see if things are running, when used in production, please modify it. Further more thanks to #MartinPrikry adding this note: If you have set SshHostKeyFingerprint correctly, then do not set GiveUpSecurityAndAcceptAnySshHostKey.
public static int WinSCPListDirectory()
{
try
{
var sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = "xxx.xxx.xxx.xxx",
UserName = "username",
Password = "password",
SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx",
GiveUpSecurityAndAcceptAnySshHostKey = true
};
using (var session = new Session())
{
session.Open(sessionOptions);
var directory = session.ListDirectory("/var/www");
foreach (RemoteFileInfo fileInfo in directory.Files)
{
Console.WriteLine(
"{0} with size {1}, permissions {2} and last modification at {3}",
fileInfo.Name, fileInfo.Length, fileInfo.FilePermissions,
fileInfo.LastWriteTime);
}
}
return 0;
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e);
return 1;
}
}
This example should return a list of directories
Related links:
https://winscp.net/eng/docs/library_session_listdirectory
OpenSource .NET library for connecting to SFTP server?
No one knows the exact cause for this behavior to be honest.
As a possible fix, Some people suggest creating a counter loop for retrying to connect, suggesting it solved their problem:
int attempts = 0;
do
{
try
{
client.Connect();
}
catch (Renci.SshNet.Common.SshConnectionException e)
{
attempts++;
}
} while (attempts < _connectiontRetryAttempts && !client.IsConnected);
Another suggestion is to add the IP address into the hosts.allow file on the server, so you could check in that direction as well.
As I said, there is no possible explanation for the behavior altogether.
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
I just setup memcached on a ubuntu system i have on my network. Didn't change any options so everything is default. I think tried to connect to the server using Enyim. It doesn't fail but when i try to retrieve the items they are always null. I'm not much of a low level won't but i've been able to discern things from wireshark before so i decided to give it a try. I'haven't been able to discern anything but i noticed the first .Store() command i sent actually sent network packets to the correct address. Every .Store() command did absolutely nothing.
Here is my app.config:
I've tried both "Binary" & "Text" Protocols and they did the same thing.
Here is my c# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Enyim.Caching;
using Enyim.Caching.Configuration;
using Enyim.Caching.Memcached;
namespace MemCacheTest
{
internal class Program
{
private static void Main(string[] args)
{
//var config = new MemcachedClientConfiguration();
//config.Servers.Add(new IPEndPoint(new IPAddress(new byte[] {10, 0, 0, 1}), 11211));
//config.Protocol = MemcachedProtocol.Binary;
var mc = new MemcachedClient();
for (var i = 0; i < 100; i++)
mc.Store(StoreMode.Set, "Hello", "World");
mc.Store(StoreMode.Set, "MyKey", "Hello World");
Console.WriteLine(mc.Get("MyKey"));
Console.WriteLine("It should have failed!!!");
Console.ReadLine();
}
}
}
Does anyone know whats going on or how i could determine what is wrong? I thought it was strange that i wasn't getting any exceptions so i set an invalid ip address in the config file. Same results.
The short answer: If your service is running check your port, it should be blocked somehow. (did you add an exception for port 11211 in Ubuntu firewall(iptables)?)
telnet 10.0.0.1 11211 If you have a telnet client on your server this will show the port is inaccessible.
Enyim doesn't throw you an error even the port is inaccessible. yes, it's strange.
To add to dasun answer. When you install memcached by default its configured to only listen on the "lo/localhost" interface. Its the only security memcache really has. Even if you try to telnet locally and do specify the lo interface for example:
telnet 10.0.0.1 11211
it will fail. To fix you have to go into the memcached.conf file and comment out
# -l 127.0.0.1
and then restart the service
I am working on an application which reads eventlogs(Application) from remote machines. I am making use of EventLog class in .net and then iterating on the Log entries but this is very slow. In some cases, some machines have 40000+ log entries and it takes hours to iterate through the entries.
what is the best way to accomplish this task? Are there any other classes in .net which are faster or in any other technology?
Man, I feel your pain. We had the exact same issue in our app.
Your solution has a branch depending on what server version you're running on and what server version your "target" machine is running on.
If you're both on Vista or Windows Server 2008, you're in luck. You should look at System.Diagnostics.Eventing.Reader.EventLogQuery and System.Diagnostics.Eventing.Reader.EventLogReader. These are new in .net 3.5.
Basically, you can build a query in XML and ship it over to run on the remote computer. Maybe you're just searching for events of a specific type, or maybe just new events from a specific point in time. The search runs on the remote machine, and then you just get back the matching events. The new classes are much faster than the old .net 2.0 way, but again, they are only supported on Vista or Windows Server 2008.
For our app when the target is NOT on Vista/Win2008, we downloaded the raw .evt file from the remote system, and then parsed the file using its binary format. There are several sources of data about the event log format for .evt files (pre-Vista), including link text and an article I recall on codeproject.com that had some c# code.
Vista and Windows Server 2008 machines use a new .evtx format that is a new format, so you can't use the same binary parsing approach across all versions. But the new EventLogQuery and EventLogReader classes are so fast that you won't have to. It's now perfectly speedy to just use the built-in classes.
Event Log Reader is horribly slow... too slow. WTF Microsoft?
Use LogParser 2.2 - Search for C# and LogParser on the Internet (or you can use the log parser commands from the command line). I don't want to duplicate the work already contributed by others.
I pull the log from the remote system by having the log exported as an EVTX file. I then copy the file from the remote system. This process is really quick - even with a network that spans the planet (I had issues with having the log exported to a network resource). Once you have it local, you can do your searches and processing.
There are multiple reasons for having the EVTX - I won't get into the reasons why we do this.
The following is a working example of the code to save a copy of the log as an EVTX:
(Notes: "device" is the network host name or IP. "LogName" is the name of the log desired: "System", "Security", or "Application". outputPathOnRemoteSystem is the path on the remote computer, such as "c:\temp\%hostname%.%LogName%.%YYYYMMDD_HH.MM%.evtx".)
static public bool DumpLog(string device, string LogName, string outputPathOnRemoteSystem, out string errMessage)
{
bool wasExported = false;
string errorMessage = "";
try
{
System.Diagnostics.Eventing.Reader.EventLogSession els = new System.Diagnostics.Eventing.Reader.EventLogSession(device);
els.ExportLogAndMessages(LogName, PathType.LogName, "*", outputPathOnRemoteSystem);
wasExported = true;
}
catch (UnauthorizedAccessException e)
{
errorMessage = "Unauthorized - Access Denied: " + e.Message;
}
catch (EventLogNotFoundException e)
{
errorMessage = "Event Log Not Found: " + e.Message;
}
catch (EventLogException e)
{
errorMessage = "Export Failed: " + e.Message + ", Log: " + LogName + ", Device: " + device;
}
errMessage = errorMessage;
return wasExported;
}
A good Explanation/Example can be found on MSDN.
EventLogSession session = new EventLogSession(Environment.MachineName);
// [System/Level=2] filters out the errors
// Where "Log" is the log you want to get data from.
EventLogQuery query = new EventLogQuery("Log", PathType.LogName, "*[System/Level=2]");
EventLogReader reader = new EventLogReader(query);
for (EventRecord eventInstance = reader.ReadEvent();
null != eventInstance;
eventInstance = reader.ReadEvent())
{
// Output or save your event data here.
}
When waiting 5-20 minutes with the old code this one does it in less than 10 seconds.
Maybe WMI can help you:
WMI with C#
Have you tried using the remoting features in powershell 2.0? They allow you to execute cmdlets (like ones to read event logs) on remote machines and return the results (as objects, of course) to the calling session.
You could place a Program at those machines that save the log to file and sends it to your webapplication i think that would be alot faster as you can do the looping local but im not sure how to do it so i cant ive you any code :(
I recently did such thing via WCF callback interface however my clients interacted with the server through WCF and adding a WCF Callback was easy in my project, full code with examples is available here
Just had the same issue and want to share my solution. It makes a search through application, system and security eventlogs from 260 seconds (using EventLog) about a 100 times faster (using EventLogQuery).
And this in a way where it is possible to check if the event message contains a pattern or any other check without the requirement of FormatDescription().
My trick is to use the same mechanism as PowerShells Get-WinEvent does and then pass it through the result check.
Here is my code to find all events within last 4 days where the event message contains a filter pattern.
string[] eventLogSources = {"Application", "System", "Security"};
var messagePattern = "*Your Message Search Pattern*";
var timeStamp = DateTime.Now.AddDays(-4);
var matchingEvents = new List<EventRecord>();
foreach (var eventLogSource in eventLogSources)
{
var i = 0;
var query = string.Format("*[System[TimeCreated[#SystemTime >= '{0}']]]",
timeStamp.ToUniversalTime().ToString("o"));
var elq = new EventLogQuery(eventLogSource, PathType.LogName, query);
var elr = new EventLogReader(elq);
EventRecord entryEventRecord;
while ((entryEventRecord = elr.ReadEvent()) != null)
{
if ((entryEventRecord.Properties)
.FirstOrDefault(x => (x.Value.ToString()).Contains(messagePattern)) != null)
{
matchingEvents.Add(entryEventRecord);
i++;
}
}
}
Maybe that the remote computers could do a little bit of computing. So this way your server would only deal with relevant information. It would be a kind of cluster using the remote computer to do some light filtering and the server would the the analysis part.