SFTP is a file transfer protocol that runs over an SSH protocol session.
The architecture of Rebex SFTP API reflects this - the Sftp
object runs on top of SshSession
object.
Running remote commands #
Remote command execution is a very useful feature provided by Sftp
object's SSH core.
To run a command at the server, use Sftp
object's Session
property:
// open an SSH session channel over a connected SFTP client
SshChannel channel = sftp.Session.OpenSession();
// execute the 'uname' command to get OS info
channel.RequestExec("uname -a");
// process the command response
var response = new StringBuilder();
var buffer = new byte[4096];
while (true)
{
int n = channel.Receive(buffer, 0, buffer.Length);
if (n == 0)
{
channel.Close();
break;
}
response.Append(Encoding.Default.GetString(buffer, 0, n));
}
Console.WriteLine("OS info: {0}", response);
' open an SSH session channel over a connected SFTP client
Dim channel As SshChannel = sftp.Session.OpenSession()
' execute the 'uname' command to get OS info
channel.RequestExec("uname -a")
' process the command response
Dim response = New StringBuilder()
Dim buffer(0 To 4095) As Byte
While True
Dim n = channel.Receive(buffer, 0, buffer.Length)
If n = 0 Then
channel.Close()
Exit While
End If
response.Append(Encoding.Default.GetString(buffer, 0, n))
End While
Console.WriteLine("OS info: {0}", response)
The code above is quite complicated. Fortunately, Rebex Terminal Emulation component not only makes it much
easier, but adds terminal emulation support as well.
Tip: Rebex SFTP and Rebex Terminal Emulation components can be purchased together as
Rebex SSH Pack bundle.
SSH session sharing #
Session sharing is another useful feature of the underlying SSH protocol. It's possible
to share a single SSH connection between several instances of Sftp
or Scp
objects.
When using Rebex SFTP with Rebex Terminal Emulation component,
you can even transfer files and run SSH shell sessions over a single connection.
To create a shared session, connect and authenticate an SshSession
object.
Then, instead of calling Connect
and Login
for each Sftp
or Scp
object,
use Bind
to attach it to the shared SshSession
.
The same SshSession
object can be used to execute commands at the server as well
// establish the shared SSH connection
var session = new Rebex.Net.SshSession();
session.Connect(hostname);
// check session.Fingerprint here
// authenticate
session.Authenticate(username, password);
// bind an SFTP client to the SSH session
Sftp sftp = new Sftp();
sftp.Bind(session);
// bind an SCP client to the SSH session
Scp scp = new Scp();
scp.Bind(session);
' establish the shared SSH session
Dim session = New Rebex.Net.SshSession()
session.Connect(hostname)
' check session.Fingerprint here
' authenticate
session.Authenticate(username, password)
' bind an SFTP client to the SSH session
Dim sftp = New Sftp()
sftp.Bind(session)
' bind an SCP client to the SSH session
Dim scp = New Scp()
scp.Bind(session)
Changing password #
Some SSH servers make it possible to change user's password programmatically. This feature is accessible through SshSession
object's ChangePassword
method.
Please note that password can only be changed before the authentication has begun.
// connect to an SSH server but don't log in
var session = new SshSession();
session.Connect(hostname, port);
// try changing the password
SshPasswordChangeResult result
= session.ChangePassword(username, password, newPassword);
// check the result
switch (result)
{
case SshPasswordChangeResult.Success:
// password changed;
// now you are logged on using the new password
break;
case SshPasswordChangeResult.ChangedButNotAuthenticated:
// password changed;
// you should authenticate explicitly
session.Authenticate(username, newPassword);
break;
case SshPasswordChangeResult.Failure:
// password not changed
throw new Exception("Password change failed.");
}
' connect to an SFTP server but don't log in
Dim session As New SshSession
session.Connect(hostname, port)
' try changing the password
Dim result = session.ChangePassword(username, password, newPassword)
' check the result
Select Case result
Case SshPasswordChangeResult.Success
' password changed
' now you are logged on using the new password
Case SshPasswordChangeResult.ChangedButNotAuthenticated
' password changed
' you should authenticate explicitly
sftp.Session.Authenticate(username, newPassword)
Case SshPasswordChangeResult.Failure
' password not changed
Throw New Exception("Password change failed.")
End Select
Keep-alive packet (pinging SSH server) #
Some firewall/router devices have a habit of dropping connections that have been inactive for a certain amount of time (such as 30 minutes).
To prevent this, the client can send a special ignore packet periodically to keep the connection alive.
To send such packet, use SshSession.KeepAlive
method. For a sample code to send the packet periodically,
check out this forum post.
Tunneling TCP protocols through SSH #
SSH can be used as a transport layer for various TCP communication protocols such as FTP, HTTP, SCP, SMTP, IMAP, POP3 or Telnet. Most Rebex communication components
support tunneling through SSH. In other words, it's possible to use an SSH server as a proxy server.
// establish the shared SSH connection
var session = new SshSession();
session.Connect(hostname);
session.Authenticate(username, password);
// use SSH session as proxy to establish FTP connection
var ftp = new Ftp();
ftp.SetSocketFactory(session.ToSocketFactory());
ftp.Connect(sftpHostname);
ftp.Login(sftpUsername, sftpPassword);
// use Ftp object to upload or download files, etc.
// use SSH session as proxy to establish IMAP connection
var imap = new Imap();
imap.SetSocketFactory(session.ToSocketFactory());
imap.Connect(imapHostname);
imap.Login(imapUsername, imapPassword);
// use Imap object to download mail messages, etc.
// use any Rebex component the same way
// (Ssh, Sftp, Ftp, Scp, Smtp, Imap, Pop3, Telnet, WebClient objects)
' establish the shared SSH connection
Dim session = New Rebex.Net.SshSession()
session.Connect(hostname)
session.Authenticate(username, password)
' use SSH session as proxy to establish FTP connection
Dim ftp = New Ftp()
ftp.SetSocketFactory(session.ToSocketFactory())
ftp.Connect(sftpHostname)
ftp.Login(sftpUsername, sftpPassword)
' use Ftp object to upload or download files ...
' use SSH session as proxy to establish IMAP connection
Dim imap = New Imap()
imap.SetSocketFactory(session.ToSocketFactory())
imap.Connect(imapHostname)
imap.Login(imapUsername, imapPassword)
' use Imap object to download mails ...
' use any Rebex component by the same way
' (Ssh, Sftp, Ftp, Scp, Smtp, Imap, Pop3, Telnet objects)
Key re-exchange #
SSH recommends changing encryption/decryption keys after each gigabyte of transmitted data or after each hour of connection time (whichever comes sooner).
To achieve this, the client or server can initiate a key re-exchange process. This involves a public key operation that requires
a fair amount of processing power; it is not initiated by Rebex SFTP automatically. To start a key re-exchange, simply call SshSession.Negotiate
method.
Usually, however, it's the server that initiates the re-exchange. Rebex SFTP handles it transparently and there is no need to explicitly enable this feature.
SSH ciphers #
Rebex SFTP's SSH core supports a number of security algorithms. Use Sftp.Settings.SshParameters
property to specify all kinds of SSH ciphers:
Key Exchange Ciphers
Use SshParameters.KeyExchangeAlgorithms
property to enable/disable whole categories of key exchange ciphers.
If you need more control over key exchange ciphers, use SshParameters.SetKeyExchangeAlgorithms(...)
method to specify supported ciphers in order of preference.
The following table lists supported key exchange ciphers:
Cipher ID |
Key length |
Description |
Note |
diffie-hellman-group-exchange-sha256 |
Negotiated |
Diffie Hellman with group exchange and SHA-256 hash |
Available on all* platforms. |
diffie-hellman-group16-sha512 |
4096 bits |
Diffie Hellman with Oakley Group 16 and SHA-512 hash |
Available on all* platforms. |
diffie-hellman-group15-sha512 |
3072 bits |
Diffie Hellman with Oakley Group 15 and SHA-512 hash |
Available on all* platforms. |
diffie-hellman-group14-sha256 |
2048 bits |
Diffie Hellman with Oakley Group 14 and SHA-256 hash |
Available on all* platforms. |
diffie-hellman-group-exchange-sha1 |
Negotiated |
Diffie Hellman with group exchange and SHA-1 hash |
Available on all* platforms. |
diffie-hellman-group14-sha1 |
2048 bits |
Diffie Hellman with Oakley Group 14 and SHA-1 hash |
Available on all* platforms. |
diffie-hellman-group1-sha1 |
1024 bits |
Diffie Hellman with Oakley Group 2 and SHA-1 hash |
Available on all platforms. Insecure. Disabled by default. |
ecdh-sha2-nistp256 |
256 bits |
Elliptic Curve Diffie Hellman with NIST P-256 curve and SHA-256 hash |
Available on Windows**. External plugin needed for other platforms. |
ecdh-sha2-nistp384 |
384 bits |
Elliptic Curve Diffie Hellman with NIST P-384 curve and SHA-384 hash |
Available on Windows**. External plugin needed for other platforms. |
ecdh-sha2-nistp521 |
521 bits |
Elliptic Curve Diffie Hellman with NIST P-521 curve and SHA-512 hash |
Available on Windows**. External plugin needed for other platforms. |
curve25519-sha256@libssh.org |
256 bits |
Elliptic Curve Diffie-Hellman on Curve25519 with SHA-256 hash |
Plugin required. |
Host Key Algorithms
Use SshParameters.HostKeyAlgorithms
property to enable/disable whole categories of key exchange ciphers.
If you need more control over key exchange ciphers, use SshParameters.SetHostKeyAlgorithms(...)
method to specify supported ciphers in order of preference.
The following table lists supported key exchange ciphers:
Cipher ID |
Description |
Note |
ssh-dss |
NIST Digital Signature Algorithm (DSA) with SHA-1 hash |
Available on all platforms. |
ssh-rsa |
RSA with SHA-1 hash |
Available on all platforms. |
ssh-rsa-sha256@ssh.com |
RSA with SHA-256 hash |
Available on all platforms. |
rsa-sha2-256 |
RSA with SHA-256 hash |
Available on all platforms. |
rsa-sha2-512 |
RSA with SHA-512 hash |
Available on all platforms. |
x509v3-sign-rsa-sha256@ssh.com |
X509 certificate with RSA and SHA-256 hash |
Available on all platforms. |
x509v3-sign-rsa |
X509 certificate with RSA and SHA-1 hash |
Available on all platforms. |
x509v3-sign-dss |
X509 certificate with DSA and SHA-1 hash |
Available on all platforms. |
ecdsa-sha2-nistp256 |
Elliptic Curve Digital Signature Algorithm (ECDSA) on NIST P-256 curve with SHA-256 hash |
Available on Windows**. External plugin needed for other platforms. |
ecdsa-sha2-nistp384 |
Elliptic Curve Digital Signature Algorithm (ECDSA) on NIST P-384 curve with SHA-384 hash |
Available on Windows**. External plugin needed for other platforms. |
ecdsa-sha2-nistp521 |
Elliptic Curve Digital Signature Algorithm (ECDSA) on NIST P-521 curve with SHA-512 hash |
Available on Windows**. External plugin needed for other platforms. |
ssh-ed25519 |
Ed25519, an Edwards-curve Digital Signature Algorithm (EdDSA) |
Plugin required. |
Encryption Ciphers
Use SshParameters.EncryptionAlgorithms
and SshParameters.EncryptionModes
properties to enable/disable whole categories of encryption ciphers.
If you need more control over encryption ciphers, use SshParameters.SetEncryptionAlgorithms(...)
method to specify supported ciphers in order of preference.
The following table lists supported encryption ciphers:
Cipher ID |
Description |
Note |
aes256-gcm@openssh.com |
AES in GCM mode with 256-bit key |
Client-side only for now. |
aes128-gcm@openssh.com |
AES in GCM mode with 128-bit key |
Client-side only for now. |
aes256-ctr |
AES in CTR mode with 256-bit key |
|
aes192-ctr |
AES in CTR mode with 192-bit key |
|
aes128-ctr |
AES in CTR mode with 128-bit key |
|
aes256-cbc |
AES in CBC mode with 256-bit key |
|
aes192-cbc |
AES in CBC mode with 192-bit key |
|
aes128-cbc |
AES in CBC mode with 128-bit key |
|
3des-ctr |
TripleDES in CTR mode |
|
3des-cbc |
TripleDES in CBC mode |
|
twofish256-ctr |
Twofish in CTR mode with 256-bit key |
|
twofish192-ctr |
Twofish in CTR mode with 192-bit key |
|
twofish128-ctr |
Twofish in CTR mode with 128-bit key |
|
twofish256-cbc |
Twofish in CBC mode with 256-bit key |
|
twofish192-cbc |
Twofish in CBC mode with 192-bit key |
|
twofish128-cbc |
Twofish in CBC mode with 128-bit key |
|
twofish-cbc |
Twofish in CBC mode with 256-bit key |
Disabled by default. |
blowfish-ctr |
Twofish in CTR mode with 256-bit key |
Disabled by default. |
blowfish-cbc |
Blowfish in CBC mode with 128-bit key |
Disabled by default. |
arcfour256 |
ArcFour (RC4) stream cipher (with discard step) with 256-bit key |
Disabled by default. |
arcfour128 |
ArcFour (RC4) stream cipher (with discard step) with 128-bit key |
Disabled by default. |
arcfour |
ArcFour (RC4) stream cipher with 128-bit key |
Disabled by default. |
MAC Ciphers
Use SshParameters.MacAlgorithms
property to enable/disable whole categories of message authentication code (MAC) ciphers.
If you need more control over MAC ciphers, use SshParameters.SetMacAlgorithms(...)
method to specify supported ciphers in order of preference.
The following table lists supported MAC ciphers:
Cipher ID |
Description |
Note |
hmac-sha2-256-etm@openssh.com |
SHA-256 (ETM mode) |
Client-side only for now. |
hmac-sha2-256 |
SHA-256 |
|
hmac-sha2-512-etm@openssh.com |
SHA-512 (ETM mode) |
Client-side only for now. |
hmac-sha2-512 |
SHA-512 |
|
hmac-sha1 |
SHA-1 |
|
hmac-md5 |
MD5 |
Disabled by default. |
hmac-sha1-96 |
SHA-1 (trimmed to 96 bits) |
Disabled by default. |
hmac-md5-96 |
MD5 (trimmed to 96 bits) |
Disabled by default. |
* Might be very slow on legacy Windows CE platforms
** Windows Vista and higher, or Windows Embedded Compact 2013
Server ciphers information #
To retrieve lists of SSH ciphers supported by your SFTP/SSH server, connect to it and inspect the Sftp.SshSession.ServerInfo
property:
var sftp = new Sftp();
sftp.Connect("test.rebex.net");
SshServerInfo serverInfo = sftp.Session.ServerInfo;
Console.WriteLine("Key exchange algorithms: " + string.Join(", ", serverInfo.KeyExchangeAlgorithms));
Console.WriteLine("Host key algorithms: " + string.Join(", ", serverInfo.ServerHostKeyAlgorithms));
Console.WriteLine("MAC algorithms (server -> client): " + string.Join(", ", serverInfo.MacAlgorithmsServerToClient));
Console.WriteLine("MAC algorithms (client -> server): " + string.Join(", ", serverInfo.MacAlgorithmsClientToServer));
Console.WriteLine("Encryption algorithms (server -> client): " + string.Join(", ", serverInfo.EncryptionAlgorithmsServerToClient));
Console.WriteLine("Encryption algorithms (client -> server): " + string.Join(", ", serverInfo.EncryptionAlgorithmsClientToServer));
Console.WriteLine("Compression algorithms (server -> client): " + string.Join(", ", serverInfo.CompressionAlgorithmsServerToClient));
Console.WriteLine("Compression algorithms (client -> server): " + string.Join(", ", serverInfo.CompressionAlgorithmsClientToServer));
Dim sftp As New Sftp()
sftp.Connect("test.rebex.net")
Dim serverInfo As SshServerInfo = sftp.Session.ServerInfo
Console.WriteLine("Key exchange algorithms: " + String.Join(", ", serverInfo.KeyExchangeAlgorithms))
Console.WriteLine("Host key algorithms: " + String.Join(", ", serverInfo.ServerHostKeyAlgorithms))
Console.WriteLine("MAC algorithms (server -> client): " + String.Join(", ", serverInfo.MacAlgorithmsServerToClient))
Console.WriteLine("MAC algorithms (client -> server): " + String.Join(", ", serverInfo.MacAlgorithmsClientToServer))
Console.WriteLine("Encryption algorithms (server -> client): " + String.Join(", ", serverInfo.EncryptionAlgorithmsServerToClient))
Console.WriteLine("Encryption algorithms (client -> server): " + String.Join(", ", serverInfo.EncryptionAlgorithmsClientToServer))
Console.WriteLine("Compression algorithms (server -> client): " + String.Join(", ", serverInfo.CompressionAlgorithmsServerToClient))
Console.WriteLine("Compression algorithms (client -> server): " + String.Join(", ", serverInfo.CompressionAlgorithmsClientToServer))