Fixing “Cannot stat sftp-server” Error When Configuring Forced Internal SFTP on CentOS 6


2 views

When implementing forced SFTP access on CentOS 6 with OpenSSH 5.3p1, many administrators encounter the misleading error:

error: subsystem: cannot stat /usr/libexec/openssh/sftp-server
subsystem request for sftp failed, subsystem not found

Despite the file existing at the specified path, the SSH daemon fails to recognize it. This typically indicates a deeper configuration issue rather than a missing binary.

The root cause often stems from two competing configurations:

# Original problematic configuration
Subsystem sftp /usr/libexec/openssh/sftp-server
Match user USERNAME
  ForceCommand internal-sftp

The conflict arises because internal-sftp doesn't use the external binary path, yet the Subsystem directive still points to it. Here's how to verify your actual sftp-server path:

# Find the correct sftp-server path
$ find / -name sftp-server 2>/dev/null
$ ls -la /usr/libexec/openssh/sftp-server

For forced SFTP to work properly, you need to modify your /etc/ssh/sshd_config as follows:

# Correct configuration for forced internal SFTP
Subsystem sftp internal-sftp

Match Group sftpusers
  ChrootDirectory /home/%u
  ForceCommand internal-sftp
  X11Forwarding no
  AllowTcpForwarding no

Key changes include:

  • Replacing the binary path with internal-sftp in Subsystem
  • Using group matching instead of individual users
  • Adding security restrictions

After making changes, always:

# Check config syntax
$ sudo sshd -t

# Restart service
$ sudo service sshd restart

# Test connection
$ sftp username@localhost

If you must use the external binary (unlikely in modern systems), ensure proper SELinux contexts:

# For systems requiring external binary
$ sudo restorecon -v /usr/libexec/openssh/sftp-server
$ sudo chmod 755 /usr/libexec/openssh/sftp-server

Then modify the Subsystem line to match your verified path.

If issues persist, check:

  • SELinux status with getenforce
  • File permissions on home directories
  • AppArmor/selinux logs in /var/log/audit/audit.log
  • SSH debug output with ssh -vvv

When attempting to restrict users to SFTP-only access on CentOS 6 with OpenSSH 5.3p1, many administrators encounter the particularly stubborn error:

error: subsystem: cannot stat /usr/libexec/openssh/sftp-server: No such file or directory
subsystem request for sftp failed, subsystem not found

The paradox occurs when the file clearly exists at the specified path but the SSH daemon fails to recognize it. Let's dissect this behavior.

The conflict stems from an incompatibility between these two configuration elements:

Subsystem sftp /usr/libexec/openssh/sftp-server
Match user USERNAME
    ForceCommand internal-sftp

Here's what's happening:

  • The Subsystem directive points to the external binary
  • ForceCommand internal-sftp tries to use the built-in implementation
  • The SSH daemon gets confused between these conflicting instructions

For modern OpenSSH versions (4.9+), the proper approach is:

# Comment out or remove the Subsystem line
# Subsystem sftp /usr/libexec/openssh/sftp-server

Match User restricted_user
    ChrootDirectory /home/%u
    ForceCommand internal-sftp
    X11Forwarding no
    AllowTcpForwarding no
    PermitTTY no

After modifying the configuration:

  1. Restart SSH: service sshd restart
  2. Test SFTP access: sftp restricted_user@localhost
  3. Verify shell access is blocked: ssh restricted_user@localhost

If you must keep the external sftp-server:

Subsystem sftp /usr/libexec/openssh/sftp-server

Match User restricted_user
    ForceCommand /usr/libexec/openssh/sftp-server
    ChrootDirectory /home/%u

Remember to set proper permissions:

chown root:root /home/restricted_user
chmod 755 /home/restricted_user

When troubleshooting:

  • Check SSH daemon logs: tail -f /var/log/secure
  • Run in debug mode: /usr/sbin/sshd -d
  • Verify file permissions: ls -la /usr/libexec/openssh/