Restricting rsync over ssh
by Juliet Kemp
I recently did some rearranging of our network setup, in part with the explicit aim of removing user logon access to several of the servers (both for security and for performance reasons). In general this has worked out fine - we use NFS so that users can still access all the relevant directories. However, the RAID array is used, among other things, for users to back up their laptops to - which means that the server running the RAID array needs to act as an rsync server.
By default these days, rsync runs over ssh. Which is great, but means that just restricting ssh access to the admin (me!) for the RAID array machine isn't an option; since then rsync too will fail. I wasn't keen on the idea of running it without ssh; not only a security issue, but also because it seemed that would mean having to keep another set of usernames/passwords, rather than relying on LDAP/Kerberos.
The solution I've come up with is slightly clunky but does the trick:
- ssh is allowed, but only for a subset of users (using the AllowUsers directive in
/etc/ssh/sshd_config) - those who've told me they need rsync backup access.
- These users are then added to /etc/password, with the shell set as '/bin/nologin' (thus overriding the LDAP data) (this and the next step are the slightly clunky parts!)
- They're also added to /etc/shadow, with *K* (meaning 'use Kerberos') as the password (maintaining two lots of passwords would be Very Bad).
- /bin/nologin looks like this:
#!/bin/sh # Script to disallow remote login - set as shell in /etc/passwd if (expr "$2" : 'rsync ..server .* .raid' > /dev/null) then if (expr "$2" : '.*;' > /dev/null) then exit else /bin/sh "$@" fi else echo "***********************************" echo "* No login allowed! *" echo "***********************************" exit fi
The trick I used for finding the command that's being sent (which is not the same as the command that you type on the command line) was to first set up /bin/nologin simply as
#!/bin/sh echo $@ > /tmp/command exitand then examine /tmp/command on the rsync server.
Note that this doesn't worry about looking terribly hard for shell escapes (although it does look for anyone trying to pass an extra command in using ; - e.g.
rsync directory/ "server:/data/directory/;rm -rf /" ). I'm using this in a local-access-only setup with a small number of reasonably trusted users, not on a machine that's open to the world at large, so I'm prepared to take more compromises than if the circs were different.
Also note that unfortunately rsync doesn't handle echo statements well - so there is no message to the user if they are misusing rsync (whether deliberately or accidentally). Again, in my case this is fine as the user will just contact me if they're legitimate and behaving legitimately.
Have you considered scponly?
|Why not just use the "command=" option in your users' ~/.ssh/authorized_keys files? See the sshd(8) man page for more info.|
Howard: thanks for that. Unfortunately the server in question is Solaris & there's no version of scponly for Solaris 10. I'll certainly bear it in mind if/when I move to a Linux server for the RAID array; and if I have time may see if I can get it to work on S10.
A number of issues here, the most obvious is that you haven't considered the environment, in particular the path. Note that ssh allows (for the traditional rsh compatibility reasons) environment variables to be passed in (and set up) as part of the session. I'd be worried also about users being able to send up new shell configs (~/.bashrc and suchlike), though this may be OK in this case.