Question #1
My question is, how do I restrict the command to just this SFTP transfer in the public key that is generated?
There are 2 methods for doing this.
1. -- Restricting through sshd
This method involves setting up the SFTP feature within your SSH daemon, sshd
. This is controlled through the /etc/ssh/sshd_config
configuration file. NOTE: This will restrict the user, backup
to only be allowed to SFTP into the server.
# /etc/ssh/sshd_config
Subsystem sftp internal-sftp
## You want to put only certain users (i.e users who belongs to sftpusers
## group) in the chroot jail environment. Add the following lines at the end
## of /etc/ssh/sshd_config
Match User backup
ForceCommand internal-sftp
2. -- Restricting through authorized_keys
This method doesn't involve any changes to the sshd_config
file. You can limit a user + a SSH key to a single command via the command=
feature which you've already mentioned in your question. The trick is in what command you include. You can put the SFTP server in this command=
line, which has the same effect as setting up the SFTP server in your sshd_config
file.
# User backup's $HOME/.ssh/authorized_keys file
command="/usr/libexec/openssh/sftp-server" ssh-dss AAAAC8ghi9ldw== backup@host
NOTE: if the user has write access to ~/.ssh/authorized_keys
, they can read and/or modify it. For example, they could download it, edit it, and reupload it stripping away the commmand=...
, granting him unfettered command access, including the shell. If the user has write access to ~/.ssh
, they could also simply unlink and recreate the file, or chmod
it to write access. Many possible solutions exist, such as putting the ~/.ssh/authorized_keys
files away in a non-user-writable place, such as with:
Match Group sftponly
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
Question #2
And since I am on a dynamic IP address, how do I overcome the "missing known host" problem each time my IP changes?
This is trickier but doable using the from=
feature within the authorized_keys
file as well. Here we're limiting access from only the host, somehost.dyndns.org
.
from="somehost.dyndns.org",command="/usr/libexec/openssh/sftp-server",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-dss AAAAC8ghi9ldw== backup@host
The additional settings after the command=
are equally important, since they'll limit the use of SSH key even further.
breakdown of features
from='hostname1,hostname2,''
- Restricts access from the specified IP or hostname patterns
command='command'
- Runs the specified command after authentication
no-pty
- Does not allocate a pty (does not allow interactive login)
no-port-forwarding
- Does not allow port forwarding
no-X11-forwarding
- user won't be able to remove display X11 GUIs
no-agent-forwarding
- user won't be able to forward through this host to other internal hosts
To get rid of the message about the "missing known hosts" you can add this SSH option to the client when it connects like so:
$ ssh -o StrictHostKeyChecking=no ....
See the man page, ssh_config
for full details about this switch.
Restricting the user's shell
For both solutions above you'll likely want to lock down the backup
user by limiting this user's shell in the /etc/passwd
file as well. Typically you'll want to set it to scponly
, but there are other choices for this as well. See this U&L Q&A titled: "Do you need a shell for SCP?" for ways of doing this.
The use of /sbin/nologin
can also be used if you opt to use the chroot feature from sshd_config
as outlined in #1 above. However if you opt to use the method outlined in #2, then you'll likely have to use scponly
or something else for the user's shell in /etc/passwd
.
BONUS - Extending #2 above
If you need to expose a set of commands for this user you can also do this. Create a script like so, /home/backup/commands.sh
:
#!/bin/sh
case $SSH_ORIGINAL_COMMAND in
"diskspace")
df -h
;;
"dirlist")
ls -1
;;
"apache_restart")
/etc/init.d/apache restart
;;
*)
echo "Unknown command"
esac
You then setup the authorized_keys
file like so:
command="/bin/sh /home/user/commands.sh" ssh-dss AAAAC8ghi9ldw== user@host
The backup
user can then run these commands like so:
# diskspace
$ ssh -q user@remote_host diskspace
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/dev-root 39G 2.2G 35G 6% /
# dirlist
$ ssh -q remote_host dirlist
commands.sh
dump.sql
References