Rebex File Server

SFTP, SCP and SSH server library for .NET

Download 30-day free trial Buy from $349
More .NET libraries

Back to feature list...

Server management

SSH module 

Rebex File Server is built around an SSH module and supports protocols that run over an SSH channel. This currently includes SFTP, SCP (or rather a simple virtual shell) and Port forwarding (direct TCP/IP tunneling).

However, it's easily possible to disable filesystem access and use Rebex File Server simply to provide access to an SSH shell that implements one or more custom commands.

Binding to endpoints 

An SFTP/SCP/SSH server needs to listen on an IP address and port (an endpoint) in order to be usable and accept incoming connections. To bind one of the available server modules or subsystems to an endpoint, call Bind on an instance of FileServer:

// bind SFTP and virtual shell subsystems to their default port (22)
server.Bind(FileServerProtocol.Sftp);
server.Bind(FileServerProtocol.Shell);

// bind SFTP subsystem to port 22
server.Bind(22, FileServerProtocol.Sftp);

// bind SFTP subsystem to port 3022 of the IPv4 loopback interface (127.0.0.1)
server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3022), FileServerProtocol.Sftp);
' var server = new FileServer();

' bind SFTP and virtual shell subsystems to their default port (22)
server.Bind(FileServerProtocol.Sftp)
server.Bind(FileServerProtocol.Shell)

' bind SFTP subsystem to port 22
server.Bind(22, FileServerProtocol.Sftp)

' bind SFTP subsystem to port 3022 of the IPv4 loopback interface (127.0.0.1)
server.Bind(New IPEndPoint(IPAddress.Parse("127.0.0.1"), 3022), FileServerProtocol.Sftp)

To remove one or more bindings, call Unbind:

// unbind all subsystems from port 22
server.Unbind(22);

// unbind all subsystems
server.Unbind();
' unbind all subsystems from port 22
server.Unbind(22)

' unbind all subsystems
server.Unbind()

Of course, you can enumerate the list of current bindings easily:

// display a list of bindings
foreach (var binding in server.Bindings)
{
    Console.WriteLine("'{0}' bound to {1}", binding.Module.Name, binding.EndPoint);
}
' display a list of bindings
For Each binding In server.Bindings
    Console.WriteLine("'{0}' bound to {1}", binding.[Module].Name, binding.EndPoint)
Next

Server private keys 

Before you start a FileServer, you need to specify the private keys for the server to use to prove its identity to its clients. Rebex File Server supports RSA and DSA keys and you assign both (and let the client decide which one to use).

// load an RSA private key from an encrypted file
var rsaKey = new SshPrivateKey("server-key-rsa.ppk", "password");

// load a DSA private key from an encrypted file
var dsaKey = new SshPrivateKey("server-key-dsa.ppk", "password");

// assign the private keys to the server
server.Keys.Add(rsaKey);
server.Keys.Add(dsaKey);
' load an RSA private key from an encrypted file
Dim rsaKey = New SshPrivateKey("server-key-rsa.ppk", "password")

' load a DSA private key from an encrypted file
Dim dsaKey = New SshPrivateKey("server-key-dsa.ppk", "password")

' assign the private keys to the server
server.Keys.Add(rsaKey)
server.Keys.Add(dsaKey)

Tip: For more information about private keys and how to generate your own, see SSH private keys.

Starting and stopping the server 

Once an instance of FileServer is bound to endpoints and suitable server keys are assigned, you can Start the server. Once started, the server will start accepting and handling connections in the background - until you Stop it:

// start the server
server.Start();

// stop the server
server.Stop();
' start the server
server.Start()

' stop the server
server.Stop()

Note: Before starting the server, don't forget to set up some virtual user accounts first.

Accepting or rejecting connections 

By default, FileServer accepts all incoming connections and lets them proceed to the algorithm negotiation, key exchange and authentication phases. However, Connecting event makes it possible to change this behavior - for example to limit the range of client IP address that are allowed to connect to the server.

// handler for Connected event
server.Connecting += (sender, e) =>
{
    // display the client's IP address
    Console.WriteLine("Connecting: {0}", e.ClientAddress);

    // only accept sessions from clients within 192.168.1.* network
    if (e.ClientAddress.ToString().StartsWith("192.168.1."))
        e.Accept = true;
    else
        e.Accept = false;
};
' handler for Connected event
AddHandler server.Connecting,
    Sub(sender, e)
        ' display the client's IP address
        Console.WriteLine("Connecting: {0}", e.ClientAddress)

        ' only accept sessions from clients within 192.168.1.* network
        If e.ClientAddress.ToString().StartsWith("192.168.1.") Then
            e.Accept = True
        Else
            e.Accept = False
        End If

    End Sub

Note: There is also a corresponding Disconnected event that is raised when a connection is closed.

Managing sessions 

In many cases, a file server will run unattended in the background once started. However, sometimes it's useful to see what is going on. FileServer provides a list of currently active sessions with lot of additional information. You can list them, close them, or even send a message to active shells.

// display a list of currently active sessions
foreach (var session in server.Sessions)
{
    Console.WriteLine("{0} {1} {2} {3}", session.ClientEndPoint, session.State, session.User, session.Duration);
}

// close all sessions of a user authenticated as "johnd"
foreach (var session in server.Sessions.Where(s => s.UserName == "johnd"))
{
    session.Close();
}

// send a message to all shell sessions
foreach (var session in server.Sessions)
{
    session.SendMessage("Hello there!");
}
' display a list of currently active sessions
For Each session In server.Sessions
    Console.WriteLine("{0} {1} {2} {3}", session.ClientEndPoint, session.State, session.User, session.Duration)
Next

' close all sessions of a user authenticated as "johnd"
For Each session In server.Sessions.Where(Function(s) s.UserName = "johnd")
    session.Close()
Next

' send a message to all shell sessions
For Each session In server.Sessions
    session.SendMessage("Hello there!")
Next

Tip: Too see what the server is up to, just create a log.

Managing users 

Rebex File Server includes a simple built-in non-persistent user database. If it's not sufficient in your scenario, it's simple to implement a custom authentication provider for your own user database.

Server settings 

Rebex File Server offers a wide range of settings and options that are accessible via FileServer object's Settings property:

// specify allowed authentication methods
server.Settings.AllowedAuthenticationMethods = AuthenticationMethods.Password;

// set a banner to display to clients before authentication
server.Settings.Banner = "This is a private server.";

// limit number of failed authentication attempts
server.Settings.MaxAuthenticationAttempts = 5;

// set welcome message for SCP shell
server.Settings.ShellWelcomeMessage = "Welcome to virtual shell!";

// only allow AES and Twofish ciphers in CTR mode
server.Settings.SshParameters.EncryptionAlgorithms = SshEncryptionAlgorithm.AES | SshEncryptionAlgorithm.Twofish;
server.Settings.SshParameters.EncryptionModes = SshEncryptionMode.CTR;
' specify allowed authentication methods
server.Settings.AllowedAuthenticationMethods = AuthenticationMethods.Password

' set a banner to display to clients before authentication
server.Settings.Banner = "This is a private server."

' limit number of failed authentication attempts
server.Settings.MaxAuthenticationAttempts = 5

' set welcome message for SCP shell
server.Settings.ShellWelcomeMessage = "Welcome to virtual shell!"

' only allow AES and Twofish ciphers in CTR mode
server.Settings.SshParameters.EncryptionAlgorithms = SshEncryptionAlgorithm.AES Or SshEncryptionAlgorithm.Twofish
server.Settings.SshParameters.EncryptionModes = SshEncryptionMode.CTR

Back to feature list...