How to Disable SCP File Transfers While Preserving SSH Shell Access on Linux/Solaris Servers


2 views

Many system administrators need to restrict file transfers via SCP/SFTP while maintaining regular SSH shell access for users. This security requirement often arises in regulated environments where data exfiltration needs monitoring.

The most effective approach modifies the SSH server configuration to disable the SCP subsystem:

# /etc/ssh/sshd_config
Subsystem sftp /usr/lib/openssh/sftp-server  # Comment this out
#Subsystem scp /usr/libexec/openssh/scp      # Explicitly disable if exists

This prevents scp from initiating transfers while preserving normal shell access. After modifying, restart sshd:

sudo systemctl restart sshd   # systemd systems
sudo svcadm restart ssh       # Solaris SMF

For finer control, create a wrapper script that filters scp commands:

#!/bin/bash
# /usr/local/bin/scp_wrapper
if [[ "$SSH_ORIGINAL_COMMAND" =~ scp ]]; then
    logger -p authpriv.warn "SCP attempt blocked: $SSH_ORIGINAL_COMMAND"
    echo "SCP file transfers are disabled on this system" >&2
    exit 1
fi
exec $SHELL

Then configure sshd to use this wrapper:

Match Group restricted_users
    ForceCommand /usr/local/bin/scp_wrapper

To monitor scp attempts even when blocking them, implement rsyslog filtering:

# /etc/rsyslog.d/30-scpmon.conf
if $programname == 'sshd' and ($msg contains 'scp' or $msg contains 'sftp') then {
    action(type="omfile" file="/var/log/scp_attempts.log")
    stop
}

Sample log entry format:

Aug 15 10:23:45 server1 sshd[12345]: scp attempt by user1 from 192.168.1.100: scp -r /data

After implementation, verify with:

# Should fail with "command not found" or custom error
scp testfile user@server:/tmp

# Should succeed normally
ssh user@server "ls -l"
  • This doesn't prevent users from piping files through ssh commands
  • Some legacy systems may require patching for proper scp subsystem removal
  • Consider implementing additional controls like two-factor authentication

SCP (Secure Copy Protocol) and SSH share the same underlying transport mechanism, which makes selectively disabling SCP while preserving SSH shell access a non-trivial task. OpenSSH implements SCP as a subsystem that gets invoked through the SSH protocol itself.

The most straightforward approach is to modify the sshd_config file. Add or modify these directives:

# /etc/ssh/sshd_config
Match Group !admins
    ForceCommand /bin/bash
    DenyUsers * scp
    Subsystem sftp internal-sftp -l INFO -f AUTH

This configuration:

  • Forces regular users into an interactive shell
  • Explicitly denies SCP access
  • Restricts SFTP subsystem usage

Create a custom shell wrapper that intercepts SCP commands:

#!/bin/bash
# /usr/local/bin/restricted_shell.sh

case $SSH_ORIGINAL_COMMAND in
    scp*)
        echo "SCP access prohibited" >&2
        exit 1
        ;;
    *)
        exec $SHELL -c "$SSH_ORIGINAL_COMMAND"
        ;;
esac

Then modify sshd_config:

ForceCommand /usr/local/bin/restricted_shell.sh

For comprehensive SCP logging, combine these approaches:

# Enhanced logging in sshd_config
LogLevel VERBOSE
Subsystem scp /usr/libexec/openssh/sftp-server -l INFO -f AUTH

# Custom syslog configuration
if $programname == 'sshd' and $msg contains 'scp' then {
    action(type="omfile" file="/var/log/scp_audit.log")
    stop
}

For maximum isolation, implement chroot jails:

Match User restricted_user
    ChrootDirectory /chroot/restricted
    X11Forwarding no
    AllowTcpForwarding no
    PermitTTY yes
    ForceCommand internal-sftp

Verify your settings with these commands:

# Test SSH access
ssh -v user@host

# Test SCP rejection
scp -v testfile user@host:/tmp

# Check logs
tail -f /var/log/auth.log | grep scp
  • These methods won't prevent ssh user@host "cat file" > localfile transfers
  • Consider using SELinux/AppArmor for additional protection
  • Regularly audit your sshd logs for bypass attempts