How to Enable SSH Shell Access While Disabling SFTP for Secure Console App Deployment


1 views

When deploying console applications through SSH, we often face a security paradox: users need shell access to launch the application, but we must prevent unauthorized file system access via SFTP. This becomes critical when your application manages its own data access controls.

SSH provides multiple channel types:


1. shell (for interactive sessions)
2. exec (for single commands) 
3. subsystem (for SFTP/SCP)
4. direct-tcpip (for port forwarding)

The solution lies in selectively disabling the SFTP subsystem while maintaining shell access.

Method 1: SSH Server Configuration

Edit your /etc/ssh/sshd_config:


# Enable shell access
AllowTcpForwarding no
X11Forwarding no
PermitTTY yes

# Disable SFTP explicitly
Subsystem sftp /bin/false
# Or alternatively:
#Subsystem sftp internal-sftp -u 0007

Method 2: Force Command Execution

In sshd_config or user's authorized_keys:


Match User appuser
    ForceCommand /path/to/your/console_app
    PermitTTY yes
    X11Forwarding no
    AllowTcpForwarding no

For more granular control, consider a custom shell wrapper:


#!/bin/bash
if [[ $SSH_ORIGINAL_COMMAND ]]; then
    # Handle direct command execution
    exec /path/to/console_app --cmd "$SSH_ORIGINAL_COMMAND"
else
    # Handle interactive session
    /path/to/console_app --interactive
    exit  # Important: terminate session after app exits
fi

After configuration, test with:


# Test shell access
ssh user@host

# Test SFTP access (should fail)
sftp user@host
  • Set proper umask (e.g., 0027) for your application
  • Consider using chroot for additional isolation
  • Implement proper logging of all access attempts

For complex scenarios, consider rssh or custom restricted shells:


# Install rssh on Debian/Ubuntu
sudo apt install rssh

# Configure in /etc/rssh.conf
allowscp
allowsftp
allowcvs

When building console applications with restricted access requirements, we often encounter a specific security paradox: Users need SSH shell access to launch the application (which immediately executes and terminates the session), but must be prevented from establishing SFTP connections that could expose restricted directories. This creates a legitimate need for SSH-SFTP separation that goes against typical security recommendations.

OpenSSH handles SFTP through its internal-sftp subsystem. The key realization is that shell access and SFTP are separate capabilities controlled by different configuration mechanisms:

# Standard SSH server components
sshd → shell (/bin/bash)
     → sftp (/usr/lib/openssh/sftp-server)

In your /etc/ssh/sshd_config, implement these changes:

# 1. Disable SFTP subsystem completely
Subsystem sftp /bin/false

# 2. Force command execution for specific users
Match User restricted_user
    ForceCommand /path/to/your_app
    PermitTTY no
    X11Forwarding no
    AllowTcpForwarding no
    PermitTunnel no
    GatewayPorts no

For finer control, implement chrooted environments:

# In sshd_config
Match Group appusers
    ChrootDirectory /var/restricted/%u
    ForceCommand /opt/app/launcher
    AllowAgentForwarding no
    PermitTunnel no

Then set up the directory structure:

sudo mkdir -p /var/restricted/username/dev/null
sudo mknod /var/restricted/username/dev/null c 1 3
sudo chown root:root /var/restricted/username
sudo chmod 755 /var/restricted/username

Create a restricted shell that immediately launches your application:

#!/bin/sh
# /bin/restricted_shell
/path/to/your_app
exit 0

Then assign this shell in /etc/passwd:

appuser:x:1001:1001::/home/appuser:/bin/restricted_shell

Test with these commands:

# Verify shell access works
ssh appuser@server

# Verify SFTP is blocked
sftp appuser@server
# Should return "Connection closed" or similar

Additional hardening measures:

  • Set PasswordAuthentication no and use SSH keys exclusively
  • Implement fail2ban for brute force protection
  • Regularly audit user sessions with last and journalctl -u sshd

If users report connection problems:

  1. Check /var/log/auth.log for SSH errors
  2. Verify permissions on chroot directories (must be owned by root)
  3. Confirm SELinux/AppArmor isn't blocking operations