Using Solaris and Linux servers and OpenSSH, is it possible to prevent users from copying files using "scp" while still allowing shell access with "ssh"?

I realize that 'ssh $server "cat file" ' type file accesses are much harder to prevent, but I need to see about stopping "scp" for starters.

Failing that, is there a way to reliably log all SCP access on the server side through syslog?

  • If you wanted to close ssh but not scp you could have used this: sublimation.org/scponly/wiki/index.php/Main_Page Too bad you want it the other way around :-\
    – samoz
    Commented Jun 19, 2009 at 18:36
  • I have the same question but for other reason. In my case I like to turn off the SFTPD and SCPD on the server. Reason is that we do allow file transfers but we like the users to do the transfers via our copy node. This is due to how we sepparate the load on our links. So according to this loop it is easy to turn off SFTPD, but if I understand correctly it is pretty much impossibly to turn off SCPD?
    – user133866
    Commented Aug 29, 2012 at 1:06

14 Answers 14


While you could edit your /etc/ssh/sshd_config to look something like this:

ForceCommand           /bin/sh
AllowTcpForwarding     no
PermitTunnel           no
# Subsystem sftp       /usr/lib/openssh/sftp-server
PermitUserEnvironment  no

I would instead determine what the user is likely to use it for. Because if there are only a few commands that you want them to have access to, I would instead remove the ability for them to even invoke a normal ssh shell.

AllowUsers             root
PermitRootLogin        forced-commands-only

PermitUserEnvironment  no

AllowTcpForwarding     no
PermitTunnel           no

# Subsystem sftp       /usr/lib/openssh/sftp-server
Subsystem smb-reload   /usr/bin/smbcontrol smbd reload-config
Subsystem status       /opt/local/bin/status.sh

ssh root@example -s smb-reload

If you find that you really do need to be able to run a normal shell, the most you really can hope for, is to slow them down, and make it more difficult.


As others have noted, you can't block scp (well, you could: rm /usr/bin/scp, but that doesn't really get you anywhere).

The best you can do is to change the users' shell to a restricted shell (rbash) and only then to run certain commands.

Remember, if they can read files, they can copy/paste them off the screen. Binary files? xxd/uuencode/mmencode all get around this.

I'd also suggest using process accounting to help you track activity.

  • Process accounting helps a bit, but the historical process accounting was really useless (e.g. logging only the basename of the command run). I'd like to hear about any modern successes with process accounting that is actually useful.
    – carlito
    Commented Jun 29, 2009 at 6:14
  • 1
    How about using a patched restricted shell that also logs all commands run to a pipe somewhere? A centralized .bash_history kind of idea.
    – MikeyB
    Commented Jun 29, 2009 at 13:43
  • Actually on the server side you would have to delete /usr/lib/openssh/sftp-server, but I think sshd has a built in sftp server. Commented Jul 2, 2009 at 5:04
  • @Brad: Any commands specified by the client are still run via the shell; so if sftp-server isn't in the default PATH (which it's not) changing the shell to a restricted one is enough to disable it, you don't have to delete the binary.
    – MikeyB
    Commented Jul 2, 2009 at 13:31
  • I'm not familiar with the details of Solaris but would be urprised if it is significantly different from Linux, where its possible to make /home and /tmp seperate mounts with noexec and thereby prevent running executables apart from places where you control the permissions. But yes , there are still lots of ways to get non-executable files onto the device. This is still not a complete solution though as a sophisticated attacker could still tinker with LD_LIRARY_PATH to incoproate a binary lib into an existing executable. Still, at least its not MS-Windows :)
    – symcbean
    Commented May 29, 2020 at 20:34

You gain nothing by stopping "scp" when you're still allowing literally infinite additional mechanisms of transferring files. Disallowing scp but allowing other mechanisms of copying files is a method of lying to auditors. Often auditors ask to be lied to. Usually I see auditors working with managers to make fake fixes, so that they can state something like "the scp file transfer command has been disabled, so that files can not be copied from the server using scp".

Now a reasonable logging mechanism would be nice. Maybe auditd finally works on Linux. Maybe Solaris finally added some mechanism or dtrace could be used safely. It's reasonable to want the OS to log every time a file is accessed. Of course there's no difference between "reading" and "copying". But this can satisfy an auditor and give significant security to the system. Your logs could be so noisy that the data is useless, or even that you're forced to keep a ridiculously short audit trail. (e.g. you can't log every read() - and one application that does something surprising can make logging every open() a disaster).


Depending on what SSH is needed for, you may be able to achieve this goal (for non-trivial) files by using IPTables to terminate sessions if the packet size is bigger then, say 1400 bytes. This means that interactive ssh will mostly work, but as soon as something tries to send a 1500 byte packet - like scp should for a file larger then 1499 bytes assuming a standard MTU of 1500, it will terminate the connection.

This will also prevent the "catting" attack you mention.

Unfortunately this means that you may have problems editing some files with a text editor, if the screen needs to draw more then 1400 characters, or if you need to cat a long file or do a long directory listing.

In the simplest case a command to do this might look something like

iptables -I OUTPUT -p tcp --dport 22 -m length --length 1400:0xffff -j DROP

We can make this work better by combining the packet length checks with ipt_recent, so that you allow a limited number of packets larger then 1400 bytes within a set timeframe (say 8 packets per 5 seconds)- this would allow packets up to 12k to slip through, but may give you the interactivity you will need for editing files etc. You can, of course, tweak the number of packets.

This might look something like

iptables -I OUTPUT -p tcp --dport 22 -m length --length 1400:0xffff \
         -m recent --name noscp --rdest --set 
