Get IP Address of Connected Client?

+1 vote
asked Jan 10 by timwestover (130 points)

We're running a Rebex FileServer. It's working great. Clients can log in and upload / download files correctly. But for logging purposes, I need to get the IP address of the connected user when the file finished uploading or downloading. I have serverFileDownloaded and serverFileUploaded methods, but I can't figure out how to get the IP address there.

Also, in the Rebex logging, I see that we have unauthorized IPs trying to access us, attempting to brute-force login. Can I block them by IP, or do I have to do that at the firewall?

Applies to: Rebex SFTP, File Server

1 Answer

0 votes
answered Jan 11 by Lukas Pokorny (83,170 points)

IP address is not available in FileUploaded/FileDownloaded events (yet), but you can work around this by using a custom user class and a custom Authentication event that associates an IP with a per-session user object.

Try using this custom user class:

public class CustomUser : FileServerUser
{
    private readonly string _userName;
    private readonly string _password;
    private readonly string _virtualRootPath;

    public CustomUser(string userName, string password, string virtualRootPath)
        : base(userName, password, virtualRootPath)
    {
        _userName = userName;
        _password = password;
        _virtualRootPath = virtualRootPath;
    }

    private class ActiveCustomUser : CustomUser
    {
        public IPAddress Address { get; private set; }

        public ActiveCustomUser(IPAddress address, string userName, string password, string virtualRootPath)
            : base(userName, password, virtualRootPath)
        {
            Address = address;
        }
    }

    public FileServerUser ToActiveUser(IPAddress address)
    {
        return new ActiveCustomUser(address, _userName, _password, _virtualRootPath);
    }

    public static IPAddress GetAddress(FileServerUser user)
    {
        var activeUser = user as ActiveCustomUser;
        if (activeUser == null)
            return IPAddress.None;
        else
            return activeUser.Address;
    }
}

To make it work, you have to provide Authentication and FileUploaded/FileDownloaded events:

var server = new FileServer();
server.Keys.Add(...);
server.Bind(22, FileServerProtocol.Sftp);

server.Users.Add(new CustomUser("user01", "password", @"c:\temp\SftpRoot"));

server.Authentication += (sender, e) =>
{
    var user = (CustomUser)e.Users[e.UserName];

    if (user.CheckPassword(e.Password))
    {
        e.Accept(user.ToActiveUser(e.ClientAddress));
        return;
    }

    e.Reject();
};

server.FileUploaded += (sender, e) =>
{
    IPAddress address = CustomUser.GetAddress(e.User);
    ...
};

server.Start();

Rejecting access from unwanted IP addresses is possible in Connecting event:

server.Connecting += (sender, e) =>
{
    e.Accept = IsAllowed(e.ClientAddress);
};

This will still accept the incoming connection, but it will be closed immediately without performing any SSH negotiation. If you prefer rejecting the connection attempts without accepting them first, you would have to do that at the firewall.

commented Jan 11 by timwestover (130 points)
Thanks, this all worked great.
...