1. Introduction
With the increasing security consciousness of both users and administrators, older protocols like File Transfer Protocol (FTP) and File Transfer Protocol Secure (FTPS) get dropped in favor of more robust modern replacements such as SSH File Transfer Protocol (SFTP). Since it’s based on SSH, SFTP provides many features and less exposure.
In this tutorial, we explore SFTP and ways to check the storage space status on an SFTP server. First, we delve into the relationship between SSH and SFTP. After that, we get into the SSH subsystem mechanism. Next, we check how SFTP is configured in a typical SSH environment. Finally, we go over SFTP commands and extensions.
For brevity and security reasons, we only consider the newest iteration of SSH version 2 (SSHv2) implemented by OpenSSH.
We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.2.15. It should work in most POSIX-compliant environments unless otherwise specified.
2. SSH and SFTP
In normal conditions, SSH permits the execution of any command in the remote shell as long as we authenticate properly and have authorization:
$ ssh [email protected] hostname
[email protected]'s password:
xost
In this case, we run the hostname on 192.168.6.66 after successfully logging-in as user baeldung.
This isn’t the way FTP or SFTP work. They have a limited set of commands mainly targeting file transfer. Unlike FTP, SFTP isn’t actually an entirely separate protocol. In fact, it’s more or less a restricted SSH server.
3. The SSH Subsystem Mechanism
The SSH protocol can run so-called subsystems. An SSH subsystem is an abstraction layer on top of the SSH protocol.
For example, we might want to create a custom protocol for system identification. Let’s see how we might do that.
3.1. Create Executable
To begin with, we first write a simple executable script and place it in /usr/lib/openssh/:
$ cat /usr/lib/openssh/xid.sh
#!/usr/bin/env bash
hostname
$ chmod +x /usr/lib/openssh/xid.sh
Notably, the script only contains a shebang and a call to the hostname command.
Alternatively, we can use a restricted shell call or even a custom binary. In any case, this is what the SSH server calls upon session establishment.
3.2. Set Subsystem
To configure a new system, we use /etc/ssh/sshd_config.
Let’s set xid as a Subsystem:
$ cat /etc/ssh/sshd_config
[...]
# override default of no subsystems
Subsystem xid /usr/lib/openssh/xid.sh
[...]
Thus, the xid subsystem is in place, targeting the /usr/lib/openssh/xid.sh script.
3.3. Test Subsystem
To call a subsystem, we use the -s option of the ssh client:
$ ssh [email protected] -s xid
[email protected]'s password:
xost
Importantly, the -s switch should come after the server URI.
In this case, we pass xid as the desired subsystem. Consequently, we get the same result as before: the hostname of the system.
At this point, we understand SSH subsystems and their inner workings.
4. SFTP Configuration
Notably, SFTP servers also run as a subsystem of SSH. Further, the sftp client is equivalent to an ssh client call with the -s sftp subsystem:
$ ssh [...] -s sftp
On the server side, this is facilitated via a Subsystem line in sshd_config that defines the sftp system as the /usr/lib/openssh/sftp-server binary executable:
$ cat /etc/ssh/sshd_config
[...]
# override default of no subsystems
Subsystem sftp /usr/lib/openssh/sftp-server
[...]
In fact, both the sftp and scp client commands rely on this to function properly.
5. SFTP Commands
What constitutes a part of SFTP and what’s restricted relative to pure SSH depends on the SFTP server implementation. Some are embedded in sshd, while others are separate executables such as sftp-server.
In any case, as SFTP evolves, these implementations may need updates.
5.1. Basic Commands
SFTP supports a basic set of commands as returned by help at the sftp prompt:
sftp > help
Available commands:
bye Quit sftp
cd path Change remote directory to 'path'
chgrp [-h] grp path Change group of file 'path' to 'grp'
chmod [-h] mode path Change permissions of file 'path' to 'mode'
chown [-h] own path Change owner of file 'path' to 'own'
...
symlink oldpath newpath Symlink remote file
version Show SFTP version
!command Execute 'command' in local shell
! Escape to local shell
? Synonym for help
They mainly help with file transfer, data traversal, listing, and removal.
However, some commands require separate extensions to function.
5.2. Updates and Extensions
Although SFTP specifications already exist for versions 3, 4, 5, and 6 of the protocol, OpenSSH and other SSH servers usually only support SFTP version 3 (SFTPv3) by default.
Naturally, we can replace the executable related to our Subsystem to use any SFTP implementation, but the collaboration between it and SSH might be inconsistent.
On the other hand, SSH_FXP_EXTENDED requests, as defined by SFTPv3, can facilitate running any command or code.
5.3. Proprietary Commands
Since SFTP runs on SSH servers, we might be able to execute any command via ssh.
For example, one way to check the storage of an SFTP server is by using ssh directly with the df command:
$ ssh [email protected] df
[email protected]'s password:
Filesystem 1K-blocks Used Available Use% Mounted on
udev 966610 0 966610 0% /dev
tmpfs 195660 5660 190000 4% /run
/dev/sda1 16660010 1004301 15655709 9% /
[...]
However, many SSH server configurations restrict any local sessions except for the SFTP subsystem. How a given system does this varies, but it generally involves non-login users, non-existent shells, and sshd_config modification.
Still, we might want to check the available storage as part of our SFTP usage.
5.4. Storage Checks
Although often useful for the general operation of an (S)FTP server, storage checks aren’t implemented in the first versions of SFTP.
So, **OpenSSH includes the statvfs implementation as a custom extension for storage checks called [email protected]**. As expected, its implementation comes in the form of an OpenSSH SFTP-specific df command:
sftp > df -h
Size Used Avail (root) %Capacity
16.6GB 1.1GB 15.5GB 11.5GB 91%
Still, SFTPv6 provides a storage status interface out of the box without the need for a custom statvfs implementation. This means that a few applications can directly leverage the functionality:
So, using any SFTPv6-enabled server and client combination should be sufficient for storage checks via the relevant feature.
6. Summary
In this article, we talked about the SSH File Transfer Protocol (SFTP), how it works with regard to SSH, and ways it can be extended.
In conclusion, although not all SFTP features are implemented in major SSH servers, we can use extensions for actions such as storage checks and similar.