iptables -I OUTPUT -p tcp --dport 22 -m length --length 1400:0xffff \
         -m recent --name noscp --rdest --update --seconds 5 --hitcount 8 \
         -j REJECT --reject-with tcp-reset

The rule examples above only protect against scp uploads such as scp myfile.data remote.host:~. To additionally protect against scp downloads such as scp remote.host:~/myfile.data /local/path, repeat the above rules but replace --dport with --sport.

A clueful hacker can work around these limitations by setting an MTU of less then 1400 on his machine (or force mtu or similar). Also, while you can't limit this to certain users, you can limit it by IP by modifying the iptables lines as appropriate !!

Cheers, David Go


Your best bet isn't to lock down scp, but to use a file system with ACLs to prevent read access. You could probably do something with SELinux to prevent certain applications from reading from certain files.


Blocking file transfer without removing so many system utilities as to leave the machine completely useless is impossible. You'd have to get rid of everything capable of displaying file contents to stdout, and everything capable of writing its stdin to stdout, and by the time you've removed all of those there's so little left that there's no point to allowing shell access at all.

So I'll focus on your logging alternative instead:

There's a program called "script" that's included in practically every distro, and which should be easy to install on the ones where it isn't. It's a session logger that records all input and output from a shell, optionally with timing data so it can be replayed and look just like you were watching over the user's shoulder when they did it. (95% anyway, it occasionally bobbles the output when ncurses is involved, but not very often.)

Its man page includes instructions for setting it up as the system's login shell. Make sure the logs go somewhere that the user can't just delete them (the append-only filesystem attribute (settable via chattr) can be useful for this. As can ACLs or inotify scripts)

This still doesn't prevent users from copying files out of the system, but it does let you review what was done by which users and when. It's probably not impossible to bypass, but the bypass would almost certainly end up in the logs so you'd at least know somebody was up to no good, even if they manage to hide exactly what it was.


No. scp and ssh operate on the same ports and use the same protocol. If you open an ssh session, you can even share your connection with subsequent scp calls using options like ControlMaster.

If you do not want people to copy particular files off of a machine, you should not give them any kind of shell access to the machine.

  • Yes, the obvious answer would be to lock up the system and not give out access. In reality however, my company has auditors who say that we need to prevent files from being copied off of the servers and / or log attempts despite the fact that we seriously limit ssh access and have a robust RBAC system in place.
    – Jason
    Commented Jun 19, 2009 at 18:40
  • 2
    @Jason: Then you need to log file access. Even if you disabled scp, how would you stop someone from running: ssh server 'cat /path/to/file' > copy ?
    – derobert
    Commented Jun 19, 2009 at 19:29

I believe you can uninstall openssh-clients (or equivalent) on the server.

I think scp client invokes scp on the server when copying data over so if you get rid of scp on the server, then you should be fine.

$ scp bla server:/tmp/
debug1: Sending environment.
debug1: Sending env LC_ALL = en_US.utf8
debug1: Sending env LANG = en_US.utf8
debug1: Sending env XMODIFIERS = @im=ibus
debug1: Sending env LANGUAGE = en_US.utf8
debug1: Sending command: scp -v -t /tmp/
bash: scp: command not found
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype [email protected] reply 0
lost connection

The solution given by @Tomas works great that deleting/renaming /usr/bin/scp does prevent incoming and outgoing scp file transfer. However, you must also block all other ports from server to client, and from client to server. Otherwise, your hackish users can run nc -l <PORT> to listen on one side and run nc <TARGET-IP> <PORT> to establish a TCP/IP connection and directly transfer data.

Even with this, you still also need to disable X11 forwarding, otherwise, an advanced hackish user can build an X11 app and transfer data via X11 tunnel.


There is a way to use 'scponly' as the shell to disable interactive ssh and allow scp, but I am not aware of anything existing that works in the reverse manner.

You may be able to explore hacking the scponly shell to accomplish the reverse.


This is not possible actually after a little googling.

Check out this discussion: http://www.mydatabasesupport.com/forums/unix-admin/387261-how-restrict-ssh-users-block-scp-sftp.html

  • 1
    This link is dead.
    – rox0r
    Commented Jan 19, 2017 at 20:10

For what it's worth, the commercial product CryptoAuditor claims to be able to control file transfers over SSH, by MITMing the connection and using deep-packet inspection. Obviously no solution is safe from copy+paste, uuencode/decode, FISH, etc. The nice thing is that it's transparent (aside from probable certificate errors); there is no agent software to install on either end of the SSH connection, and no portal/proxy to configure.

I haven't used the product, so YMMV.


scp needs bash of sh or the restricted shell version. The restricted shells, rbash or rsh, won't let the users leave there own home dir so they can rummage around to their heats content without harm. When the users don't need a prompt you can start a menu from /etc/passwd as their shell. When you need a prompt and access els then own home you can use "screen" to start the bash. Like: screen bash. Just create a script and put the script as shell in the /etc/passwd. Scp can not cope with that and won't work.

This way you can determine exactly who can and can not use scp in a simple way.


I'm not sure why deleting or renaming /usr/bin/scp isn't considered a valid answer, as it directly addresses the original question.

We have restricted servers which exist for interactive shell sessions, but must export files through approved channels, and removing the obvious transfer protocols goes a long way to achieving this goal. Specifically, Windows clients using MobaXterm will get a remote file browser using SFTP by default, but tries SCP as a fallback, and it isn't very obvious that anything is different to the end user.

  • 1
    Because /usr/bin/scp is a client tool, /usr/sbin/sshd being a server counterpart. So, on the server you need to delete /usr/sbin/sshd for that. Commented Apr 17 at 3:10

You must log in to answer this question.